"""
Smart Bet Recommender
=====================

Skor tahminine göre akıllı bahis önerileri yapan sistem.

Örnek: Beşiktaş-Galatasaray için model 3-1 tahmin ediyor
→ DÜŞÜK RİSK: 1.5 Üst (yüksek ihtimal tutar)
→ ORTA RİSK: MS 1 + 2.5 Üst (orta ihtimal)
→ YÜKSEK RİSK: 3.5 Üst veya skor 3-1 (düşük ihtimal, yüksek kazanç)

Ayrıca kombinasyonlar:
- MS 1 + 1.5 Üst
- MS 1 + KG Var
- Her iki takım skor > 0.5 (her takım en az 1 gol atar)
"""

from dataclasses import dataclass
from typing import Dict, List, Optional, Tuple
from enum import Enum


class RiskLevel(Enum):
    LOW = "LOW"          # Yüksek olasılık, düşük oran (güvenli)
    MEDIUM = "MEDIUM"    # Orta olasılık, orta oran
    HIGH = "HIGH"        # Düşük olasılık, yüksek kazanç
    EXTREME = "EXTREME"  # Çok düşük olasılık, çok yüksek kazanç


@dataclass
class BetRecommendation:
    """Tek bir bahis önerisi"""
    market: str           # Piyasa adı (örn: "MS 1", "2.5 Üst")
    pick: str             # Seçim (örn: "1", "OVER", "YES")
    odds: float           # Oran
    probability: float    # Model olasılığı (0-1)
    confidence: float     # Güven seviyesi (0-100)
    risk_level: RiskLevel
    
    def to_dict(self) -> dict:
        return {
            "market": self.market,
            "pick": self.pick,
            "odds": self.odds,
            "probability": round(self.probability * 100, 1),
            "confidence": round(self.confidence, 1),
            "risk_level": self.risk_level.value
        }


@dataclass
class MatchPredictionSet:
    """Bir maç için tüm tahmin seti"""
    match_name: str
    predicted_score: Tuple[int, int]  # (home, away)
    home_win_prob: float
    draw_prob: float
    away_win_prob: float
    over_15_prob: float
    over_25_prob: float
    over_35_prob: float
    btts_yes_prob: float
    
    # Öneriler
    low_risk_bets: List[BetRecommendation]
    medium_risk_bets: List[BetRecommendation]
    high_risk_bets: List[BetRecommendation]
    extreme_risk_bets: List[BetRecommendation]
    
    def to_dict(self) -> dict:
        return {
            "match_name": self.match_name,
            "predicted_score": f"{self.predicted_score[0]}-{self.predicted_score[1]}",
            "probs": {
                "home_win": round(self.home_win_prob * 100, 1),
                "draw": round(self.draw_prob * 100, 1),
                "away_win": round(self.away_win_prob * 100, 1),
                "over_15": round(self.over_15_prob * 100, 1),
                "over_25": round(self.over_25_prob * 100, 1),
                "over_35": round(self.over_35_prob * 100, 1),
                "btts": round(self.btts_yes_prob * 100, 1)
            },
            "low_risk": [b.to_dict() for b in self.low_risk_bets],
            "medium_risk": [b.to_dict() for b in self.medium_risk_bets],
            "high_risk": [b.to_dict() for b in self.high_risk_bets],
            "extreme_risk": [b.to_dict() for b in self.extreme_risk_bets]
        }


class SmartBetRecommender:
    """
    Akıllı Bahis Öneri Sistemi
    
    Skor tahminine göre farklı risk seviyelerinde bahisler önerir.
    
    Mantık:
    1. DÜŞÜK RİSK: Yüksek olasılıklı (>70%), düşük oranlı bahisler
       - 1.5 Üst
       - Double Chance
       - Favori takım gol atar
    
    2. ORTA RİSK: Orta olasılıklı (50-70%), orta oranlı bahisler
       - MS favori
       - 2.5 Üst
       - KG Var/Var
    
    3. YÜKSEK RİSK: Düşük olasılıklı (30-50%), yüksek oranlı bahisler
       - 3.5 Üst
       - Skor tahmini
       - Handikap
    
    4. EXTREME RİSK: Çok düşük olasılıklı (<30%), çok yüksek oranlı
       - Tam skor
       - Uzunluklu kombinasyonlar
    """
    
    # Olasılık eşikleri
    PROB_LOW_RISK = 0.70      # > %70 olasılık
    PROB_MEDIUM_RISK = 0.50   # %50-70 olasılık
    PROB_HIGH_RISK = 0.30     # %30-50 olasılık
    # < %30 = EXTREME
    
    def __init__(self):
        pass
    
    def _determine_risk(self, probability: float) -> RiskLevel:
        """Olasılığa göre risk seviyesi belirle"""
        if probability >= self.PROB_LOW_RISK:
            return RiskLevel.LOW
        elif probability >= self.PROB_MEDIUM_RISK:
            return RiskLevel.MEDIUM
        elif probability >= self.PROB_HIGH_RISK:
            return RiskLevel.HIGH
        else:
            return RiskLevel.EXTREME
    
    def _get_favorite(self, home_prob: float, draw_prob: float, away_prob: float) -> Tuple[str, float]:
        """Favori sonucu ve olasılığını döndür"""
        if home_prob >= draw_prob and home_prob >= away_prob:
            return "1", home_prob
        elif away_prob >= home_prob and away_prob >= draw_prob:
            return "2", away_prob
        else:
            return "X", draw_prob
    
    def _calculate_expected_goals(self, predicted_score: Tuple[int, int]) -> float:
        """Tahmin edilen skora göre beklenen gol sayısı"""
        return predicted_score[0] + predicted_score[1]
    
    def recommend(
        self,
        match_name: str,
        predicted_score: Tuple[int, int],
        probs: Dict[str, float],
        odds: Dict[str, float]
    ) -> MatchPredictionSet:
        """
        Maç için tüm bahis önerilerini oluştur.
        
        Args:
            match_name: Maç adı
            predicted_score: (home_goals, away_goals)
            probs: {"home_win": 0.55, "draw": 0.25, "away_win": 0.20,
                    "over_15": 0.85, "over_25": 0.65, "over_35": 0.35,
                    "btts_yes": 0.55}
            odds: {"1": 1.80, "X": 3.50, "2": 4.20,
                   "ou15_o": 1.25, "ou15_u": 3.80,
                   "ou25_o": 1.90, "ou25_u": 1.85,
                   "ou35_o": 3.20, "ou35_u": 1.30,
                   "btts_y": 1.75, "btts_n": 2.00}
        
        Returns:
            MatchPredictionSet with all recommendations
        """
        home_prob = probs.get("home_win", 0.33)
        draw_prob = probs.get("draw", 0.33)
        away_prob = probs.get("away_win", 0.33)
        over_15_prob = probs.get("over_15", 0.70)
        over_25_prob = probs.get("over_25", 0.50)
        over_35_prob = probs.get("over_35", 0.30)
        btts_prob = probs.get("btts_yes", 0.50)
        
        # Beklenen goller
        expected_goals = self._calculate_expected_goals(predicted_score)
        
        # Favori
        favorite, favorite_prob = self._get_favorite(home_prob, draw_prob, away_prob)
        
        # Önerileri oluştur
        low_risk = []
        medium_risk = []
        high_risk = []
        extreme_risk = []
        
        # ========== DÜŞÜK RİSK ÖNERİLERİ ==========
        # 1.5 Üst (en güvenli)
        if over_15_prob >= self.PROB_LOW_RISK:
            low_risk.append(BetRecommendation(
                market="1.5 Üst/Alt",
                pick="OVER",
                odds=odds.get("ou15_o", 1.25),
                probability=over_15_prob,
                confidence=over_15_prob * 100,
                risk_level=RiskLevel.LOW
            ))
        
        # Double Chance
        if home_prob > away_prob:
            dc_prob = home_prob + draw_prob
            if dc_prob >= self.PROB_LOW_RISK:
                low_risk.append(BetRecommendation(
                    market="Double Chance",
                    pick="1X",
                    odds=odds.get("dc_1x", 1.30),
                    probability=dc_prob,
                    confidence=dc_prob * 100,
                    risk_level=RiskLevel.LOW
                ))
        elif away_prob > home_prob:
            dc_prob = away_prob + draw_prob
            if dc_prob >= self.PROB_LOW_RISK:
                low_risk.append(BetRecommendation(
                    market="Double Chance",
                    pick="X2",
                    odds=odds.get("dc_x2", 1.30),
                    probability=dc_prob,
                    confidence=dc_prob * 100,
                    risk_level=RiskLevel.LOW
                ))
        
        # ========== ORTA RİSK ÖNERİLERİ ==========
        # MS Favori
        if self.PROB_MEDIUM_RISK <= favorite_prob < self.PROB_LOW_RISK:
            medium_risk.append(BetRecommendation(
                market="Maç Sonucu",
                pick=favorite,
                odds=odds.get(favorite, 2.00),
                probability=favorite_prob,
                confidence=favorite_prob * 100,
                risk_level=RiskLevel.MEDIUM
            ))
        
        # 2.5 Üst
        if self.PROB_MEDIUM_RISK <= over_25_prob < self.PROB_LOW_RISK:
            medium_risk.append(BetRecommendation(
                market="2.5 Üst/Alt",
                pick="OVER",
                odds=odds.get("ou25_o", 1.90),
                probability=over_25_prob,
                confidence=over_25_prob * 100,
                risk_level=RiskLevel.MEDIUM
            ))
        
        # KG Var
        if self.PROB_MEDIUM_RISK <= btts_prob < self.PROB_LOW_RISK:
            medium_risk.append(BetRecommendation(
                market="Karşılıklı Gol",
                pick="YES",
                odds=odds.get("btts_y", 1.75),
                probability=btts_prob,
                confidence=btts_prob * 100,
                risk_level=RiskLevel.MEDIUM
            ))
        
        # MS + 2.5 Üst kombinasyonu
        if favorite_prob >= 0.45 and over_25_prob >= 0.50:
            combo_prob = favorite_prob * over_25_prob  # Basit çarpım
            combo_odds = odds.get(favorite, 2.00) * odds.get("ou25_o", 1.90)
            if combo_prob >= 0.30:  # En az %30 olasılık
                medium_risk.append(BetRecommendation(
                    market=f"MS {favorite} + 2.5 Üst",
                    pick=f"{favorite} & OVER",
                    odds=combo_odds,
                    probability=combo_prob,
                    confidence=combo_prob * 100,
                    risk_level=RiskLevel.MEDIUM
                ))
        
        # ========== YÜKSEK RİSK ÖNERİLERİ ==========
        # 3.5 Üst
        if self.PROB_HIGH_RISK <= over_35_prob < self.PROB_MEDIUM_RISK:
            high_risk.append(BetRecommendation(
                market="3.5 Üst/Alt",
                pick="OVER",
                odds=odds.get("ou35_o", 3.20),
                probability=over_35_prob,
                confidence=over_35_prob * 100,
                risk_level=RiskLevel.HIGH
            ))
        
        # Skor tahmini (yüksek skorlu maçlar için)
        if expected_goals >= 3.5:
            score_str = f"{predicted_score[0]}-{predicted_score[1]}"
            # Skor olasılığı tahmini (basit model)
            score_prob = 0.15 if expected_goals <= 4 else 0.10
            high_risk.append(BetRecommendation(
                market="Tam Skor",
                pick=score_str,
                odds=8.0,  # Tahmini oran
                probability=score_prob,
                confidence=score_prob * 100,
                risk_level=RiskLevel.HIGH
            ))
        
        # MS + 3.5 Üst
        if favorite_prob >= 0.40 and over_35_prob >= 0.30:
            combo_prob = favorite_prob * over_35_prob
            combo_odds = odds.get(favorite, 2.00) * odds.get("ou35_o", 3.20)
            high_risk.append(BetRecommendation(
                market=f"MS {favorite} + 3.5 Üst",
                pick=f"{favorite} & OVER",
                odds=combo_odds,
                probability=combo_prob,
                confidence=combo_prob * 100,
                risk_level=RiskLevel.HIGH
            ))
        
        # ========== EXTREME RİSK ÖNERİLERİ ==========
        # Uzun kombinasyonlar
        if favorite_prob >= 0.50 and btts_prob >= 0.50 and over_25_prob >= 0.60:
            combo_prob = favorite_prob * btts_prob * over_25_prob
            combo_odds = odds.get(favorite, 2.00) * odds.get("btts_y", 1.75) * odds.get("ou25_o", 1.90)
            if combo_prob >= 0.15:  # En az %15 olasılık
                extreme_risk.append(BetRecommendation(
                    market=f"MS {favorite} + KG Var + 2.5 Üst",
                    pick=f"{favorite} & BTTS & OVER",
                    odds=combo_odds,
                    probability=combo_prob,
                    confidence=combo_prob * 100,
                    risk_level=RiskLevel.EXTREME
                ))
        
        return MatchPredictionSet(
            match_name=match_name,
            predicted_score=predicted_score,
            home_win_prob=home_prob,
            draw_prob=draw_prob,
            away_win_prob=away_prob,
            over_15_prob=over_15_prob,
            over_25_prob=over_25_prob,
            over_35_prob=over_35_prob,
            btts_yes_prob=btts_prob,
            low_risk_bets=low_risk,
            medium_risk_bets=medium_risk,
            high_risk_bets=high_risk,
            extreme_risk_bets=extreme_risk
        )


# Singleton
_recommender = None

def get_smart_bet_recommender() -> SmartBetRecommender:
    global _recommender
    if _recommender is None:
        _recommender = SmartBetRecommender()
    return _recommender