<?xml version="1.0" encoding="UTF-8"?>
<changelog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="file:/var/app/InputFileSchema.xsd">
    <changeset id="SR-904_track" author="nlittmann" run-always="true">
        <precondition>
            <sqlquery>
                <![CDATA[
                    WITH
                    tuids_with_tiktok_track_rules AS (
                        SELECT DISTINCT(ORCHARD_OBJ_ID)::INTEGER AS tuid
                        FROM FACTS.PROD.HAS_FINGERPRINT_RULE
                        WHERE ORCHARD_OBJ_TYPE = 'Track'
                        AND SERVICE = 'tiktok'
                    ),
                    candidate_tuids AS (
                        SELECT tuid FROM tuids_with_tiktok_track_rules
                    ),
                    service_ids_to_names AS (
                        SELECT *
                        FROM VALUES (453, 'youtube') AS services (service_id, service_name)
                    ),
                    territories_in_registry AS (
                        SELECT territory FROM FACTS.PROD.REGISTRY_TERRITORIES
                    ),
                    territories_in_registry_count AS (
                        SELECT count(*) AS count FROM territories_in_registry
                    ),
                    release_level_dms_star_carveouts AS (
                        SELECT
                            sitn.service_name,
                            tr.id AS tuid,
                            rmr.customer_master_master_id IS NOT NULL AS star_carveout
                        FROM
                            candidate_tuids ct
                            FULL OUTER JOIN service_ids_to_names sitn
                            LEFT JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.TRACK tr ON ct.tuid = tr.id
                            LEFT JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.RELEASE_DMS_MASTER_RESTRICTION rmr
                            ON tr.release_id = rmr.release_id AND sitn.service_id = rmr.customer_master_master_id AND rmr.DISTRIBUTION_TYPE_ID = 1
                        GROUP BY 1, 2, 3
                    ),
                    release_level_country_carveouts AS (
                        SELECT
                            sitn.service_name,
                            tr.id AS tuid,
                            cou.COUNTRY_CODE AS territory_carveouts
                        FROM
                            candidate_tuids ct
                            FULL OUTER JOIN service_ids_to_names sitn
                            INNER JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.TRACK tr ON ct.tuid = tr.id
                            INNER JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.RELEASE_TERRITORY_RESTRICTION rtr ON tr.release_id = rtr.release_id
                            INNER JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.COUNTRY cou ON cou.ID = rtr.COUNTRY_ID
                            INNER JOIN territories_in_registry tir ON tir.territory = cou.COUNTRY_CODE
                        GROUP BY 1, 2, 3
                    ),
                    release_level_dms_country_carveouts AS (
                        SELECT
                            sitn.service_name,
                            tr.id AS tuid,
                            cou.COUNTRY_CODE AS territory_carveouts
                        FROM
                            candidate_tuids ct
                            INNER JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.TRACK tr ON ct.tuid = tr.id
                            INNER JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.RELEASE_DMS_RESTRICTION rr ON tr.release_id = rr.release_id
                            INNER JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.CUSTOMER_MASTER cm ON cm.CUSTOMER_ID = rr.DMS_CUSTOMER_ID
                            INNER JOIN service_ids_to_names sitn ON sitn.service_id = cm.CUSTOMER_MASTER_MASTER_ID
                            INNER JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.COUNTRY cou ON cou.ID = cm.TERRITORY
                            INNER JOIN territories_in_registry tir ON tir.territory = cou.COUNTRY_CODE
                        GROUP BY 1, 2, 3
                    ),
                    registry_locked_territories AS (
                        SELECT
                            sitn.service_name,
                            ct.tuid,
                            reg_lock.territory AS territory_carveouts
                        FROM
                            candidate_tuids ct
                            FULL OUTER JOIN service_ids_to_names sitn
                            INNER JOIN ORCHARD_APP_REPORTING_V2.ART_RELATIONS_PROD_ART_RELATIONS.TRACK tr ON ct.tuid = tr.id
                            INNER JOIN FACTS.PROD.REGISTRY_LOCKED reg_lock ON tr.isrc = reg_lock.isrc
                            INNER JOIN territories_in_registry tir ON tir.territory = reg_lock.territory
                        GROUP BY 1, 2, 3
                    ),
                    inverse_of_registry AS (
                        SELECT
                            sitn.service_name,
                            candidate_tuids.tuid,
                            territories_in_registry.territory AS territory_carveouts
                        FROM candidate_tuids
                        CROSS JOIN territories_in_registry
                        LEFT JOIN FACTS.PROD.REGISTRY registry
                        ON candidate_tuids.tuid = registry.tuid
                        AND territories_in_registry.territory = registry.territory
                        FULL OUTER JOIN service_ids_to_names sitn
                        WHERE registry.tuid IS NULL
                        GROUP BY 1, 2, 3
                    ),
                    combined_territories AS (
                        SELECT * FROM (
                            SELECT * FROM release_level_country_carveouts
                            UNION
                            SELECT * FROM release_level_dms_country_carveouts
                            UNION
                            SELECT * FROM registry_locked_territories
                            UNION
                            SELECT * FROM inverse_of_registry
                        )
                        WHERE territory_carveouts IN (SELECT * FROM territories_in_registry)
                        GROUP BY 1, 2, 3
                    ),
                    are_all_territories_carved_out AS (
                        SELECT
                            service_name,
                            tuid,
                            IFF(count(*) = (SELECT count FROM territories_in_registry_count), TRUE, FALSE) AS star_carveout
                        FROM combined_territories
                        GROUP BY 1, 2
                    ),
                    should_be_rules AS (
                        SELECT
                            ft.tuid,
                            IFF(rldsc.star_carveout OR aatco.star_carveout, tir.territory, ct.territory_carveouts) AS territory_carveouts
                        FROM
                            candidate_tuids ft
                            INNER JOIN combined_territories ct ON ft.tuid = ct.tuid
                            INNER JOIN release_level_dms_star_carveouts rldsc ON ft.tuid = rldsc.tuid AND ct.service_name = rldsc.service_name
                            INNER JOIN are_all_territories_carved_out aatco ON ct.tuid = aatco.tuid AND ct.service_name = aatco.service_name
                            FULL OUTER JOIN territories_in_registry tir
                        GROUP BY ALL
                    ),
                    existing_territory_rules AS (
                        SELECT
                            TRY_TO_NUMBER(ORCHARD_OBJ_ID) AS tuid,
                            TERRITORY AS territory
                        FROM FACTS.PROD.HAS_FINGERPRINT_RULE
                        WHERE ORCHARD_OBJ_TYPE = 'Track'
                        AND SERVICE = 'youtube'
                        AND POLICY = 'carveout'
                        AND TERRITORY != '*'
                        AND TRY_TO_NUMBER(ORCHARD_OBJ_ID) IN (SELECT tuid FROM candidate_tuids)
                    ),
                    tuids_to_sync AS (
                        SELECT DISTINCT tuid FROM (
                            SELECT sbr.tuid FROM should_be_rules sbr
                            LEFT JOIN existing_territory_rules etr ON sbr.tuid = etr.tuid AND sbr.territory_carveouts = etr.territory
                            WHERE etr.tuid IS NULL
                            UNION
                            SELECT etr.tuid FROM existing_territory_rules etr
                            LEFT JOIN should_be_rules sbr ON etr.tuid = sbr.tuid AND etr.territory = sbr.territory_carveouts
                            WHERE sbr.tuid IS NULL
                        )
                        LIMIT 150000
                    ),
                    rules_to_add AS (
                        SELECT sbr.tuid, sbr.territory_carveouts AS territory
                        FROM should_be_rules sbr
                        INNER JOIN tuids_to_sync tts ON sbr.tuid = tts.tuid
                        LEFT JOIN existing_territory_rules etr ON sbr.tuid = etr.tuid AND sbr.territory_carveouts = etr.territory
                        WHERE etr.tuid IS NULL
                    ),
                    rules_to_delete AS (
                        SELECT etr.tuid, etr.territory
                        FROM existing_territory_rules etr
                        INNER JOIN tuids_to_sync tts ON etr.tuid = tts.tuid
                        LEFT JOIN should_be_rules sbr ON etr.tuid = sbr.tuid AND etr.territory = sbr.territory_carveouts
                        WHERE sbr.tuid IS NULL
                    ),
                    sync_operations AS (
                        SELECT
                            tts.tuid,
                            COALESCE(LISTAGG(DISTINCT rta.territory, ',') WITHIN GROUP (ORDER BY rta.territory), '') AS territories_to_add,
                            COALESCE(LISTAGG(DISTINCT rtd.territory, ',') WITHIN GROUP (ORDER BY rtd.territory), '') AS territories_to_delete
                        FROM tuids_to_sync tts
                        LEFT JOIN rules_to_add rta ON tts.tuid = rta.tuid
                        LEFT JOIN rules_to_delete rtd ON tts.tuid = rtd.tuid
                        GROUP BY tts.tuid
                    )
                    SELECT * FROM sync_operations;
                ]]>
            </sqlquery>
        </precondition>
        <cypherquery>
            <![CDATA[
                WITH event,
                    CASE WHEN event.TERRITORIES_TO_ADD <> ''
                         THEN split(event.TERRITORIES_TO_ADD, ',') ELSE [] END AS add_list,
                    CASE WHEN event.TERRITORIES_TO_DELETE <> ''
                         THEN split(event.TERRITORIES_TO_DELETE, ',') ELSE [] END AS del_list
                MATCH (track:Track {id: event.TUID})
                WITH track, add_list, del_list
                CALL {
                    WITH track, add_list
                    UNWIND add_list AS territory
                    MATCH (rule:FingerprintRule {territory: territory, service: 'youtube', policy: 'carveout'})
                    MERGE (track)-[rel:HAS_FINGERPRINT_RULE]->(rule)
                    ON CREATE SET
                        rel.createdAt = datetime(),
                        rel.createdBy = '179_1',
                        rel.lastModifiedAt = datetime(),
                        rel.lastModifiedBy = '179_1'
                    RETURN count(rel) AS created
                }
                CALL {
                    WITH track, del_list
                    UNWIND del_list AS territory
                    MATCH (track)-[old:HAS_FINGERPRINT_RULE]->(rule:FingerprintRule {territory: territory, service: 'youtube', policy: 'carveout'})
                    SET
                        old.lastModifiedAt = datetime(),
                        old.lastModifiedBy = '179_1'
                    WITH old
                    CALL apoc.refactor.setType(old, 'DELETED_HAS_FINGERPRINT_RULE') YIELD output
                    RETURN count(output) AS deleted
                }
                RETURN created, deleted
            ]]>
        </cypherquery>
    </changeset>
</changelog>
