"""admin「领券数据」看板 schemas:汇总卡 + 按天/小时趋势 + 逐条领券明细。

数据源 coupon_session(一次领券一行)。耗时单位 ms(前端按需折秒);均值/分位只统计 completed。
"""
from __future__ import annotations

from datetime import datetime

from pydantic import BaseModel, Field


class CouponDataSummary(BaseModel):
    """汇总卡:发起/完成数 + 耗时均值与分位(P5/P50/P95/P99,基于 completed 的 elapsed_ms)。"""

    started_count: int = Field(..., description="发起数(区间内所有领券 session)")
    completed_count: int = Field(..., description="完成数(status=completed)")
    avg_elapsed_ms: int | None = Field(None, description="平均耗时(ms,仅 completed;无数据为空)")
    p5_ms: int | None = Field(None, description="耗时 5 分位(ms)")
    p50_ms: int | None = Field(None, description="耗时 50 分位(ms,中位数)")
    p95_ms: int | None = Field(None, description="耗时 95 分位(ms)")
    p99_ms: int | None = Field(None, description="耗时 99 分位(ms)")
    # 平台粒度成功率(见 docs/guides/领券成功率指标-设计与埋点.md):基数含全部 session。
    full_success_count: int = Field(0, description="整单成功数(勾选平台全部领到的 session 数)")
    full_success_rate: float | None = Field(None, description="整单成功率②=整单成功数/发起数;无数据为空")
    point_success_count: int = Field(0, description="成功平台点位数(Σ 每次成功的平台数)")
    point_total_count: int = Field(0, description="总平台点位数(Σ 每次勾选平台数;空勾选=全领三档)")
    point_success_rate: float | None = Field(None, description="点位成功率③=成功点位/总点位;无数据为空")
    per_platform: dict[str, float | None] = Field(
        default_factory=dict,
        description="分平台点位成功率 {平台id: rate|None};恒含美团/淘宝/京东三档,区间内无人勾选的平台为 None",
    )


class CouponDataDaily(BaseModel):
    """按天趋势(全量,不受分页影响):柱=发起/完成数,线=平均耗时。"""

    date: str = Field(..., description="北京时间 YYYY-MM-DD")
    started_count: int
    completed_count: int
    avg_elapsed_ms: int | None = Field(None, description="当天平均耗时(ms,仅 completed)")


class CouponDataHourly(BaseModel):
    """按北京小时(0–23)趋势(单日 granularity=hour 时非空)。"""

    hour: int = Field(..., description="北京时间小时 0–23")
    started_count: int
    completed_count: int
    avg_elapsed_ms: int | None = None


class CouponPointDetail(BaseModel):
    """一次领券任务中的单券点位结果。"""

    coupon_id: str
    coupon_name: str | None = None
    status: str = Field(..., description="success / already_claimed / failed / skipped")
    reason: str | None = None


class CouponDataRow(BaseModel):
    """一条领券明细(一次领券任务)。"""

    id: int = Field(..., description="coupon_session 主键(抽屉 rowKey 用)")
    trace_id: str
    user_id: int | None = None
    user_phone: str | None = Field(None, description="手机号(admin 展示;匿名领券/查不到为空)")
    user_nickname: str | None = Field(None, description="昵称")
    status: str = Field(..., description="started / completed / failed / abandoned")
    platforms: list[str] | None = Field(None, description="发起勾选平台")
    origin_package: str | None = Field(None, description="发起来源 App 包名;null=App 内(傻瓜比价首页)发起")
    elapsed_ms: int | None = Field(None, description="全程耗时(ms)")
    platform_elapsed: dict[str, int] | None = Field(
        None, description="各平台耗时 {meituan-waimai/taobao-shanguang/jd-waimai: ms}"
    )
    device_model: str | None = None
    rom: str | None = None
    app_env: str | None = None
    started_at: datetime = Field(..., description="发起时刻(明细「时间」列)")
    claimed_count: int | None = None
    point_success_count: int | None = Field(
        None, description="本次成功单券数(success+already_claimed);无逐券事件为空"
    )
    point_total_count: int | None = Field(
        None, description="本次尝试单券数(success+already_claimed+failed,不含 skipped);无逐券事件为空"
    )
    trace_url: str | None = Field(None, description="pricebot 公网 trace 链接(仅 completed 有);admin 渲染可点链接,无则显示可复制 trace_id")
    ad_revenue_yuan: float = Field(
        0.0, description="本次领券看的信息流广告预估收益(元);按 trace_id 聚合 ad_ecpm_record"
    )


class CouponDataOut(BaseModel):
    """领券数据看板响应:汇总卡 + 趋势 + 明细分页。"""

    date_from: str
    date_to: str
    summary: CouponDataSummary
    daily: list[CouponDataDaily] = Field(default_factory=list, description="按天趋势(全量)")
    hourly: list[CouponDataHourly] = Field(
        default_factory=list, description="按小时趋势(单日 hour 粒度时非空)"
    )
    total: int = Field(..., description="明细总条数(全量,不受分页)")
    items: list[CouponDataRow] = Field(..., description="逐条领券明细(当前页)")


class CouponPointDetailsOut(BaseModel):
    """单次领券任务的逐券点位结果，供点击分数时按需加载。"""

    trace_id: str
    items: list[CouponPointDetail] = Field(default_factory=list)


class CouponUserRecordsOut(BaseModel):
    """某用户全部领券记录(点手机号抽屉用):total=该用户领券总次数,items=记录列表(UserRecordsDrawer 渲染)。"""

    items: list[CouponDataRow]
    total: int


class CouponSlotRow(BaseModel):
    """按券成功率一行(§13):粒度=设备-天;成功率=成功/(成功+失败),skipped 排除。"""

    coupon_id: str
    coupon_name: str | None = None
    platform: str | None = Field(None, description="美团/淘宝/京东 平台 id;无法识别为空")
    tried: int = Field(..., description="尝试数(success+already_claimed+failed 的设备-天数)")
    succeeded: int = Field(..., description="成功数(success+already_claimed)")
    success_rate: float | None = Field(None, description="成功率=成功/尝试")


class CouponSlotsOut(BaseModel):
    """按券成功率表响应(§13)。"""

    date_from: str
    date_to: str
    items: list[CouponSlotRow]
