"""
Match Commentary Generator
===========================
Generates human-readable Turkish commentary from the analysis package.
Reads all engine signals (model, odds band, betting brain, triple value)
and produces a clear, actionable summary for end users.

No LLM required — fully template-based.
"""

from __future__ import annotations

from typing import Any, Dict, List, Optional


def generate_match_commentary(package: Dict[str, Any]) -> Dict[str, Any]:
    """
    Main entry point. Takes a full analysis package and returns a commentary dict.

    Returns:
        {
            "action": "BET" | "WATCH" | "SKIP",
            "headline": "...",
            "summary": "...",
            "notes": ["...", "..."],
            "contradictions": ["...", "..."],
            "confidence_label": "YÜKSEK" | "ORTA" | "DÜŞÜK" | "ÇOK DÜŞÜK"
        }
    """
    match_info = package.get("match_info") or {}
    home = match_info.get("home_team", "Ev Sahibi")
    away = match_info.get("away_team", "Deplasman")
    main_pick = package.get("main_pick") or {}
    betting_brain = package.get("betting_brain") or {}
    v27_engine = package.get("v27_engine") or {}
    market_board = package.get("market_board") or {}
    score_pred = package.get("score_prediction") or {}
    risk = package.get("risk") or {}
    data_quality = package.get("data_quality") or {}

    # ── Determine action ──────────────────────────────────────────
    brain_decision = str(betting_brain.get("decision") or "NO_BET").upper()
    main_playable = bool(main_pick.get("playable"))
    main_vetoed = bool((main_pick.get("upper_brain") or {}).get("veto"))
    approved_count = int(betting_brain.get("approved_count", 0) or 0)

    if main_playable and not main_vetoed and approved_count > 0:
        action = "BET"
    elif approved_count == 0 and brain_decision == "NO_BET":
        action = "SKIP"
    else:
        action = "WATCH"

    # ── Headline ──────────────────────────────────────────────────
    headline = _build_headline(action, main_pick, home, away)

    # ── Summary paragraph ─────────────────────────────────────────
    summary = _build_summary(
        action, main_pick, market_board, v27_engine,
        score_pred, risk, data_quality, home, away,
        match_info=match_info,
    )

    # ── Quick notes ───────────────────────────────────────────────
    notes = _build_notes(market_board, v27_engine, score_pred, risk, home, away, league_name=match_info.get("league", ""))

    # ── Contradiction detection ───────────────────────────────────
    contradictions = _detect_contradictions(market_board, v27_engine, package)

    # ── Overall confidence label ──────────────────────────────────
    confidence_label = _overall_confidence_label(main_pick, data_quality)

    return {
        "action": action,
        "headline": headline,
        "summary": summary,
        "notes": notes[:6],
        "contradictions": contradictions[:4],
        "confidence_label": confidence_label,
    }


# ═══════════════════════════════════════════════════════════════════════
#  Headline
# ═══════════════════════════════════════════════════════════════════════

def _build_headline(
    action: str,
    main_pick: Dict[str, Any],
    home: str,
    away: str,
) -> str:
    if action == "BET":
        market = main_pick.get("market", "")
        pick = main_pick.get("pick", "")
        odds = main_pick.get("odds", 0.0)
        conf = main_pick.get("calibrated_confidence", main_pick.get("confidence", 0))
        market_tr = _market_to_turkish(market, pick)
        return f"🎯 {market_tr} önerisi — Oran: {odds}, Güven: %{conf:.0f}"

    if action == "WATCH":
        return f"👀 {home} vs {away} — İzlemeye değer sinyaller var"

    return f"⚠️ {home} vs {away} — Şu an net bir fırsat görülmüyor"


# ═══════════════════════════════════════════════════════════════════════
#  Summary
# ═══════════════════════════════════════════════════════════════════════

def _build_summary(
    action: str,
    main_pick: Dict[str, Any],
    market_board: Dict[str, Any],
    v27_engine: Dict[str, Any],
    score_pred: Dict[str, Any],
    risk: Dict[str, Any],
    data_quality: Dict[str, Any],
    home: str,
    away: str,
    match_info: Optional[Dict[str, Any]] = None,
) -> str:
    parts: List[str] = []

    # C-2: live-aware preamble — if the match is in play, lead with current score
    # vs the pre-match read so users immediately see how the prediction is faring.
    match_info = match_info or {}
    if match_info.get("is_live"):
        cur_home = match_info.get("current_score_home")
        cur_away = match_info.get("current_score_away")
        if cur_home is not None and cur_away is not None:
            parts.append(
                f"🔴 CANLI: {home} {cur_home} - {cur_away} {away} "
                f"(aşağıdaki analiz maç öncesi tahmindir)"
            )

    # Who is the favourite?
    ms_board = market_board.get("MS") or {}
    ms_pick = ms_board.get("pick", "")
    ms_conf = float(ms_board.get("confidence", 50) or 50)

    if ms_pick == "1" and ms_conf > 55:
        parts.append(f"{home} net favori")
    elif ms_pick == "1" and ms_conf > 45:
        parts.append(f"{home} hafif favori görünüyor")
    elif ms_pick == "2" and ms_conf > 55:
        parts.append(f"{away} net favori")
    elif ms_pick == "2" and ms_conf > 45:
        parts.append(f"{away} hafif favori görünüyor")
    else:
        parts.append("İki takım da birbirine yakın güçte")

    # xG expectation
    xg_home = float(score_pred.get("xg_home", 0) or 0)
    xg_away = float(score_pred.get("xg_away", 0) or 0)
    xg_total = xg_home + xg_away
    if xg_total > 3.0:
        parts.append(f"Gol beklentisi yüksek (toplam xG: {xg_total:.1f})")
    elif xg_total < 2.0:
        parts.append(f"Düşük gol beklentisi (toplam xG: {xg_total:.1f})")

    # Consensus check
    consensus = str(v27_engine.get("consensus") or "").upper()
    if consensus == "AGREE":
        parts.append("Model motorları aynı fikirde")
    elif consensus == "DISAGREE":
        parts.append("Model motorları farklı sonuçlara ulaşıyor — belirsizlik var")

    # Action-specific
    if action == "BET":
        market_tr = _market_to_turkish(
            main_pick.get("market", ""), main_pick.get("pick", "")
        )
        edge = float(main_pick.get("ev_edge", 0) or 0)
        parts.append(
            f"{market_tr} yönünde değer tespit edildi (EV edge: {edge:+.1%})"
        )
    elif action == "SKIP":
        parts.append(
            "Hiçbir markette piyasanın fiyatlamadığı bir avantaj görülmüyor"
        )

    # Risk
    risk_level = str(risk.get("level") or "MEDIUM").upper()
    if risk_level == "HIGH":
        parts.append("⚠️ Risk seviyesi yüksek")
    elif risk_level == "EXTREME":
        parts.append("🔴 Çok yüksek risk — dikkatli olun")

    # Data quality
    quality_label = str(data_quality.get("label") or "MEDIUM").upper()
    if quality_label == "LOW":
        parts.append("Veri kalitesi düşük — tahminler daha az güvenilir")

    return ". ".join(parts) + "."


# ═══════════════════════════════════════════════════════════════════════
#  Quick Notes
# ═══════════════════════════════════════════════════════════════════════

def _build_notes(
    market_board: Dict[str, Any],
    v27_engine: Dict[str, Any],
    score_pred: Dict[str, Any],
    risk: Dict[str, Any],
    home: str,
    away: str,
    league_name: str = "",
) -> List[str]:
    notes: List[str] = []
    triple_value = v27_engine.get("triple_value") or {}
    odds_band = v27_engine.get("odds_band") or {}

    # Cup game note — model uses league statistics; cup dynamics differ
    _cup_kws = ("kupa", "cup", "coupe", "copa", "pokal", "ziraat", "trophy", "shield", "super cup", "süper kupa")
    if any(kw in (league_name or "").lower() for kw in _cup_kws):
        notes.append("⚠️ Kupa maçı: ev avantajı zayıf, rotasyon ve düşük motivasyon riski var")

    # MS note
    ms = market_board.get("MS") or {}
    ms_conf = float(ms.get("confidence", 0) or 0)
    if ms_conf < 45:
        notes.append("Maç sonucu belirsiz, net favori yok")
    elif ms.get("pick") == "1":
        notes.append(f"{home} favori ama oran değerli mi kontrol et")
    elif ms.get("pick") == "2":
        notes.append(f"{away} favori ama oran değerli mi kontrol et")

    # OU25 note
    ou25 = market_board.get("OU25") or {}
    ou25_probs = ou25.get("probs") or {}
    over_prob = float(ou25_probs.get("over", 0.5) or 0.5)
    if over_prob > 0.58:
        notes.append("2.5 Üst yönünde eğilim var")
    elif over_prob < 0.42:
        notes.append("2.5 Alt yönünde eğilim var")
    else:
        notes.append("2.5 Üst/Alt dengeli — kesin sinyal yok")

    # BTTS note
    btts = market_board.get("BTTS") or {}
    btts_probs = btts.get("probs") or {}
    btts_yes = float(btts_probs.get("yes", 0.5) or 0.5)
    if btts_yes > 0.58:
        notes.append("Her iki takımın da gol atması bekleniyor")
    elif btts_yes < 0.42:
        notes.append("KG olasılığı düşük")

    # HT note
    ht = market_board.get("HT") or {}
    ht_pick = ht.get("pick", "")
    ht_conf = float(ht.get("confidence", 0) or 0)
    if ht_conf > 40 and ht_pick:
        ht_label = {"1": f"İY {home}", "2": f"İY {away}", "X": "İY beraberlik"}.get(
            ht_pick, f"İY {ht_pick}"
        )
        notes.append(f"{ht_label} yönünde hafif sinyal (%{ht_conf:.0f})")

    # Risk warnings
    warnings = risk.get("warnings") or []
    for w in warnings[:2]:
        notes.append(f"⚠️ {w}")

    return notes


# ═══════════════════════════════════════════════════════════════════════
#  Contradiction Detection
# ═══════════════════════════════════════════════════════════════════════

def _detect_contradictions(
    market_board: Dict[str, Any],
    v27_engine: Dict[str, Any],
    package: Dict[str, Any],
) -> List[str]:
    """
    Detect cases where model prediction and odds band/triple value
    point in opposite directions — the user's main complaint.
    """
    contradictions: List[str] = []
    triple_value = v27_engine.get("triple_value") or {}
    predictions = v27_engine.get("predictions") or {}

    # C-2 live-vs-prediction mismatch
    match_info = package.get("match_info") or {}
    if match_info.get("is_live"):
        cur_h = match_info.get("current_score_home")
        cur_a = match_info.get("current_score_away")
        ms_board_live = market_board.get("MS") or {}
        predicted_pick = str(ms_board_live.get("pick") or "")
        if cur_h is not None and cur_a is not None:
            actual_pick: Optional[str] = None
            if cur_h > cur_a:
                actual_pick = "1"
            elif cur_a > cur_h:
                actual_pick = "2"
            else:
                actual_pick = "X"
            if predicted_pick and actual_pick and predicted_pick != actual_pick:
                contradictions.append(
                    "Canlı durum maç öncesi tahmin ile çelişiyor — sürpriz GERÇEKLEŞİYOR"
                )

    # MS contradiction: model says home but triple_value says away has value
    ms_preds = predictions.get("ms") or {}
    ms_home = float(ms_preds.get("home", 0) or 0)
    ms_away = float(ms_preds.get("away", 0) or 0)
    home_triple = triple_value.get("home") or {}
    away_triple = triple_value.get("away") or {}

    model_favours_home = ms_home > ms_away
    away_is_value = bool(away_triple.get("is_value"))
    home_is_value = bool(home_triple.get("is_value"))

    if model_favours_home and away_is_value:
        contradictions.append(
            "Model ev sahibini favori görüyor ama oran bandı deplasmanda değer buluyor — "
            "bu çelişki nedeniyle MS tahminine dikkatli yaklaş"
        )
    elif not model_favours_home and home_is_value:
        contradictions.append(
            "Model deplasmanı favori görüyor ama oran bandı ev sahibinde değer buluyor — "
            "bu çelişki nedeniyle MS tahminine dikkatli yaklaş"
        )

    # HT contradiction
    ht_board = market_board.get("HT") or {}
    ht_pick = ht_board.get("pick", "")
    ht_home_triple = triple_value.get("ht_home") or {}
    ht_away_triple = triple_value.get("ht_away") or {}

    if ht_pick == "1" and bool(ht_away_triple.get("is_value")):
        contradictions.append(
            "Model İY ev sahibi diyor ama oran bandı İY deplasmanda değer buluyor — "
            "İY tahmini güvenilir değil"
        )
    elif ht_pick == "2" and bool(ht_home_triple.get("is_value")):
        contradictions.append(
            "Model İY deplasman diyor ama oran bandı İY ev sahibinde değer buluyor — "
            "İY tahmini güvenilir değil"
        )

    # OU25 contradiction
    ou25_board = market_board.get("OU25") or {}
    ou25_pick = ou25_board.get("pick", "")
    ou25_over_triple = triple_value.get("ou25_over") or {}
    ou25_under_triple = triple_value.get("ou25_under") or {}

    if ou25_pick == "Üst" and bool(ou25_under_triple.get("is_value")):
        contradictions.append(
            "Model 2.5 Üst diyor ama oran bandı 2.5 Alt'ta değer buluyor — çelişki var"
        )
    elif ou25_pick == "Alt" and bool(ou25_over_triple.get("is_value")):
        contradictions.append(
            "Model 2.5 Alt diyor ama oran bandı 2.5 Üst'te değer buluyor — çelişki var"
        )

    return contradictions


# ═══════════════════════════════════════════════════════════════════════
#  Helpers
# ═══════════════════════════════════════════════════════════════════════

def _overall_confidence_label(
    main_pick: Dict[str, Any],
    data_quality: Dict[str, Any],
) -> str:
    """Overall confidence label for the entire analysis."""
    quality_score = float(data_quality.get("score", 0.5) or 0.5)
    main_conf = float(
        main_pick.get("calibrated_confidence", main_pick.get("confidence", 0)) or 0
    )
    main_playable = bool(main_pick.get("playable"))

    if main_playable and main_conf >= 60 and quality_score >= 0.8:
        return "YÜKSEK"
    if main_playable and main_conf >= 45:
        return "ORTA"
    if main_conf >= 30:
        return "DÜŞÜK"
    return "ÇOK DÜŞÜK"


_MARKET_TR_MAP = {
    "MS": {"1": "Maç Sonucu Ev Sahibi", "2": "Maç Sonucu Deplasman", "X": "Beraberlik"},
    "DC": {"1X": "Çifte Şans 1X", "X2": "Çifte Şans X2", "12": "Çifte Şans 12"},
    "OU25": {"Üst": "2.5 Üst", "Alt": "2.5 Alt", "Over": "2.5 Üst", "Under": "2.5 Alt"},
    "OU15": {"Üst": "1.5 Üst", "Alt": "1.5 Alt", "Over": "1.5 Üst", "Under": "1.5 Alt"},
    "OU35": {"Üst": "3.5 Üst", "Alt": "3.5 Alt", "Over": "3.5 Üst", "Under": "3.5 Alt"},
    "BTTS": {"KG Var": "Karşılıklı Gol Var", "KG Yok": "Karşılıklı Gol Yok",
             "Yes": "Karşılıklı Gol Var", "No": "Karşılıklı Gol Yok"},
    "HT": {"1": "İlk Yarı Ev Sahibi", "2": "İlk Yarı Deplasman", "X": "İlk Yarı Beraberlik"},
    "HT_OU05": {"Üst": "İY 0.5 Üst", "Alt": "İY 0.5 Alt"},
    "HT_OU15": {"Üst": "İY 1.5 Üst", "Alt": "İY 1.5 Alt"},
    "OE": {"Tek": "Tek", "Çift": "Çift", "Odd": "Tek", "Even": "Çift"},
    "CARDS": {"Üst": "Kart Üst", "Alt": "Kart Alt"},
}


def _market_to_turkish(market: str, pick: str) -> str:
    market_map = _MARKET_TR_MAP.get(market, {})
    result = market_map.get(pick)
    if result:
        return result
    return f"{market} {pick}"
