#!/usr/bin/env python3
"""
enrich_prices.py — детект изменения цены: вчера vs позавчера.

Логика:
  - Сегодня тянем текущие цены по SKU через discounts-prices-api.
  - В рабочей папке держим кэш .wb-daily-drops.cache/prices_<date>.json.
  - Сравниваем сегодняшний снапшот с предыдущим (по дате анализируемой даты — 1 день).
  - Если разница > 3% — флаг price_changed с дельтой.
  - На первом прогоне кэша нет → флаг "no_history".

Хранится только цена со скидкой и СПП-цена (если есть).
"""
from __future__ import annotations

import argparse
import json
import os
import sys
import time
from datetime import date, timedelta
from pathlib import Path

import requests

URL = "https://discounts-prices-api.wildberries.ru/api/v2/list/goods/filter"
MAX_RETRIES = 5
PRICE_CHANGE_THRESHOLD_PCT = 3.0


def log(msg: str) -> None:
    print(f"[prices] {msg}", file=sys.stderr)


def get_jwt() -> str:
    jwt = os.environ.get("WB_ANALYTICS_JWT")
    if not jwt:
        sys.exit(3)
    return jwt


def fetch_prices(jwt: str) -> dict[int, dict[str, float]] | None:
    headers = {"Authorization": jwt}
    out: dict[int, dict[str, float]] = {}
    offset = 0
    while True:
        params = {"limit": 1000, "offset": offset}
        for attempt in range(MAX_RETRIES):
            try:
                r = requests.get(URL, headers=headers, params=params, timeout=60)
            except requests.RequestException as exc:
                log(f"  conn: {exc}")
                time.sleep(5); continue
            if r.status_code in (401, 403):
                log(f"  {r.status_code} no access; skip")
                return None
            if r.status_code == 429:
                time.sleep(60); continue
            if r.status_code != 200:
                log(f"  HTTP {r.status_code}: {r.text[:200]}")
                time.sleep(5); continue
            data = r.json()
            goods = (data.get("data") or {}).get("listGoods", [])
            for g in goods:
                nm = g.get("nmID")
                if not nm:
                    continue
                # WB v2 list/goods: цена в копейках price * (1 - discount/100); spp-price отдельно
                price = g.get("sizes", [{}])[0].get("price", 0) or 0
                disc = g.get("discount", 0) or 0
                final = price * (1 - disc / 100)
                out[nm] = {
                    "price_no_spp": final,
                    "spp_price": g.get("sizes", [{}])[0].get("clubDiscountedPrice") or final,
                }
            if len(goods) < 1000:
                return out
            offset += 1000
            break
        else:
            return out
        time.sleep(6)  # 10 req/min
    return out


def main() -> int:
    p = argparse.ArgumentParser()
    p.add_argument("--insights", required=True)
    p.add_argument("--cache-dir", default=".wb-daily-drops.cache")
    args = p.parse_args()

    with open(args.insights, encoding="utf-8") as f:
        insights = json.load(f)
    target_date = date.fromisoformat(insights["target_date"])
    cache_dir = Path(args.cache_dir)
    cache_dir.mkdir(parents=True, exist_ok=True)

    today_iso = (target_date + timedelta(days=1)).isoformat()
    prev_iso = target_date.isoformat()
    today_cache = cache_dir / f"prices_{today_iso}.json"
    prev_cache = cache_dir / f"prices_{prev_iso}.json"

    jwt = get_jwt()
    prices = fetch_prices(jwt)
    if prices is None:
        log("Skipped: no scope or hard error")
        for section in ("drops", "growths", "oos_candidates"):
            for s in insights.get(section, []):
                s.setdefault("enrichment", {})["price"] = {"flag": "NO_DATA"}
        with open(args.insights, "w", encoding="utf-8") as f:
            json.dump(insights, f, ensure_ascii=False, indent=2)
        return 0

    log(f"  fetched prices for {len(prices)} SKUs")
    with open(today_cache, "w", encoding="utf-8") as f:
        json.dump(prices, f, ensure_ascii=False)

    prev = None
    if prev_cache.exists():
        with open(prev_cache, encoding="utf-8") as f:
            prev = json.load(f)

    for section in ("drops", "growths", "oos_candidates"):
        for s in insights.get(section, []):
            nm = str(s["nmID"])
            today_p = prices.get(int(nm)) or prices.get(nm)
            if not today_p:
                s.setdefault("enrichment", {})["price"] = {"flag": "no_data_for_sku"}
                continue
            spp = today_p.get("spp_price") or today_p.get("price_no_spp", 0)
            if not prev:
                s.setdefault("enrichment", {})["price"] = {"spp_price": spp, "flag": "no_history"}
                continue
            prev_p = (prev.get(nm) or prev.get(str(nm)) or {})
            prev_spp = prev_p.get("spp_price") or prev_p.get("price_no_spp", 0)
            if prev_spp == 0:
                s.setdefault("enrichment", {})["price"] = {"spp_price": spp, "flag": "no_history"}
                continue
            delta_pct = (spp - prev_spp) / prev_spp * 100
            flag = "price_changed" if abs(delta_pct) >= PRICE_CHANGE_THRESHOLD_PCT else "no_change"
            s.setdefault("enrichment", {})["price"] = {
                "spp_price": spp,
                "prev_spp_price": prev_spp,
                "delta_pct": round(delta_pct, 2),
                "flag": flag,
            }

    with open(args.insights, "w", encoding="utf-8") as f:
        json.dump(insights, f, ensure_ascii=False, indent=2)
    return 0


if __name__ == "__main__":
    sys.exit(main())
