"""
Pydantic v2 response schemas for the V2 Betting Engine.
Strictly mirrors the NestJS DTO contract for SingleMatchPredictionPackage.
"""

from __future__ import annotations

from typing import Any

from pydantic import BaseModel, Field


# ── Sub-models ──────────────────────────────────────────────────────────────


class MatchInfo(BaseModel):
    match_id: str
    match_name: str = ""
    home_team: str = ""
    away_team: str = ""
    league: str = ""
    match_date_ms: int = 0


class DataQuality(BaseModel):
    label: str = Field(default="MEDIUM", description="HIGH | MEDIUM | LOW")
    score: float = Field(default=0.5, ge=0.0, le=1.0)
    flags: list[str] = Field(default_factory=list)
    home_lineup_count: int = 0
    away_lineup_count: int = 0


class RiskAssessment(BaseModel):
    level: str = Field(default="MEDIUM", description="LOW | MEDIUM | HIGH | EXTREME")
    score: float = Field(default=0.0, ge=0.0, le=1.0)
    is_surprise_risk: bool = False
    surprise_type: str | None = None
    warnings: list[str] = Field(default_factory=list)


class PickDetail(BaseModel):
    market: str = Field(..., description="MS, OU25, BTTS, DC, HT, HTFT, etc.")
    pick: str = Field(..., description="1, X, 2, Over, Under, Yes, No, 1/1, etc.")
    probability: float = Field(..., ge=0.0, le=1.0)
    confidence: float = Field(default=0.0, description="Percentage 0-100")
    odds: float | None = Field(default=None, gt=0.0)
    raw_confidence: float = 0.0
    calibrated_confidence: float = 0.0
    min_required_confidence: float = 0.0
    edge: float = Field(default=0.0, description="Model prob minus implied prob")
    play_score: float = Field(default=0.0, ge=0.0, le=100.0)
    playable: bool = False
    bet_grade: str = Field(default="PASS", description="A | B | C | PASS")
    stake_units: float = Field(default=0.0, ge=0.0)
    decision_reasons: list[str] = Field(default_factory=list)


class BetAdvice(BaseModel):
    playable: bool = False
    suggested_stake_units: float = 0.0
    reason: str = "no_playable_pick"


class BetSummaryRow(BaseModel):
    market: str
    pick: str
    raw_confidence: float = 0.0
    calibrated_confidence: float = 0.0
    bet_grade: str = "PASS"
    playable: bool = False
    stake_units: float = 0.0
    play_score: float = 0.0
    reasons: list[str] = Field(default_factory=list)


class ScoreScenario(BaseModel):
    score: str
    prob: float


class ScorePrediction(BaseModel):
    ft: str = "0-0"
    ht: str = "0-0"
    xg_home: float = 0.0
    xg_away: float = 0.0
    xg_total: float = 0.0


class EngineBreakdown(BaseModel):
    team: float = 0.0
    player: float = 0.0
    odds: float = 0.0
    referee: float = 0.0


class MarketProbs(BaseModel):
    pick: str = ""
    confidence: float = 0.0
    probs: dict[str, float] = Field(default_factory=dict)


# ── Root Response ───────────────────────────────────────────────────────────


class PredictionResponse(BaseModel):
    """
    Root API contract. Every field matches the NestJS
    `SingleMatchPredictionPackage` DTO exactly.
    """

    model_version: str = "v2.betting_engine"
    match_info: MatchInfo
    data_quality: DataQuality = Field(default_factory=DataQuality)
    risk: RiskAssessment = Field(default_factory=RiskAssessment)
    engine_breakdown: EngineBreakdown = Field(default_factory=EngineBreakdown)
    main_pick: PickDetail | None = None
    value_pick: PickDetail | None = None
    bet_advice: BetAdvice = Field(default_factory=BetAdvice)
    bet_summary: list[BetSummaryRow] = Field(default_factory=list)
    supporting_picks: list[PickDetail] = Field(default_factory=list)
    aggressive_pick: PickDetail | None = None
    scenario_top5: list[ScoreScenario] = Field(default_factory=list)
    score_prediction: ScorePrediction = Field(default_factory=ScorePrediction)
    market_board: dict[str, Any] = Field(default_factory=dict)
    reasoning_factors: list[str] = Field(default_factory=list)
