"""empty message

Revision ID: 4da34e253f23
Revises: f292917fa81c
Create Date: 2020-12-16 14:31:00.194254

"""
import json
import logging
from datetime import datetime

import pytz
import sqlalchemy as sa
from alembic import op

from maps_adv.billing_proxy.lib.db.migration_helpers import data_migration


# revision identifiers, used by Alembic.
revision = "4da34e253f23"
down_revision = "98f0ce4cac52"
branch_labels = None
depends_on = None

_moscow_tz = pytz.timezone("Europe/Moscow")

active_from = _moscow_tz.localize(datetime(2021, 1, 1))
active_to = _moscow_tz.localize(datetime(2021, 12, 31, 23, 59, 59))

comment = "Геомедийные продукты 2021; https://st.yandex-team.ru/GEOPROD-5440"

products_data = [
    {
        "oracle_id": 511018,
        "title": "Геомедийная реклама. Пины по маршруту.",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "60"},
        "currency": "RUB",
        "platforms": ["NAVI", "MAPS"],
        "campaign_type": "PIN_ON_ROUTE",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 17500,
    },
    {
        "oracle_id": 509962,
        "title": "Pins along the route",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "0.9"},
        "currency": "EUR",
        "platforms": ["NAVI"],
        "campaign_type": "PIN_ON_ROUTE",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 510712,
        "title": "Pins along the route",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "1"},
        "currency": "USD",
        "platforms": ["NAVI"],
        "campaign_type": "PIN_ON_ROUTE",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 510732,
        "title": "Геомедийная реклама. Пины по маршруту.",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "320"},
        "currency": "KZT",
        "platforms": ["NAVI"],
        "campaign_type": "PIN_ON_ROUTE",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 112000,
    },
    {
        "oracle_id": 510728,
        "title": "Геомедийная реклама. Пины по маршруту.",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "1.7"},
        "currency": "BYN",
        "platforms": ["NAVI"],
        "campaign_type": "PIN_ON_ROUTE",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 595,
    },
    {
        "oracle_id": 509591,
        "title": "Билборды по маршруту",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "50"},
        "currency": "RUB",
        "platforms": ["NAVI"],
        "campaign_type": "BILLBOARD",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 17500,
    },
    {
        "oracle_id": 509961,
        "title": "Billboards along the route",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "0.75"},
        "currency": "EUR",
        "platforms": ["NAVI"],
        "campaign_type": "BILLBOARD",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 510711,
        "title": "Billboards along the route",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "0.85"},
        "currency": "USD",
        "platforms": ["NAVI"],
        "campaign_type": "BILLBOARD",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 510733,
        "title": "Билборды по маршруту",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "320"},
        "currency": "KZT",
        "platforms": ["NAVI"],
        "campaign_type": "BILLBOARD",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 112000,
    },
    {
        "oracle_id": 510729,
        "title": "Билборды по маршруту",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "1.7"},
        "currency": "BYN",
        "platforms": ["NAVI"],
        "campaign_type": "BILLBOARD",
        "cpm_filters": [
            "rubric_name_common_v2",
            "targeting_type_cascade_except_realty",
        ],
        "service_id": 110,
        "min_budget": 595,
    },
    {
        "oracle_id": 511016,
        "title": "Геомедийная реклама. Баннер",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "220"},
        "currency": "RUB",
        "platforms": ["NAVI"],
        "campaign_type": "ZERO_SPEED_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 17500,
    },
    {
        "oracle_id": 509960,
        "title": "Banner in Yandex.Navigator",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "3.5"},
        "currency": "EUR",
        "platforms": ["NAVI"],
        "campaign_type": "ZERO_SPEED_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 510710,
        "title": "Banner in Yandex.Navigator",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "4"},
        "currency": "USD",
        "platforms": ["NAVI"],
        "campaign_type": "ZERO_SPEED_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 510734,
        "title": "Геомедийная реклама. Баннер",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "1300"},
        "currency": "KZT",
        "platforms": ["NAVI"],
        "campaign_type": "ZERO_SPEED_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 89286,
    },
    {
        "oracle_id": 510730,
        "title": "Геомедийная реклама. Баннер",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "7"},
        "currency": "BYN",
        "platforms": ["NAVI"],
        "campaign_type": "ZERO_SPEED_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 511249,
        "title": "Баннер при построении маршрута",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "220"},
        "currency": "RUB",
        "platforms": ["NAVI"],
        "campaign_type": "OVERVIEW_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 17500,
    },
    {
        "oracle_id": 511778,
        "title": "Banner when building a route",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "3.5"},
        "currency": "EUR",
        "platforms": ["NAVI"],
        "campaign_type": "OVERVIEW_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 511775,
        "title": "Banner when building a route",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "4"},
        "currency": "USD",
        "platforms": ["NAVI"],
        "campaign_type": "OVERVIEW_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 511786,
        "title": "Баннер при построении маршрута",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "1300"},
        "currency": "KZT",
        "platforms": ["NAVI"],
        "campaign_type": "OVERVIEW_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 89286,
    },
    {
        "oracle_id": 511784,
        "title": "Баннер при построении маршрута",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "7"},
        "currency": "BYN",
        "platforms": ["NAVI"],
        "campaign_type": "OVERVIEW_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 509840,
        "title": "Баннер в Метро",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "220"},
        "currency": "RUB",
        "platforms": ["NAVI"],
        "campaign_type": "ROUTE_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 17500,
    },
    {
        "oracle_id": 511777,
        "title": "Banner in the Y.Metro",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "3.5"},
        "currency": "EUR",
        "platforms": ["NAVI"],
        "campaign_type": "ROUTE_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 511774,
        "title": "Banner in the Y.Metro",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "4"},
        "currency": "USD",
        "platforms": ["NAVI"],
        "campaign_type": "ROUTE_BANNER",
        "cpm_filters": ["targeting_type_common"],
        "service_id": 110,
        "min_budget": 500,
    },
    {
        "oracle_id": 510960,
        "title": "Рекомендация маршрута",
        "billing_type": "CPM",
        "billing_data": {"base_cpm": "100"},
        "currency": "RUB",
        "platforms": ["NAVI"],
        "campaign_type": "VIA_POINTS",
        "cpm_filters": ["rubric_name_common"],
        "service_id": 110,
        "min_budget": 17500,
    },
    {
        "oracle_id": 511013,
        "title": "Геомедийная реклама. Иконка в категории. По дням",
        "billing_type": "FIX",
        "billing_data": {"cost": "120000.00", "time_interval": "DAILY"},
        "currency": "RUB",
        "platforms": ["NAVI"],
        "campaign_type": "CATEGORY_SEARCH_PIN",
        "cpm_filters": [],
        "service_id": 110,
        "min_budget": 1680000,
    },
    {
        "oracle_id": 511013,
        "title": "Геомедийная реклама. Иконка в категории. По дням",
        "billing_type": "FIX",
        "billing_data": {"cost": "80000.00", "time_interval": "DAILY"},
        "currency": "RUB",
        "platforms": ["MAPS"],
        "campaign_type": "CATEGORY_SEARCH_PIN",
        "cpm_filters": [],
        "service_id": 110,
        "min_budget": 1120000,
    },
    {
        "oracle_id": 511785,
        "title": "Геомедийная реклама. Иконка в категории. По дням",
        "billing_type": "FIX",
        "billing_data": {"cost": "357.00", "time_interval": "DAILY"},
        "currency": "BYN",
        "platforms": ["NAVI"],
        "campaign_type": "CATEGORY_SEARCH_PIN",
        "cpm_filters": [],
        "service_id": 110,
        "min_budget": 4998,
    },
    {
        "oracle_id": 511788,
        "title": "Геомедийная реклама. Иконка в категории. По дням",
        "billing_type": "FIX",
        "billing_data": {"cost": "57000.00", "time_interval": "DAILY"},
        "currency": "KZT",
        "platforms": ["NAVI"],
        "campaign_type": "CATEGORY_SEARCH_PIN",
        "cpm_filters": [],
        "service_id": 110,
        "min_budget": 798000,
    },
    {
        "oracle_id": 511014,
        "title": "Геомедийная реклама. Иконка в категории.",
        "billing_type": "FIX",
        "billing_data": {"cost": "3600000.00", "time_interval": "MONTHLY"},
        "currency": "RUB",
        "platforms": ["NAVI"],
        "campaign_type": "CATEGORY_SEARCH_PIN",
        "cpm_filters": [],
        "service_id": 110,
        "min_budget": 3600000,
    },
    {
        "oracle_id": 511014,
        "title": "Геомедийная реклама. Иконка в категории.",
        "billing_type": "FIX",
        "billing_data": {"cost": "2400000.00", "time_interval": "MONTHLY"},
        "currency": "RUB",
        "platforms": ["MAPS"],
        "campaign_type": "CATEGORY_SEARCH_PIN",
        "cpm_filters": [],
        "service_id": 110,
        "min_budget": 2400000,
    },
    {
        "oracle_id": 510731,
        "title": "Геомедийная реклама. Иконка в категории.",
        "billing_type": "FIX",
        "billing_data": {"cost": "10000.00", "time_interval": "MONTHLY"},
        "currency": "BYN",
        "platforms": ["NAVI"],
        "campaign_type": "CATEGORY_SEARCH_PIN",
        "cpm_filters": [],
        "service_id": 110,
        "min_budget": 10000,
    },
    {
        "oracle_id": 510731,
        "title": "Геомедийная реклама. Иконка в категории.",
        "billing_type": "FIX",
        "billing_data": {"cost": "1700000.00", "time_interval": "MONTHLY"},
        "currency": "KZT",
        "platforms": ["NAVI"],
        "campaign_type": "CATEGORY_SEARCH_PIN",
        "cpm_filters": [],
        "service_id": 110,
        "min_budget": 1700000,
    },
]

outdated_products = [
    {
        "oracle_id": 510731,
        "title": "Геомедийная реклама. Иконка в категории.",
        "platform": "MAPS",
        "campaign_type": "CATEGORY_SEARCH_PIN",
    },
]


@data_migration
def upgrade():
    con = op.get_bind()

    product_oracle_ids = set(
        product_data["oracle_id"] for product_data in products_data
    )
    existing_products = []
    new_products = []
    for product_data in products_data:
        for platform in product_data["platforms"]:
            result = con.execute(
                sa.text(
                    """
                        SELECT id
                        FROM products
                        WHERE oracle_id = :oracle_id and platform = :platform
                """
                ),
                oracle_id=product_data["oracle_id"],
                platform=platform,
            ).fetchone()

            if result is not None:
                existing_products.append(
                    {"oracle_id": product_data["oracle_id"], "platfrom": platform}
                )
            else:
                new_products.append(
                    {"oracle_id": product_data["oracle_id"], "platfrom": platform}
                )

    # Update existing
    for product_data in products_data:
        for platform in product_data["platforms"]:
            if {
                "oracle_id": product_data["oracle_id"],
                "platfrom": platform,
            } in existing_products:
                con.execute(
                    sa.text(
                        """
                        WITH product_rules AS (
                            SELECT product_rules_versions.*
                            FROM product_rules_versions
                            INNER JOIN (
                                SELECT product_id, max(version) AS version
                                FROM product_rules_versions
                                WHERE product_id IN (
                                    SELECT id FROM products WHERE oracle_id = :oracle_id
                                )
                                GROUP BY product_id) AS product_rules_versions_subq
                            ON product_rules_versions_subq.product_id = product_rules_versions.product_id
                            AND product_rules_versions_subq.version = product_rules_versions.version
                            WHERE :active_from <= coalesce(product_rules_versions.active_to, now())
                            AND :active_from > active_from
                        ),
                        updating AS (
                            UPDATE product_rules_versions
                            SET active_to = :active_from
                            FROM product_rules
                            WHERE product_rules.id = product_rules_versions.id
                        )
                        INSERT INTO product_rules_versions(
                            product_id,
                            version,
                            active_from,
                            active_to,
                            billing_data,
                            min_budget,
                            cpm_filters)
                            SELECT product_id,
                            version + 1 AS version,
                            :active_from,
                            :active_to,
                            :billing_data,
                            0,
                            :cpm_filters
                        FROM product_rules
                    """  # noqa: E501
                    ),
                    oracle_id=product_data["oracle_id"],
                    active_from=active_from,
                    active_to=active_to,
                    billing_data=json.dumps(product_data["billing_data"]),
                    cpm_filters=product_data["cpm_filters"],
                )
            elif {
                "oracle_id": product_data["oracle_id"],
                "platfrom": platform,
            } in new_products:
                con.execute(
                    sa.text(
                        """
                        WITH
                            inserted_product AS (
                                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
                                )
                                VALUES (
                                    :oracle_id,
                                    :title,
                                    :act_text,
                                    :description,
                                    :currency,
                                    :billing_type,
                                    :vat,
                                    :campaign_type,
                                    :platform,
                                    :comment,
                                    TRUE,
                                    TRUE,
                                    (:platforms)::platformtype[],
                                    :service_id
                                )
                                RETURNING id
                            ),
                            inserted_version AS (
                                INSERT INTO product_rules_versions (
                                    product_id,
                                    version,
                                    active_from,
                                    active_to,
                                    billing_data,
                                    min_budget,
                                    cpm_filters
                                )
                                SELECT id,
                                       1,
                                       :active_from,
                                       :active_to,
                                       :billing_data,
                                       :min_budget,
                                       :cpm_filters
                                FROM inserted_product
                            )
                        SELECT 1
                        """  # noqa: E501
                    ),
                    comment=comment,  # noqa: E501
                    currency=product_data["currency"],
                    vat=0.2,
                    oracle_id=product_data["oracle_id"],
                    title=product_data["title"],
                    act_text=product_data["title"],
                    description="{} {}".format(
                        product_data["oracle_id"], product_data["title"]
                    ),
                    billing_type=product_data["billing_type"],
                    campaign_type=product_data["campaign_type"],
                    platform=platform,
                    platforms=[platform],
                    active_from=active_from,
                    active_to=active_to,
                    billing_data=json.dumps(product_data["billing_data"]),
                    cpm_filters=product_data["cpm_filters"],
                    min_budget=product_data["min_budget"],
                    service_id=product_data["service_id"],
                )

    for product_data in outdated_products:
        con.execute(
            sa.text(
                """
            WITH product_rules AS (
                SELECT product_rules_versions.*
                  FROM product_rules_versions
                 INNER JOIN (
                    SELECT product_id, max(version) AS version
                    FROM product_rules_versions
                    WHERE product_id IN (
                        SELECT id FROM products WHERE oracle_id = :oracle_id
                        AND platform=:platform
                    )
                    GROUP BY product_id
                 ) AS product_rules_versions_subq
                       ON product_rules_versions_subq.product_id = product_rules_versions.product_id
                      AND product_rules_versions_subq.version = product_rules_versions.version
                WHERE :active_from <= coalesce(product_rules_versions.active_to, now())
                  AND :active_from > active_from
            )
            UPDATE product_rules_versions
               SET active_to = :active_from
             FROM product_rules
             WHERE product_rules.id = product_rules_versions.id
        """
            ),
            active_from=active_from,
            oracle_id=product_data["oracle_id"],
            platform=product_data["platform"],
        )


def downgrade():
    pass
