find_product_by_id = """
    SELECT
        products.id,
        products.oracle_id,
        products.service_id,
        products.title,
        products.act_text,
        products.description,
        products.currency,
        products.billing_type,
        products.vat_value,
        products.campaign_type,
        products.platforms,
        products.comment,
        products.available_for_agencies,
        products.available_for_internal,
        products.type,
        active_from_subq.active_from AS active_from,
        active_to_subq.active_to AS active_to,
        coalesce(active_version_subq.version, latest_version_subq.version) AS version,
        coalesce(active_version_subq.billing_data, latest_version_subq.billing_data) AS billing_data,
        coalesce(active_version_subq.min_budget, latest_version_subq.min_budget) AS min_budget,
        coalesce(active_version_subq.cpm_filters, latest_version_subq.cpm_filters) AS cpm_filters,
        (CASE
            WHEN array_agg(product_client_restrictions.client_id) = ARRAY[NULL]::bigint[]
            THEN NULL
            ELSE array_agg(product_client_restrictions.client_id)
        END) AS dedicated_client_ids
    FROM products
    LEFT JOIN product_client_restrictions
        ON products.id = product_client_restrictions.product_id
    LEFT JOIN (
        SELECT MIN(active_from) AS active_from
        FROM product_rules_versions
        WHERE product_id = $1
    ) AS active_from_subq ON TRUE
    LEFT JOIN (
        SELECT active_to
        FROM product_rules_versions
        WHERE product_id = $1
        ORDER BY active_to DESC NULLS FIRST
        LIMIT 1
    ) AS active_to_subq ON TRUE
    LEFT JOIN (
        SELECT
            active_from,
            active_to,
            version,
            billing_data,
            min_budget,
            cpm_filters
        FROM product_rules_versions
        WHERE product_id = $1
            AND active_from <= now()
            AND (active_to IS NULL OR active_to >= now())
        ORDER BY active_from, id
        LIMIT 1
    ) AS active_version_subq ON TRUE
    LEFT JOIN (
        SELECT
            version,
            billing_data,
            min_budget,
            cpm_filters
        FROM product_rules_versions
        WHERE product_id = $1
        ORDER BY active_to DESC, id
        LIMIT 1
    ) AS latest_version_subq ON TRUE
    WHERE products.id = $1
    GROUP BY
        products.id,
        active_from_subq.active_from,
        active_to_subq.active_to,
        active_version_subq.version,
        active_version_subq.billing_data,
        active_version_subq.min_budget,
        active_version_subq.cpm_filters,
        latest_version_subq.version,
        latest_version_subq.billing_data,
        latest_version_subq.min_budget,
                latest_version_subq.cpm_filters
"""  # noqa: E501


list_products = """
    SELECT
        products.id,
        products.oracle_id,
        products.service_id,
        products.title,
        products.act_text,
        products.description,
        products.currency,
        products.billing_type,
        products.vat_value,
        products.campaign_type,
        products.platforms,
        products.comment,
        products.available_for_agencies,
        products.available_for_internal,
        products.type,
        active_from_subq.active_from AS active_from,
        active_to_subq.active_to AS active_to,
        coalesce(active_version_subq.version, latest_version_subq.version) AS version,
        coalesce(active_version_subq.billing_data, latest_version_subq.billing_data) AS billing_data,
        coalesce(active_version_subq.min_budget, latest_version_subq.min_budget) AS min_budget,
        coalesce(active_version_subq.cpm_filters, latest_version_subq.cpm_filters) AS cpm_filters
    FROM products
    LEFT JOIN (
        SELECT product_id, MIN(active_from) AS active_from
        FROM product_rules_versions
        GROUP BY product_id
    ) AS active_from_subq ON active_from_subq.product_id = products.id
    LEFT JOIN (
        SELECT
            product_id,
            active_to,
            rank() OVER (PARTITION BY product_id ORDER BY active_to DESC NULLS FIRST) AS rnk
        FROM product_rules_versions
    ) AS active_to_subq ON active_to_subq.product_id = products.id
        AND active_to_subq.rnk = 1
    LEFT JOIN (
        SELECT
            product_id,
            active_from,
            active_to,
            version,
            billing_data,
            min_budget,
            cpm_filters,
            rank() OVER (PARTITION BY product_id ORDER BY active_from, id) AS rnk
        FROM product_rules_versions
        WHERE active_from <= now()
            AND (active_to IS NULL OR active_to >= now())
    ) AS active_version_subq ON active_version_subq.product_id = products.id
        AND active_version_subq.rnk = 1
    LEFT JOIN (
        SELECT
            product_id,
            version,
            billing_data,
            min_budget,
            cpm_filters,
            rank() OVER (PARTITION BY product_id ORDER BY active_from DESC, id) AS rnk
        FROM product_rules_versions
    ) AS latest_version_subq ON latest_version_subq.product_id = products.id
        AND latest_version_subq.rnk = 1
    WHERE products.service_id = ANY($1)
    GROUP BY
        products.id,
        active_from_subq.active_from,
        active_to_subq.active_to,
        active_version_subq.version,
        active_version_subq.billing_data,
        active_version_subq.min_budget,
        active_version_subq.cpm_filters,
        latest_version_subq.version,
        latest_version_subq.billing_data,
        latest_version_subq.min_budget,
        latest_version_subq.cpm_filters
    ORDER BY products.id
"""  # noqa: E501

find_product_active_version = """
    SELECT
        id,
        product_id,
        version,
        active_from,
        active_to,
        billing_data,
        min_budget,
        cpm_filters
    FROM product_rules_versions
    WHERE product_id = $1
        AND $2 >= active_from AND (active_to IS NULL OR $2 < active_to)
    ORDER BY active_from
    LIMIT 1
"""

list_products_by_params = """
    SELECT
        products.id,
        products.oracle_id,
        products.service_id,
        products.title,
        products.act_text,
        products.description,
        products.currency,
        products.billing_type,
        products.vat_value,
        products.campaign_type,
        products.platforms,
        products.comment,
        products.available_for_agencies,
        products.available_for_internal,
        products.type,
        active_from_subq.active_from AS active_from,
        active_to_subq.active_to AS active_to,
        coalesce(active_version_subq.version, latest_version_subq.version) AS version,
        coalesce(active_version_subq.billing_data, latest_version_subq.billing_data) AS billing_data,
        coalesce(active_version_subq.min_budget, latest_version_subq.min_budget) AS min_budget,
        coalesce(active_version_subq.cpm_filters, latest_version_subq.cpm_filters) AS cpm_filters,
        (product_client_restrictions.client_id IS NOT NULL) AS is_client_specific
    FROM products
    LEFT JOIN product_client_restrictions
        ON products.id = product_client_restrictions.product_id
    LEFT JOIN (
        SELECT product_id, MIN(active_from) AS active_from
        FROM product_rules_versions
        GROUP BY product_id
    ) AS active_from_subq ON active_from_subq.product_id = products.id
    LEFT JOIN (
        SELECT
            product_id,
            active_to,
            rank() OVER (PARTITION BY product_id ORDER BY active_to DESC NULLS FIRST) AS rnk
        FROM product_rules_versions
    ) AS active_to_subq ON active_to_subq.product_id = products.id
        AND active_to_subq.rnk = 1
    LEFT JOIN (
        SELECT
            product_id,
            active_from,
            active_to,
            version,
            billing_data,
            min_budget,
            cpm_filters,
            rank() OVER (PARTITION BY product_id ORDER BY active_from, id) AS rnk
        FROM product_rules_versions
        WHERE active_from <= $4
            AND (active_to IS NULL OR active_to > $4)
    ) AS active_version_subq ON active_version_subq.product_id = products.id
        AND active_version_subq.rnk = 1
    LEFT JOIN (
        SELECT
            product_id,
            version,
            billing_data,
            min_budget,
            cpm_filters,
            rank() OVER (PARTITION BY product_id ORDER BY active_from DESC, id) AS rnk
        FROM product_rules_versions
    ) AS latest_version_subq ON latest_version_subq.product_id = products.id
        AND latest_version_subq.rnk = 1
    WHERE
        ($1 <@ products.platforms AND $1 @> products.platforms) -- Checks for being identical sets
        AND products.campaign_type = $2
        AND products.currency = $3
        AND active_from_subq.active_from <= $4
        AND (active_to_subq.active_to IS NULL OR active_to_subq.active_to > $4)
        AND (
            products.type = 'REGULAR'
            OR product_client_restrictions.client_id = $5
        )
        AND ($6::integer IS NULL OR products.service_id = $6::integer)
    GROUP BY
        products.id,
        product_client_restrictions.client_id,
        active_from_subq.active_from,
        active_to_subq.active_to,
        active_version_subq.version,
        active_version_subq.billing_data,
        active_version_subq.min_budget,
        active_version_subq.cpm_filters,
        latest_version_subq.version,
        latest_version_subq.billing_data,
        latest_version_subq.min_budget,
        latest_version_subq.cpm_filters
    ORDER BY products.id
"""  # noqa: E501

retrieve_product_params = """
    SELECT oracle_id, platforms, campaign_type, currency
    FROM products
    WHERE id = $1
"""

list_all_products_versions = """
    SELECT product_id, version, active_from, active_to, billing_data :: json,
        min_budget, cpm_filters, products.billing_type as billing_type
    FROM product_rules_versions
    LEFT JOIN products ON product_rules_versions.product_id = products.id
    WHERE products.service_id = ANY($1)
"""

list_all_product_versions_by_product = """
    SELECT product_id, version, active_from, active_to, billing_data :: json,
        min_budget, cpm_filters, products.billing_type as billing_type
    FROM product_rules_versions
    LEFT JOIN products ON product_rules_versions.product_id = products.id
    WHERE product_id = $1
"""

list_clients_bound_to_product = """
    SELECT client_id, contract_id
    FROM product_client_restrictions
    WHERE product_id = $1
"""

list_clients_bound_to_overlapping_products = """
    SELECT client_id
    FROM product_client_restrictions
    INNER JOIN products ON product_client_restrictions.product_id = products.id
    WHERE client_id = ANY($1)
        AND products.campaign_type = $2
        AND products.id <> $3
        AND ($4 <@ products.platforms AND $4 @> products.platforms) -- Checks for being identical sets
        AND products.currency = $5
"""

bind_client_to_product = """
    INSERT INTO product_client_restrictions(product_id, client_id, contract_id)
    VALUES {}
    ON CONFLICT DO NOTHING
"""


unbind_client_from_product = """
    DELETE FROM product_client_restrictions
    WHERE {}
    RETURNING client_id
"""

insert_product = """
    INSERT INTO products (
        oracle_id,
        title,
        act_text,
        description,
        currency,
        billing_type,
        vat_value,
        campaign_type,
        platform,
        comment,
        available_for_agencies,
        available_for_internal,
        platforms,
        service_id,
        type
    ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, TRUE, TRUE, $11, $12, $13)
    RETURNING *;
"""

insert_product_version = """
    INSERT INTO product_rules_versions (
        product_id,
        version,
        active_from,
        active_to,
        billing_data,
        min_budget,
        cpm_filters
    ) VALUES ($1,
        COALESCE(
            (SELECT MAX(version) + 1 FROM product_rules_versions WHERE product_id = $1),
            1),
        $2, $3, $4::jsonb, $5, $6);
"""

update_product = """
    UPDATE products
    SET title = $2, act_text = $3, description = $4, vat_value = $5, comment = $6
    WHERE id = $1;
"""


remove_product_versions = """
    DELETE FROM product_rules_versions WHERE product_id = $1;
"""


check_for_duplicate_products = """
    SELECT DISTINCT prv.product_id as product_id
    FROM product_rules_versions prv
    INNER JOIN products p ON p.id = prv.product_id
    WHERE p.type = 'REGULAR'
        AND p.campaign_type = $1
        AND p.currency = $2
        AND p.service_id = $3
        AND (prv.active_to IS NULL OR prv.active_to > $4)
        AND ($5::timestamp with time zone IS NULL OR
            prv.active_from < $5::timestamp with time zone)
        AND ($6::integer IS NULL OR p.id <> $6::integer)
    ORDER BY prv.product_id;
"""
