"""
WB analytics — воронка продаж Wildberries (sales-funnel), mp_id=1.

POST /api/analytics/v3/sales-funnel/products — один запрос, все товары.
Период: последние 7 дней (selectedPeriod), metric_date = сегодня (конец периода).
Rate limit: 3 req/min (seller-analytics-api). Порт из V2 wildberries.collect_analytics.
intake: gwptd_intake.wb_analytics; legacy dual-write → mp_analytics_daily (BaseCollector).
"""
from __future__ import annotations

import json
from datetime import timedelta
from pathlib import Path
from typing import Any, Iterator

from collectors.base import BaseCollector
from config import MP_WB_FBO, WILDBERRIES
from db import get_cursor

MAPPING_PATH = Path(__file__).resolve().parent.parent / "mappings/wb/analytics.yaml"


class WbAnalyticsCollector(BaseCollector):
    endpoint_code = "wb.analytics"
    mp_id = MP_WB_FBO
    collector_class = "WbAnalyticsCollector"
    # Реализует _row_to_params_list — строки идут пачкой, а не по одной.
    supports_batch_write = True
    legacy_mapping_path = str(MAPPING_PATH)  # legacy dual-write → mp_analytics_daily (через BaseCollector)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        if WILDBERRIES.get("token"):
            self.session.headers["Authorization"] = f"Bearer {WILDBERRIES['token']}"

    def fetch(self) -> Iterator[tuple[Any, int, str | None]]:
        url = f"{WILDBERRIES['analytics_url']}/api/analytics/v3/sales-funnel/products"
        body = {
            "selectedPeriod": {
                "start": (self.today - timedelta(days=7)).isoformat(),
                "end": self.today.isoformat(),
            },
            "nmIds": [],  # пусто = все товары
        }
        status, data = self.http("POST", url, json=body)
        if status != 200 or not isinstance(data, dict):
            self.logger.error(f"WB analytics failed: status={status}")
            return
        products = (data.get("data") or {}).get("products") or []
        self.logger.info(f"WB analytics: {len(products)} products")
        for item in products:
            vc = (item.get("product") or {}).get("vendorCode")
            yield item, status, str(vc) if vc else None

    def _ensure_table(self, cur) -> None:
        cur.execute("""
            CREATE TABLE IF NOT EXISTS gwptd_intake.wb_analytics (
              id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
              payload_id BIGINT UNSIGNED NOT NULL,
              mp_id TINYINT UNSIGNED NOT NULL DEFAULT 1,
              metric_date DATE,
              nm_id BIGINT,
              offer_id VARCHAR(255),
              product_name VARCHAR(512),
              views INT, cart_adds INT, orders_count INT,
              orders_sum DECIMAL(14,2), buyout_count INT, buyout_sum DECIMAL(14,2),
              buyout_pct DECIMAL(8,2), cart_conversion DECIMAL(8,2), order_conversion DECIMAL(8,2),
              raw_json JSON,
              collected_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
              KEY idx_offer (offer_id), KEY idx_date (metric_date), KEY idx_payload (payload_id)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
        """)

    def _insert_sql(self) -> str:
        return """
            INSERT INTO gwptd_intake.wb_analytics
              (payload_id, mp_id, metric_date, nm_id, offer_id, product_name,
               views, cart_adds, orders_count, orders_sum, buyout_count, buyout_sum,
               buyout_pct, cart_conversion, order_conversion, raw_json)
            VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
        """

    def _row_to_params_list(
        self, payload_id: int, item: Any
    ) -> list[tuple[int, tuple, str | None]]:
        product = item.get("product") or {}
        sel = (item.get("statistic") or {}).get("selected") or {}
        conv = sel.get("conversions") or {}
        source_key = str(product.get("vendorCode") or "")
        params = (
            payload_id, self.mp_id, self.today,
            product.get("nmID"), product.get("vendorCode"), product.get("name"),
            sel.get("openCount"), sel.get("cartCount"), sel.get("orderCount"),
            sel.get("orderSum"), sel.get("buyoutCount"), sel.get("buyoutSum"),
            conv.get("buyoutPercent"), conv.get("addToCartPercent"), conv.get("cartToOrderPercent"),
            json.dumps(item, ensure_ascii=False),
        )
        return [(payload_id, params, source_key)]

    def parse_and_store(self, payload_id: int, item: Any) -> None:
        """Однострочный fallback (для обратной совместимости)."""
        with get_cursor() as cur:
            self._ensure_table(cur)
            cur.execute(self._insert_sql(), self._row_to_params_list(payload_id, item)[0][1])
        # legacy dual-write → mp_analytics_daily выполняет BaseCollector._write_legacy
