MERGE (np:NrProduct:NrOwnership { upc: $upc })
ON MATCH SET
    np.name = $name,
    np.code = $code,
    np.externalId =
        CASE
            WHEN $externalId IS NULL THEN np.externalId
            WHEN np.externalId IS NULL THEN [$externalId]
            WHEN $externalId IN np.externalId THEN np.externalId
            ELSE np.externalId + $externalId
        END,
    np.format = $format,
    np.pLineYear = $pLineYear,
    np.pLineLabel = $pLineLabel,
    np.contentType = $contentType,
    np.salesStartDate = date(datetime({ epochMillis: apoc.date.parse($salesStartDate,'ms','dd-MMM-yyyy') })),
    np.lastModifiedAt = datetime(),
    np.lastModifiedBy = "graphql-neighbouring-rights/createNrOwnershipProduct/" + $identityId,
    np.version = $version,
    np.subType = $subType,
    np.imprint = $imprint,
    np.displayArtistName = $displayArtistName,
    np.manuallyOverwritten = $manuallyOverwritten
ON CREATE SET
    np.id = randomUUID(),
    np.name = $name,
    np.code = $code,
    np.externalId =
        CASE
            WHEN $externalId IS NULL THEN np.externalId
            ELSE [$externalId]
        END,
    np.format = $format,
    np.pLineYear = $pLineYear,
    np.pLineLabel = $pLineLabel,
    np.contentType = $contentType,
    np.salesStartDate = date(datetime({ epochMillis: apoc.date.parse($salesStartDate,'ms','dd-MMM-yyyy') })),
    np.createdAt = datetime(),
    np.createdBy = "graphql-neighbouring-rights/createNrOwnershipProduct/" + $identityId,
    np.lastModifiedAt = datetime(),
    np.lastModifiedBy = "graphql-neighbouring-rights/createNrOwnershipProduct/" + $identityId,
    np.version = $version,
    np.subType = $subType,
    np.imprint = $imprint,
    np.displayArtistName = $displayArtistName,
    np.manuallyOverwritten = $manuallyOverwritten
WITH np

CALL apoc.lock.nodes([np])

OPTIONAL MATCH (np)-[oldRel:HAS_PRIMARY_ARTIST|HAS_FEATURED_ARTIST]->(oldParticipant:NrParticipant:NrOwnership)
WITH np, collect(oldRel) as oldRelations, collect(oldParticipant) as oldParticipants

UNWIND $primaryArtists as primaryArtist
OPTIONAL MATCH (primaryParticipant:NrParticipant:NrOwnership {name: primaryArtist})
CALL apoc.util.validate(primaryParticipant IS NULL, 'invalid-primary-artist %s', [primaryArtist])
WITH np, oldRelations, oldParticipants, collect(primaryParticipant) as newParticipants

CALL {
    WITH np
    UNWIND $featuredArtists as featuredArtist
    OPTIONAL MATCH (featuredParticipant:NrParticipant:NrOwnership {name: featuredArtist})
    CALL apoc.util.validate(featuredParticipant IS NULL, 'invalid-featured-artist %s', [featuredArtist])
    RETURN collect(featuredParticipant) as newFtParticipants
}

CALL apoc.lock.nodes(oldParticipants + newParticipants + newFtParticipants)

FOREACH (oldRelation IN oldRelations |
    DELETE oldRelation
)
WITH np, newParticipants, newFtParticipants

UNWIND newParticipants as newParticipant
MERGE (np)-[primaryRel:HAS_PRIMARY_ARTIST]->(newParticipant)
SET
    primaryRel.lastModifiedAt = datetime(),
    primaryRel.lastModifiedBy = "graphql-neighbouring-rights/createNrOwnershipProduct/" + $identityId
WITH np, newFtParticipants

FOREACH (newFtParticipant IN newFtParticipants |
    MERGE (np)-[featuredRel:HAS_FEATURED_ARTIST]->(newFtParticipant)
        SET
            featuredRel.lastModifiedAt = datetime(),
            featuredRel.lastModifiedBy = "graphql-neighbouring-rights/createNrOwnershipProduct/" + $identityId
)

RETURN np.id
