/*
 * This file is part of ***  M y C o R e  ***
 * See http://www.mycore.de/ for details.
 *
 * MyCoRe is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MyCoRe is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MyCoRe.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.mycore.mcr.neo4j.datamodel.metadata.neo4jutil;

import static org.mycore.mcr.neo4j.datamodel.metadata.neo4jutil.MCRNeo4JUtil.removeIllegalRelationshipTypeCharacters;

import java.util.concurrent.ThreadLocalRandom;

public record Neo4JRelation(String sourceNodeID, String targetNodeID, String relationshipType) {

    @Override
    public String toString() {
        return "Neo4JRelation{" +
            "sourceNode='" + sourceNodeID + '\'' +
            ", targetNode='" + targetNodeID + '\'' +
            ", relationshipType='" + relationshipType + '\'' +
            '}';
    }

    /**
     * Appends the current query with a directed relation between the current node 'a' and a target node 'b'.
     * Since node references needs to be unique within a query, node 'b' will be extended with a random number.
     * In Case node 'b' doesn't already exist it will be generated.
     * The relationshipType will be filtered of all illegal characters.
     *
     * sample sub query:
     * MERGE (b12345 {id:'MCRID_TARGET_ID'})
     * ON CREATE
     *   SET b12345:AutoGenerated , b12345.id='MCRID_TARGET_ID'
     *
     * MERGE (a)-[:relationshipType]->(b12345)
     *
     *
     * @return a sub query containing a relation between two nodes
     */
    public String toAppendQuery() {
        StringBuilder sbQuery = new StringBuilder();
        Long random = ThreadLocalRandom.current().nextLong(Long.MAX_VALUE);
        sbQuery.append("MERGE (b").append(random).append(" {id: '").append(targetNodeID).append("'})\n")
            .append("ON CREATE\n")
            .append("  SET b").append(random).append(":AutoGenerated").append(" , b").append(random)
            .append(".id='")
            .append(targetNodeID).append("'\n");

        String filteredType = removeIllegalRelationshipTypeCharacters(relationshipType);

        sbQuery.append("MERGE (a)-[:").append(filteredType).append("]->(b").append(random)
            .append(")\n");

        return sbQuery.toString();
    }

    /**
     * Generates a query with a directed relation between the current node 'a' and a target node 'b'.
     * Since node references needs to be unique within a query, node 'b' will be extended with a random number.
     * In Case node 'a' and/or 'b' doesn't already exist they will be generated.
     * The relationshipType will be filtered of all illegal characters.
     *
     * sample sub query:
     * MERGE (a {id:'MCRID_SOURCE_ID'})
     *        * ON CREATE
     *        *   SET a:AutoGenerated , a.id='MCRID_SOURCE_ID'
     * MERGE (b12345 {id:'MCRID_TARGET_ID'})
     * ON CREATE
     *   SET b12345:AutoGenerated , b12345.id='MCRID_TARGET_ID'
     *
     * MERGE (a)-[:relationshipType]->(b12345)
     *
     *
     * @return a full query containing a relation between two nodes
     */
    public String toFullQuery() {
        StringBuilder sbQuery = new StringBuilder();
        Long random = ThreadLocalRandom.current().nextLong(Long.MAX_VALUE);
        sbQuery.append("MERGE (a").append(random).append(" {id: '").append(sourceNodeID).append("'})\n")
            .append("ON CREATE\n")
            .append("  SET a").append(random).append(":AutoGenerated").append(" , a").append(random)
            .append(".id='")
            .append(sourceNodeID).append("'\n");
        sbQuery.append("MERGE (b").append(random).append(" {id: '").append(targetNodeID).append("'})\n")
            .append("ON CREATE\n")
            .append("  SET b").append(random).append(":AutoGenerated").append(" , b").append(random)
            .append(".id='")
            .append(targetNodeID).append("'\n");

        String filteredType = removeIllegalRelationshipTypeCharacters(relationshipType);

        sbQuery.append("MERGE (a").append(random).append(")-[:").append(filteredType).append("]->(b").append(random)
            .append(")\n");

        return sbQuery.toString();
    }
}
