"""价格观测落库:一次比价的整批观测幂等写入。

幂等键 = (trace_id, platform, scope)。pricebot 重试 / replay 会重复上报同一 trace,
这里先查该 trace 已存在的 (platform, scope),只插新的——跨方言(PG / SQLite dev)都安全,
不依赖 ON CONFLICT。极端并发下若仍撞唯一约束,IntegrityError 回滚后忽略(本批本就幂等)。
"""
from __future__ import annotations

import logging

from sqlalchemy import select
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session

from app.models.price_observation import PriceObservation
from app.schemas.price_observation import PriceObservationBatchIn

logger = logging.getLogger("shagua.price_obs")


def insert_batch(db: Session, payload: PriceObservationBatchIn) -> tuple[int, int]:
    """写入一次比价的整批观测,返回 (inserted, skipped)。

    skipped = 因 (trace_id, platform, scope) 已存在而幂等跳过的条数。
    """
    if not payload.observations:
        return 0, 0

    # 该 trace 已有的 (platform, scope),用于幂等过滤
    existing: set[tuple[str, str]] = set(
        db.execute(
            select(PriceObservation.platform, PriceObservation.scope).where(
                PriceObservation.trace_id == payload.trace_id
            )
        ).all()
    )

    inserted = 0
    skipped = 0
    for obs in payload.observations:
        key = (obs.platform, obs.scope)
        if key in existing:
            skipped += 1
            continue
        existing.add(key)  # 同批内去重(防 pricebot 同帧给重复平台)
        db.add(
            PriceObservation(
                trace_id=payload.trace_id,
                business_type=payload.business_type,
                platform=obs.platform,
                platform_store_id=obs.platform_store_id,
                store_name=payload.store_name,
                city=payload.city,
                geohash=payload.geohash,
                lng=payload.lng,
                lat=payload.lat,
                is_source=obs.is_source,
                scope=obs.scope,
                price_cents=obs.price_cents,
                coupon_saved_cents=obs.coupon_saved_cents,
                coupon_name=obs.coupon_name,
                store_closed=obs.store_closed,
                rank=obs.rank,
                dishes=payload.dishes,
                attrs=obs.attrs,
                source_device_id=payload.source_device_id,
                source_user_id=payload.source_user_id,
            )
        )
        inserted += 1

    if inserted == 0:
        return 0, skipped

    try:
        db.commit()
    except IntegrityError:
        # 并发下另一个请求刚插了同 (trace,platform,scope) → 唯一约束撞了。
        # 本批本就幂等,回滚后当作全跳过(不重试,失败就失败,见 P0 约定)。
        db.rollback()
        logger.warning(
            "price_observation 并发幂等冲突 trace=%s,本批回滚跳过", payload.trace_id
        )
        return 0, skipped + inserted

    return inserted, skipped
