list_existing_order_ids = """
    SELECT coalesce(array_agg(id), ARRAY[]::bigint[])
    FROM orders
    WHERE id = ANY($1::bigint[]) AND hidden = FALSE
"""

_list_orders = """
    SELECT
        orders.id,
        orders.external_id,
        orders.service_id,
        orders.title,
        orders.created_at,
        orders.client_id,
        orders.agency_id,
        orders.contract_id,
        orders.product_id,
        orders.act_text,
        orders.text,
        orders.comment,
        orders."limit",
        orders.consumed,
        orders.tid,
        products.campaign_type,
        products.currency,
        products.platforms,
        products.type
    FROM orders
    LEFT JOIN products
        ON orders.product_id = products.id
    WHERE {}
    ORDER BY orders.created_at DESC
"""

find_order_by_id = _list_orders.format("orders.id = $1 AND hidden = FALSE")

find_order_by_external_id = _list_orders.format(
    "orders.external_id = $1 AND hidden = FALSE"
)

list_orders_by_ids = _list_orders.format(
    "orders.id = ANY($1::bigint[]) AND hidden = FALSE"
)

retrieve_order_id_by_external_id = "SELECT id FROM orders WHERE external_id = $1"

list_agency_orders = _list_orders.format(
    """
    ($1::integer IS NULL AND orders.agency_id IS NULL OR orders.agency_id = $1)
    AND
    ($2::integer IS NULL OR orders.client_id = $2)
    AND hidden = FALSE
"""
)

list_client_orders = _list_orders.format(
    """
    orders.client_id = $1::integer AND hidden = FALSE
    """
)

retrieve_order_ids_for_account = """
    SELECT orders.id as order_id
    FROM orders
    INNER JOIN clients ON orders.client_id = clients.id
    WHERE clients.account_manager_id = $1 AND orders.hidden = FALSE
"""

list_orders_stats = """
    SELECT id, ("limit" - consumed) AS balance
    FROM orders
    WHERE id = ANY($1::bigint[]) AND hidden = FALSE
"""

list_positive_balance_order_ids = """
    SELECT coalesce(array_agg(id), ARRAY[]::bigint[])
    FROM
    (
        SELECT orders.id, hidden
        FROM orders
        JOIN products ON orders.product_id = products.id
        WHERE "limit" > consumed AND products.billing_type <> 'FIX'

        UNION

        SELECT orders.id, hidden
        FROM orders
        JOIN products p ON orders.product_id = p.id
        JOIN product_rules_versions prv ON prv.product_id = p.id
        WHERE p.billing_type = 'FIX'
            AND prv.active_from <= now()
            AND (prv.active_to IS NULL OR prv.active_to >= now())
            AND "limit" > consumed
            AND ("limit" - consumed) >= CAST(prv.billing_data ->> 'cost' as numeric(24, 10))
    ) subq
    WHERE ($1::bigint[] IS NULL OR id = ANY($1::bigint[]))
            AND hidden = FALSE
"""

insert_order = """
    WITH next_id AS (SELECT nextval('orders_id_seq') AS id)
    INSERT INTO orders (
        id,
        external_id,
        service_id,
        title,
        act_text,
        text,
        comment,
        client_id,
        agency_id,
        contract_id,
        product_id
    )
    SELECT id, COALESCE($1, id), $2, $3, $4, $5, $6, $7, $8, $9, $10
    FROM next_id
    RETURNING
        id,
        external_id,
        service_id,
        created_at,
        tid,
        title,
        act_text,
        text,
        comment,
        client_id,
        agency_id,
        contract_id,
        product_id,
        "limit",
        consumed
"""

update_order = """
    UPDATE orders
    SET title = $2, text = $3, comment = $4
    WHERE id = $1
"""

list_order_rows_by_ids = """
    SELECT *
    FROM orders
    WHERE id = ANY($1::bigint[])
"""

_upsert_order_data = """
    INSERT INTO orders (
        id,
        external_id,
        service_id,
        created_at,
        tid,
        title,
        act_text,
        text,
        comment,
        client_id,
        agency_id,
        contract_id,
        product_id,
        "limit",
        consumed
    )
    VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
    ON CONFLICT (id) DO UPDATE SET {}
"""

upsert_order_consumed = _upsert_order_data.format("consumed = excluded.consumed")

upsert_order_limit_and_tid = _upsert_order_data.format(
    """ "limit" = excluded."limit", tid = excluded.tid """
)

insert_order_log = """
    INSERT INTO order_logs (order_id, op_type, amount, consumed, "limit", billed_due_to)
    VALUES ($1, $2, $3, $4, $5, $6)
"""

lock_and_return_orders_balance_by_ids = """
    SELECT id, ("limit" - consumed) AS balance
    FROM orders
    WHERE id = ANY($1::bigint[])
    FOR UPDATE
"""

lock_and_return_orders_rows_by_ids = """
    SELECT *
    FROM orders
    WHERE id = ANY($1::bigint[])
    FOR UPDATE
"""


list_orders_operations_summary = """
    WITH
        ops_summary AS (
            SELECT
                order_id,
                SUM(amount) FILTER ( WHERE op_type = 'DEBIT' ) AS completion,
                SUM(amount) FILTER ( WHERE op_type = 'CREDIT' ) AS consumption
            FROM order_logs
            WHERE coalesce(billed_due_to, created_at) < $1
            AND coalesce(billed_due_to, created_at) >= $2
            GROUP BY order_id
        ),
        child_orders_completion AS (
            SELECT
                orders.parent_order_id,
                SUM(order_logs.amount) AS completion
            FROM orders
            LEFT JOIN order_logs ON orders.id = order_logs.order_id
            WHERE
                orders.parent_order_id IS NOT NULL
                AND order_logs.op_type = 'DEBIT'
                AND coalesce(order_logs.billed_due_to, order_logs.created_at) < $1
                AND coalesce(order_logs.billed_due_to, order_logs.created_at) >= $2
            GROUP BY orders.parent_order_id
        )
    SELECT
        id AS order_id,
        external_id AS external_order_id,
        coalesce(ops_summary.completion, 0.0) AS completion,
        (
            CASE
                WHEN orders.parent_order_id IS NULL
                    THEN coalesce(ops_summary.consumption, 0.0) - coalesce(child_orders_completion.completion, 0.0)
                ELSE (coalesce(ops_summary.completion, 0.0))
            END
        ) AS consumption
    FROM orders
    LEFT JOIN ops_summary ON orders.id = ops_summary.order_id
    LEFT JOIN child_orders_completion ON orders.id = child_orders_completion.parent_order_id
    WHERE orders.created_at < $1 and orders.service_id = $3
    ORDER BY orders.id
"""  # noqa: E501

debits_with_bill_due_to_exist = """
    SELECT EXISTS(
        SELECT 1
        FROM order_logs
        WHERE billed_due_to = $1
    )
"""

list_orders_debits_for_billed_due_to = """
    SELECT order_id, amount
    FROM order_logs
    WHERE billed_due_to = $1
        AND op_type = 'DEBIT'
    ORDER BY order_id
"""

list_orders_debits = """
    SELECT order_id, amount, billed_due_to
    FROM order_logs
    WHERE op_type = 'DEBIT'
        AND order_id = ANY($1::bigint[])
        AND billed_due_to > $2
    ORDER BY billed_due_to
"""
