"""
Expert Recommendation Engine (Senior Level)
============================================
Evaluates ALL markets, classifies by risk, and ensures NO "empty" recommendations.
Prioritizes user safety by clearly labeling risk levels.
"""

from dataclasses import dataclass, field
from typing import List, Optional, Any, Dict
from .base_calculator import BaseCalculator, CalculationContext
from .match_result_calculator import MatchResultPrediction
from .over_under_calculator import OverUnderPrediction
from .risk_assessor import RiskAnalysis


@dataclass
class ExpertPick:
    market_type: str
    pick: str
    probability: float
    confidence: float
    odds: float
    edge: float  # Expected value percentage
    
    # Risk Classification
    risk_level: str  # SAFE, MEDIUM, RISKY, SURPRISE
    reasoning: str   # Why this pick? (e.g., "High xG support", "Value detected")

@dataclass
class ExpertResult:
    main_pick: ExpertPick
    safe_alternative: Optional[ExpertPick]
    value_picks: List[ExpertPick]
    surprise_picks: List[ExpertPick]
    market_summary: Dict[str, float] # {market: probability}


class ExpertRecommender(BaseCalculator):
    def calculate(self,  # type: ignore[override]
                  ctx: CalculationContext,
                  ms_res: MatchResultPrediction,
                  ou_res: OverUnderPrediction,
                  risk: RiskAnalysis) -> ExpertResult:

        odds_data = ctx.odds_data
        all_picks: List[ExpertPick] = []

        # ─── 1. Helper to Evaluate Pick ───
        def evaluate(market: str, pick: str, prob: float, odd_key: str):
            odd_val = float(odds_data.get(odd_key, 0))
            # If odd is missing/low, estimate it via probability (Kelly-ish estimation)
            if odd_val <= 1.01:
                odd_val = round(1.0 / (prob + 0.05), 2) # Conservative estimation
                reasoning = "Derived (No market odd)"
            else:
                reasoning = "Market Confirmed"

            implied = 1.0 / odd_val
            edge = (prob - implied) * 100

            # ─── Risk Classification ───
            if prob >= 0.75 and odd_val <= 1.45:
                level = "SAFE"
            elif edge > 5.0:
                level = "VALUE"
            elif odd_val >= 2.50 and prob >= 0.35:
                level = "SURPRISE"
            else:
                level = "MEDIUM"

            all_picks.append(ExpertPick(
                market_type=market, pick=pick, probability=prob,
                confidence=prob * 100, odds=odd_val, edge=edge,
                risk_level=level, reasoning=reasoning
            ))

        # ─── 2. Evaluate All Major Markets ───
        # MS
        evaluate("MS", ms_res.ms_pick, 
                 ms_res.ms_home_prob if ms_res.ms_pick == "1" else (ms_res.ms_away_prob if ms_res.ms_pick == "2" else ms_res.ms_draw_prob),
                 f"ms_{ms_res.ms_pick.lower()}")
        
        # Double Chance
        evaluate("DC", ms_res.dc_pick,
                 ms_res.dc_1x_prob if ms_res.dc_pick == "1X" else (ms_res.dc_x2_prob if ms_res.dc_pick == "X2" else ms_res.dc_12_prob),
                 f"dc_{ms_res.dc_pick.lower()}")

        # OU25
        evaluate("OU25", ou_res.ou25_pick,
                 ou_res.over_25_prob if "Üst" in ou_res.ou25_pick else ou_res.under_25_prob,
                 "ou25_o" if "Üst" in ou_res.ou25_pick else "ou25_u")

        # BTTS
        evaluate("BTTS", ou_res.btts_pick,
                 ou_res.btts_yes_prob if "Var" in ou_res.btts_pick else ou_res.btts_no_prob,
                 "btts_y" if "Var" in ou_res.btts_pick else "btts_n")

        # OU15
        evaluate("OU15", ou_res.ou15_pick,
                 ou_res.over_15_prob if "Üst" in ou_res.ou15_pick else ou_res.under_15_prob,
                 "ou15_o" if "Üst" in ou_res.ou15_pick else "ou15_u")

        # ─── 3. Sort and Select ───
        # Sort by a mix of Confidence and Edge
        all_picks.sort(key=lambda p: (p.probability * 0.6) + (max(0, p.edge/100) * 0.4), reverse=True)

        main = all_picks[0]
        
        # Find Safe Alternative (if main isn't Safe)
        safe_alt = next((p for p in all_picks if p.risk_level == "SAFE"), None)
        if safe_alt == main: safe_alt = None

        value_picks = [p for p in all_picks if p.risk_level == "VALUE" and p != main]
        surprise_picks = [p for p in all_picks if p.risk_level == "SURPRISE"]

        # Market Summary for UI
        market_summary = {
            "MS_Home": ms_res.ms_home_prob,
            "MS_Draw": ms_res.ms_draw_prob,
            "MS_Away": ms_res.ms_away_prob,
            "OU25_Over": ou_res.over_25_prob,
            "BTTS_Yes": ou_res.btts_yes_prob
        }

        return ExpertResult(
            main_pick=main,
            safe_alternative=safe_alt,
            value_picks=value_picks,
            surprise_picks=surprise_picks,
            market_summary=market_summary
        )
