insert_cpm = """
    WITH cpm_rows AS (
        INSERT INTO billing_cpm (cost, budget, daily_budget, auto_daily_budget)
        VALUES ($1, $2, $3, $4)
        RETURNING id
    )
    INSERT INTO campaign_billing (cpm_id)
    SELECT id FROM cpm_rows
    RETURNING id
"""
insert_cpa = """
    WITH cpa_rows AS (
        INSERT INTO billing_cpa (cost, budget, daily_budget, auto_daily_budget)
        VALUES ($1, $2, $3, $4)
        RETURNING id
    )
    INSERT INTO campaign_billing (cpa_id)
    SELECT id FROM cpa_rows
    RETURNING id
"""
insert_fix = """
    WITH fix_rows AS (
        INSERT INTO billing_fix (time_interval, cost)
        VALUES ($1, $2)
        RETURNING id
    )
    INSERT INTO campaign_billing (fix_id)
    SELECT id FROM fix_rows
    RETURNING id
"""

_insert_cpm = """
    INSERT INTO billing_cpm (cost, budget, daily_budget, auto_daily_budget)
    VALUES ($2, $3, $4, $5)
    RETURNING id, 'CPM' AS type
"""
_insert_cpa = """
    INSERT INTO billing_cpa (cost, budget, daily_budget, auto_daily_budget)
    VALUES ($2, $3, $4, $5)
    RETURNING id, 'CPA' AS type
"""
_insert_fix = """
    INSERT INTO billing_fix (time_interval, cost)
    VALUES ($2, $3)
    RETURNING id, 'FIX' AS type
"""
_replace_billing = """
    WITH
        created_concrete_billing_row AS ({}),
        old_values AS (
            SELECT cpm_id, cpa_id, fix_id
            FROM campaign_billing
            WHERE id = (SELECT billing_id AS id FROM campaign WHERE id = $1)
        ),
        update_billing AS (
            UPDATE campaign_billing
            SET
                fix_id = (CASE WHEN created_concrete_billing_row.type = 'FIX' THEN created_concrete_billing_row.id END),
                cpm_id = (CASE WHEN created_concrete_billing_row.type = 'CPM' THEN created_concrete_billing_row.id END),
                cpa_id = (CASE WHEN created_concrete_billing_row.type = 'CPA' THEN created_concrete_billing_row.id END)
            FROM created_concrete_billing_row
            WHERE campaign_billing.id = (SELECT billing_id AS id FROM campaign WHERE id = $1)
        ),
        delete_old_cpm AS (DELETE FROM billing_cpm USING old_values WHERE id = old_values.cpm_id),
        delete_old_cpa AS (DELETE FROM billing_cpa USING old_values WHERE id = old_values.cpa_id),
        delete_old_fix AS (DELETE FROM billing_fix USING old_values WHERE id = old_values.fix_id)
    SELECT 1
"""  # noqa: E501

replace_billing_with_cpm = _replace_billing.format(_insert_cpm)
replace_billing_with_cpa = _replace_billing.format(_insert_cpa)
replace_billing_with_fix = _replace_billing.format(_insert_fix)

create_campaigns_charged_sums_tmp_table = """
CREATE TEMPORARY TABLE campaigns_charged_sums_tmp (
    campaign_id BIGINT PRIMARY KEY UNIQUE,
    charged NUMERIC(20, 6)
)
ON COMMIT DROP
"""

refresh_campaigns_auto_daily_budgets = """
WITH
active_campaigns AS (
    SELECT
           id,
           billing_cpm_id,
           billing_cpa_id,
           days_to_end,
           budget,
           charged,
           GREATEST(0, CEIL(((budget - charged) / days_to_end) * 100) / 100) AS daily_budget
    FROM (
        SELECT
                campaign.id as id,

                (
                    (campaign.end_datetime AT TIME ZONE campaign.timezone)::date
                    - GREATEST(
                        timezone(campaign.timezone, $1),
                        campaign.start_datetime AT TIME ZONE campaign.timezone
                    )::date
                ) + 1 AS days_to_end,

                billing_cpm.id AS billing_cpm_id,
                billing_cpa.id AS billing_cpa_id,

                coalesce(dashboard.charged, 0) AS charged,
                coalesce(billing_cpm.budget, billing_cpa.budget) AS budget

        FROM campaign
            LEFT JOIN campaigns_charged_sums_tmp AS dashboard ON dashboard.campaign_id = campaign.id
            LEFT JOIN campaign_billing ON campaign_billing.id = campaign.billing_id
            LEFT JOIN billing_cpm ON billing_cpm.id = campaign_billing.cpm_id
            LEFT JOIN billing_cpa ON billing_cpa.id = campaign_billing.cpa_id

        WHERE campaign.id = ANY($2)
    ) AS campaign_budget_subq
    WHERE days_to_end > 0
),

update_cpm as (
    UPDATE billing_cpm
    SET daily_budget = active_campaigns.daily_budget

    FROM active_campaigns
    WHERE billing_cpm.id = active_campaigns.billing_cpm_id
      AND active_campaigns.charged < billing_cpm.budget
      AND billing_cpm.daily_budget <> active_campaigns.daily_budget

    RETURNING active_campaigns.id
),

update_cpa as (
    UPDATE billing_cpa
    SET daily_budget = active_campaigns.daily_budget

    FROM active_campaigns
    WHERE billing_cpa.id = active_campaigns.billing_cpa_id
      AND active_campaigns.charged < billing_cpa.budget
      AND billing_cpa.daily_budget <> active_campaigns.daily_budget

    RETURNING active_campaigns.id
)

SELECT * FROM update_cpm

UNION ALL
SELECT * FROM update_cpa
"""  # noqa: E501
