create_bulk_clients_tmp = """
    CREATE TEMPORARY TABLE bulk_clients_tmp (
        id bigserial PRIMARY KEY,
        first_name varchar(256),
        last_name varchar(256),
        phone varchar(16),
        email varchar(64),
        comment text
    ) ON COMMIT DROP;

    CREATE TEMPORARY TABLE merged_bulk_clients_tmp (
        id bigserial PRIMARY KEY,
        first_name varchar(256),
        last_name varchar(256),
        phone varchar(16),
        email varchar(64),
        comment text
    ) ON COMMIT DROP;
"""

build_indexes_on_bulk_clients_tmp = """
    CREATE INDEX bulk_clients_tmp_phone_idx
        ON bulk_clients_tmp USING btree (phone);
    CREATE INDEX bulk_clients_tmp_email_idx
        ON bulk_clients_tmp USING btree (email);

    CREATE INDEX merged_bulk_clients_tmp_phone_idx
        ON merged_bulk_clients_tmp USING btree (phone);
    CREATE INDEX merged_bulk_clients_tmp_email_idx
        ON merged_bulk_clients_tmp USING btree (email);
"""

merge_input_bulk_clients = """
    WITH merged_by_phone AS (
        SELECT
            max(id) AS id,
            (array_remove(array_agg(first_name ORDER BY id DESC), NULL))[1]
                AS first_name,
            (array_remove(array_agg(last_name ORDER BY id DESC), NULL))[1]
                AS last_name,
            phone,
            (array_remove(array_agg(email ORDER BY id DESC), NULL))[1] AS email,
            (array_remove(array_agg(comment ORDER BY id DESC), NULL))[1] AS comment
        FROM bulk_clients_tmp
        WHERE phone IS NOT NULL
        GROUP BY phone

        UNION ALL

        SELECT id, first_name, last_name, phone, email, comment
        FROM bulk_clients_tmp
        WHERE phone IS NULL
    ),
    merged_by_email AS (
        SELECT
            max(id) AS id,
            (array_remove(array_agg(first_name ORDER BY id DESC), NULL))[1]
                AS first_name,
            (array_remove(array_agg(last_name ORDER BY id DESC), NULL))[1]
                AS last_name,
            (array_remove(array_agg(phone ORDER BY id DESC), NULL))[1] AS phone,
            email,
            (array_remove(array_agg(comment ORDER BY id DESC), NULL))[1] AS comment
        FROM merged_by_phone
        WHERE email IS NOT NULL
            AND phone IS NULL
        GROUP BY email

        UNION ALL

        SELECT id, first_name, last_name, phone, email, comment
        FROM merged_by_phone
        WHERE email IS NULL
            OR phone IS NOT NULL
    )
    INSERT INTO merged_bulk_clients_tmp (
        first_name, last_name, phone, email, comment
    )
    SELECT first_name, last_name, phone, email, comment
    FROM merged_by_email
"""


create_clients = """
    -- matching for merge
    WITH matched_by_phone AS (
        SELECT
            mbct.id,
            max(clients.id) AS client_id,
            (array_agg(mbct.first_name))[1] as first_name,
            (array_agg(mbct.last_name))[1] as last_name,
            (array_agg(mbct.phone))[1] as phone,
            (array_agg(mbct.email))[1] as email,
            (array_agg(mbct.comment))[1] as comment
        FROM clients
        JOIN merged_bulk_clients_tmp mbct ON clients.phone = mbct.phone
        WHERE clients.biz_id = $1
        GROUP BY mbct.id
    ),
    matched_by_email AS (
        SELECT
            mbct.id,
            max(clients.id) AS client_id,
            (array_agg(mbct.first_name))[1] as first_name,
            (array_agg(mbct.last_name))[1] as last_name,
            (array_agg(mbct.phone))[1] as phone,
            (array_agg(mbct.email))[1] as email,
            (array_agg(mbct.comment))[1] as comment
        FROM clients
        JOIN merged_bulk_clients_tmp mbct ON clients.email = mbct.email
        WHERE clients.biz_id = $1
            AND mbct.phone IS NULL
        GROUP BY mbct.id
    ),
    -- merge
    merged_by_phone AS (
        UPDATE clients
        SET first_name = coalesce(mbp.first_name, clients.first_name),
            last_name = coalesce(mbp.last_name, clients.last_name),
            email = coalesce(mbp.email, clients.email),
            comment = coalesce(mbp.comment, clients.comment),
            labels = CASE
                WHEN $3::text IS NULL THEN labels
                ELSE ARRAY(
                    SELECT DISTINCT unnest(array_append(labels, $3))
                    ORDER BY 1
                )
            END
        FROM matched_by_phone AS mbp
        WHERE mbp.client_id = clients.id
        returning clients.*
    ),
    merged_by_email AS (
        UPDATE clients
        SET first_name = coalesce(mbe.first_name, clients.first_name),
            last_name = coalesce(mbe.last_name, clients.last_name),
            phone = coalesce(mbe.phone, clients.phone),
            comment = coalesce(mbe.comment, clients.comment),
            labels = CASE
                WHEN $3::text IS NULL THEN labels
                ELSE ARRAY(
                    SELECT DISTINCT unnest(array_append(labels, $3))
                    ORDER BY 1
                )
            END
        FROM matched_by_email mbe
        WHERE mbe.client_id = clients.id
        returning clients.*
    ),
    revisions_for_merged AS (
        INSERT INTO client_revisions(
                client_id, biz_id, source, phone, email,
                passport_uid, first_name, last_name, gender, comment
            )
        SELECT id, biz_id, $2, phone, email, passport_uid, first_name,
            last_name, gender, comment
        FROM (
            SELECT * FROM merged_by_phone
            UNION ALL
            SELECT * FROM merged_by_email
        ) _q
    ),
    -- creation
    new_clients AS (
        INSERT INTO clients (
            biz_id, first_name, last_name, phone, email, comment, labels
        )
        SELECT $1, first_name, last_name, phone, email, comment,
            CASE
                WHEN $3::text IS NULL THEN '{}'
                ELSE ARRAY[$3]
            END
        FROM merged_bulk_clients_tmp
        WHERE id NOT IN (
            SELECT id FROM matched_by_phone
            UNION ALL
            SELECT id FROM matched_by_email
        )
        returning *
    ),
    new_revisions AS (
        INSERT INTO client_revisions (
            client_id, biz_id, source, first_name, last_name,
            phone, email, comment
        )
        SELECT id, $1, $2, first_name, last_name, phone, email, comment
        FROM new_clients
    )
    SELECT (
        (SELECT count(*) FROM merged_by_phone) +
        (SELECT count(*) FROM merged_by_email)
    ) AS total_merged,
    (SELECT count(*) FROM new_clients) AS total_created
"""
