"""
Upset Engine v2 - GLM-5 Tespitleri ile Geliştirilmiş Sürpriz Tespiti
====================================================================

Yeni Eklenen Faktörler (GLM-5 Analizinden):
1. MARGIN_ANALIZI - Bookmaker margin > %18 = sürpriz riski
2. FAVORI_ORAN_TUZAGI - 1.40-1.60 arası en yüksek sürpriz oranı
3. HAKEM_SURPRIZ_ORANI - Hakemin geçmiş maçlarında ev kayıp oranı
4. FORM_FARKI_TUZAGI - Form farkı > 40 = "çok iyi görünen" favori tuzak

Orijinal Faktörler:
- Atmosfer (Avrupa gecesi, taraftar baskısı)
- Motivasyon asimetrisi (küme düşme vs şampiyon)
- Yorgunluk (maç yoğunluğu, seyahat)
- Tarihsel upset pattern
"""

from typing import Dict, Any, Optional, Tuple, List
from dataclasses import dataclass, field

try:
    import psycopg2
    from psycopg2.extras import RealDictCursor
except ImportError:
    psycopg2 = None


@dataclass
class UpsetFactorsV2:
    """Upset potansiyelini etkileyen faktörler - v2"""
    # Orijinal faktörler
    atmosphere_score: float = 0.0
    motivation_score: float = 0.0
    fatigue_score: float = 0.0
    historical_upset_rate: float = 0.0
    
    # YENİ FAKTÖRLER (GLM-5)
    margin_score: float = 0.0           # Bookmaker margin analizi
    favorite_odds_trap: float = 0.0     # Favori oran tuzağı
    referee_upset_score: float = 0.0    # Hakem sürpriz oranı
    form_trap_score: float = 0.0        # Form farkı tuzağı
    
    # Toplam
    total_upset_potential: float = 0.0
    reasoning: List[str] = field(default_factory=list)
    
    # YENİ: Sürpriz skoru (0-100)
    upset_score: int = 0
    upset_level: str = "LOW"  # LOW, MEDIUM, HIGH, EXTREME


class UpsetEngineV2:
    """
    Favori takımın kaybedeceği maçları tespit eder.
    v2: GLM-5 analizlerinden elde edilen yeni faktörler eklendi.
    """
    
    # Yüksek atmosferli stadyumlar
    HIGH_ATMOSPHERE_TEAMS = {
        "galatasaray", "fenerbahce", "besiktas", "trabzonspor",
        "liverpool", "newcastle", "leeds",
        "dortmund", "union berlin",
        "olympiacos", "panathinaikos", "aek athens",
        "boca juniors", "river plate",
        "celtic", "rangers", "red star belgrade"
    }
    
    EUROPEAN_COMPETITIONS = {
        "şampiyonlar ligi", "champions league", "uefa champions league",
        "avrupa ligi", "europa league", "uefa europa league",
        "konferans ligi", "conference league", "uefa conference league"
    }
    
    # YENİ: Sürpriz oranları (veritabanı analizinden)
    # Favori oran aralığına göre sürpriz oranları
    FAVORITE_ODDS_UPSET_RATES = {
        (1.10, 1.20): 0.111,  # %11.1 sürpriz
        (1.20, 1.30): 0.150,  # %15.0 sürpriz
        (1.30, 1.40): 0.235,  # %23.5 sürpriz
        (1.40, 1.50): 0.333,  # %33.3 sürpriz ← DİKKAT!
        (1.50, 1.60): 0.350,  # %35.0 sürpriz ← EN YÜKSEK!
    }
    
    def __init__(self):
        self.conn = None
        self._connect_db()
    
    def _connect_db(self):
        if psycopg2 is None:
            return
        try:
            from data.db import get_clean_dsn
            self.conn = psycopg2.connect(get_clean_dsn())
        except Exception as e:
            print(f"[UpsetEngineV2] DB connection failed: {e}")
            self.conn = None
    
    def _get_conn(self):
        if self.conn is None or self.conn.closed:
            self._connect_db()
        return self.conn
    
    # ═════════════════════════════════════════════════════════════════
    # YENİ FAKTÖRLER (GLM-5 Analizinden)
    # ═════════════════════════════════════════════════════════════════
    
    def calculate_margin_score(
        self,
        odds_data: Dict[str, float]
    ) -> Tuple[float, List[str]]:
        """
        GLM-5 Tespiti: Bookmaker margin analizi
        
        Margin > %18 → Bookmaker kendini koruyor, favori riskli
        Margin > %20 → Yüksek risk, sürpriz bekleniyor
        """
        score = 0.0
        reasons = []
        
        ms_h = odds_data.get("ms_h", 0)
        ms_d = odds_data.get("ms_d", 0)
        ms_a = odds_data.get("ms_a", 0)
        
        if ms_h > 0 and ms_d > 0 and ms_a > 0:
            margin = (1/ms_h + 1/ms_d + 1/ms_a) - 1
            
            if margin > 0.20:
                score = 0.25
                reasons.append(f"⚠️ Margin çok yüksek (%{margin*100:.1f}) - Bookmaker risk görüyor!")
            elif margin > 0.18:
                score = 0.15
                reasons.append(f"⚠️ Margin yüksek (%{margin*100:.1f}) - Dikkat!")
        
        return score, reasons
    
    def calculate_favorite_odds_trap(
        self,
        favorite_odds: float,
        favorite_side: str  # 'home' or 'away'
    ) -> Tuple[float, List[str]]:
        """
        GLM-5 Tespiti: Favori oran tuzağı
        
        Veritabanı analizine göre:
        - 1.40-1.50 arası: %33.3 sürpriz
        - 1.50-1.60 arası: %35.0 sürpriz (EN YÜKSEK!)
        - < 1.20: Tuzak oranı şüphesi
        """
        score = 0.0
        reasons = []
        
        if favorite_odds <= 0:
            return score, reasons
        
        for (low, high), upset_rate in self.FAVORITE_ODDS_UPSET_RATES.items():
            if low <= favorite_odds < high:
                score = upset_rate  # Doğrudan sürpriz olasılığı
                if upset_rate >= 0.30:
                    reasons.append(f"🔴 Favori oran {favorite_odds:.2f} - %{upset_rate*100:.0f} sürpriz oranı!")
                elif upset_rate >= 0.20:
                    reasons.append(f"⚠️ Favori oran {favorite_odds:.2f} - %{upset_rate*100:.0f} sürpriz riski")
                break
        
        # Çok düşük oran tuzağı
        if favorite_odds < 1.20:
            score = max(score, 0.20)
            reasons.append(f"⚠️ Favori oran çok düşük ({favorite_odds:.2f}) - Tuzak oranı şüphesi")
        
        return score, reasons
    
    def calculate_referee_upset_score(
        self,
        referee_name: str
    ) -> Tuple[float, List[str]]:
        """
        GLM-5 Tespiti: Hakem sürpriz oranı
        
        Hakemin yönettiği maçlarda ev sahibi kayıp oranı
        > %25 → Yüksek sürpriz riski
        """
        score = 0.0
        reasons = []
        
        if not referee_name or not self._get_conn():
            return score, reasons
        
        try:
            cur = self._get_conn().cursor()
            
            # Hakemin yönettiği maçlarda sonuçlar
            cur.execute("""
                SELECT 
                    COUNT(*) as total,
                    SUM(CASE WHEN m.score_home < m.score_away THEN 1 ELSE 0 END) as away_wins,
                    SUM(CASE WHEN m.score_home = m.score_away THEN 1 ELSE 0 END) as draws
                FROM match_officials mo
                JOIN matches m ON m.id = mo.match_id
                WHERE mo.name = %s AND mo.role_id = 1
                AND m.score_home IS NOT NULL
            """, (referee_name,))
            
            row = cur.fetchone()
            cur.close()
            
            if row and row[0] and row[0] >= 3:
                total = row[0]
                away_wins = row[1] or 0
                draws = row[2] or 0
                
                upset_rate = (away_wins + draws * 0.5) / total
                
                if upset_rate > 0.40:
                    score = 0.25
                    reasons.append(f"👨‍⚖️ {referee_name}: %{upset_rate*100:.0f} sürpriz oranı (YÜKSEK!)")
                elif upset_rate > 0.30:
                    score = 0.15
                    reasons.append(f"👨‍⚖️ {referee_name}: %{upset_rate*100:.0f} sürpriz oranı")
        
        except Exception as e:
            pass
        
        return score, reasons
    
    def calculate_form_trap_score(
        self,
        home_form_score: float,
        away_form_score: float,
        favorite_side: str
    ) -> Tuple[float, List[str]]:
        """
        GLM-5 Tespiti: Form farkı tuzağı
        
        Form farkı > 40 → "Çok iyi görünen" favori tuzak
        Favori formu kötü ama oran düşük → Sürpriz bekleniyor
        """
        score = 0.0
        reasons = []
        
        form_diff = home_form_score - away_form_score
        
        # Form farkı çok büyük
        if abs(form_diff) > 40:
            score = 0.20
            if form_diff > 0 and favorite_side == 'away':
                reasons.append(f"🔴 Form tuzağı! Ev sahibi formda ({home_form_score:.0f}) ama deplasman favori")
            elif form_diff < 0 and favorite_side == 'home':
                reasons.append(f"🔴 Form tuzağı! Deplasman formda ({away_form_score:.0f}) ama ev sahibi favori")
        
        # Favori formu kötü
        if favorite_side == 'home' and home_form_score < 50:
            score = max(score, 0.15)
            reasons.append(f"⚠️ Favori ev sahibi formu düşük ({home_form_score:.0f})")
        elif favorite_side == 'away' and away_form_score < 50:
            score = max(score, 0.15)
            reasons.append(f"⚠️ Favori deplasman formu düşük ({away_form_score:.0f})")
        
        return score, reasons
    
    # ═════════════════════════════════════════════════════════════════
    # ORİJİNAL FAKTÖRLER
    # ═════════════════════════════════════════════════════════════════
    
    def calculate_atmosphere_score(
        self,
        home_team_name: str,
        league_name: str,
        is_cup_match: bool = False
    ) -> Tuple[float, List[str]]:
        """Orijinal: Atmosfer skoru"""
        score = 0.0
        reasons = []
        
        home_lower = home_team_name.lower()
        for team in self.HIGH_ATMOSPHERE_TEAMS:
            if team in home_lower:
                score += 0.25
                reasons.append(f"🔥 {home_team_name} yüksek atmosferli stadyum")
                break
        
        league_lower = league_name.lower()
        for comp in self.EUROPEAN_COMPETITIONS:
            if comp in league_lower:
                score += 0.20
                reasons.append("🌟 Avrupa gecesi - ekstra motivasyon")
                break
        
        if is_cup_match:
            score += 0.10
            reasons.append("🏆 Kupa maçı - her şey olabilir")
        
        return min(score, 1.0), reasons
    
    def calculate_motivation_score(
        self,
        home_position: int,
        away_position: int,
        total_teams: int = 20
    ) -> Tuple[float, List[str]]:
        """Orijinal: Motivasyon asimetrisi"""
        score = 0.0
        reasons = []
        
        if home_position is not None and away_position is not None:
            position_diff = away_position - home_position
            relegation_zone = total_teams - 3
            
            if home_position >= relegation_zone and away_position <= 3:
                score += 0.30
                reasons.append("⚔️ Hayatta kalma savaşı vs şampiyonluk adayı")
            elif home_position >= relegation_zone:
                score += 0.15
                reasons.append("🔥 Ev sahibi küme düşme hattında")
            
            if position_diff < -10:
                score += 0.15
                reasons.append(f"📊 {abs(position_diff)} sıra fark")
        
        return min(score, 1.0), reasons
    
    # ═════════════════════════════════════════════════════════════════
    # ANA FONKSİYON
    # ═════════════════════════════════════════════════════════════════
    
    def calculate_upset_potential(
        self,
        home_team_name: str,
        home_team_id: str,
        away_team_name: str,
        league_name: str,
        home_position: int = None,
        away_position: int = None,
        match_date_ms: int = None,
        odds_data: Dict[str, float] = None,
        referee_name: str = None,
        home_form_score: float = 50.0,
        away_form_score: float = 50.0,
        favorite_side: str = None,  # 'home', 'away', or 'draw'
        favorite_odds: float = None
    ) -> UpsetFactorsV2:
        """
        Tam upset analizi - v2 (GLM-5 geliştirmeleri ile)
        """
        factors = UpsetFactorsV2()
        all_reasons = []
        
        # 1. Margin analizi (YENİ)
        if odds_data:
            factors.margin_score, reasons = self.calculate_margin_score(odds_data)
            all_reasons.extend(reasons)
        
        # 2. Favori oran tuzağı (YENİ)
        if favorite_odds and favorite_side:
            factors.favorite_odds_trap, reasons = self.calculate_favorite_odds_trap(
                favorite_odds, favorite_side
            )
            all_reasons.extend(reasons)
        
        # 3. Hakem sürpriz oranı (YENİ)
        if referee_name:
            factors.referee_upset_score, reasons = self.calculate_referee_upset_score(
                referee_name
            )
            all_reasons.extend(reasons)
        
        # 4. Form tuzağı (YENİ)
        factors.form_trap_score, reasons = self.calculate_form_trap_score(
            home_form_score, away_form_score, favorite_side or 'home'
        )
        all_reasons.extend(reasons)
        
        # 5. Atmosfer (orijinal)
        factors.atmosphere_score, reasons = self.calculate_atmosphere_score(
            home_team_name, league_name
        )
        all_reasons.extend(reasons)
        
        # 6. Motivasyon (orijinal)
        if home_position is not None and away_position is not None:
            factors.motivation_score, reasons = self.calculate_motivation_score(
                home_position, away_position
            )
            all_reasons.extend(reasons)
        
        # ═══════════════════════════════════════════════════════════
        # SÜRPRİZ SKORU HESAPLAMA (0-100) - GÜÇLENDİRİLMİŞ v2.1
        # ═══════════════════════════════════════════════════════════
        
        upset_score = 0
        
        # Margin (> %18 = +20, > %20 = +30) - GÜÇLENDİRİLDİ
        if factors.margin_score >= 0.25:
            upset_score += 30  # Artırıldı: 20 -> 30
            all_reasons.append("🔴 Margin > %20: Bookmaker büyük risk görüyor!")
        elif factors.margin_score >= 0.15:
            upset_score += 20  # Artırıldı: 15 -> 20
            all_reasons.append("⚠️ Margin > %18: Dikkatli ol!")
        
        # Favori oran tuzağı - GÜÇLENDİRİLDİ
        if factors.favorite_odds_trap >= 0.30:
            upset_score += 30  # Artırıldı: 25 -> 30
        elif factors.favorite_odds_trap >= 0.20:
            upset_score += 25  # Artırıldı: 20 -> 25
        elif factors.favorite_odds_trap >= 0.15:
            upset_score += 20  # Artırıldı: 15 -> 20
        
        # Hakem
        if factors.referee_upset_score >= 0.25:
            upset_score += 20
        elif factors.referee_upset_score >= 0.15:
            upset_score += 10
        
        # Form tuzağı - GÜÇLENDİRİLDİ
        if factors.form_trap_score >= 0.20:
            upset_score += 20  # Artırıldı: 15 -> 20
        elif factors.form_trap_score >= 0.15:
            upset_score += 15  # Artırıldı: 10 -> 15
        
        # Atmosfer - GÜÇLENDİRİLDİ
        if factors.atmosphere_score >= 0.40:
            upset_score += 20  # Artırıldı: 15 -> 20
        elif factors.atmosphere_score >= 0.25:
            upset_score += 15  # Artırıldı: 10 -> 15
        
        # Motivasyon
        if factors.motivation_score >= 0.30:
            upset_score += 15
        elif factors.motivation_score >= 0.15:
            upset_score += 10
        
        # ═══════════════════════════════════════════════════════════
        # YENİ: EKSTRA RİSK FAKTÖRLERİ
        # ═══════════════════════════════════════════════════════════
        
        # Deplasman favorisi ekstra risk (+10)
        if favorite_side == 'away':
            upset_score += 10
            all_reasons.append("📍 Deplasman favorisi - ekstra risk!")
        
        # Favori formu çok düşük (< 40) = +15
        if favorite_side == 'home' and home_form_score < 40:
            upset_score += 15
            all_reasons.append(f"🔴 Favori ev sahibi formu ÇOK DÜŞÜK ({home_form_score:.0f})")
        elif favorite_side == 'away' and away_form_score < 40:
            upset_score += 15
            all_reasons.append(f"🔴 Favori deplasman formu ÇOK DÜŞÜK ({away_form_score:.0f})")
        
        # Çok düşük favori oranı (< 1.30) ama margin yüksek = tuzak şüphesi
        if favorite_odds and favorite_odds < 1.30 and factors.margin_score >= 0.15:
            upset_score += 10
            all_reasons.append(f"⚠️ Düşük oran ({favorite_odds:.2f}) + yüksek margin = TUZAK ŞÜPHESİ!")
        
        factors.upset_score = min(upset_score, 100)
        
        # Seviye belirle
        if factors.upset_score >= 60:
            factors.upset_level = "EXTREME"
        elif factors.upset_score >= 45:
            factors.upset_level = "HIGH"
        elif factors.upset_score >= 30:
            factors.upset_level = "MEDIUM"
        else:
            factors.upset_level = "LOW"
        
        # Toplam upset potansiyeli
        factors.total_upset_potential = min(
            (factors.margin_score + factors.favorite_odds_trap + 
             factors.referee_upset_score + factors.form_trap_score +
             factors.atmosphere_score * 0.5 + factors.motivation_score * 0.5) / 1.5,
            1.0
        )
        
        factors.reasoning = all_reasons
        
        return factors


def get_upset_engine_v2():
    """Singleton pattern"""
    return UpsetEngineV2()


if __name__ == "__main__":
    # Test
    engine = get_upset_engine_v2()
    
    # Real Madrid vs Getafe test
    result = engine.calculate_upset_potential(
        home_team_name="Real Madrid",
        home_team_id="test",
        away_team_name="Getafe",
        league_name="LaLiga",
        odds_data={"ms_h": 1.25, "ms_d": 3.92, "ms_a": 6.86},
        referee_name="A. Muniz Ruiz",
        home_form_score=80.0,
        away_form_score=56.7,
        favorite_side="home",
        favorite_odds=1.25
    )
    
    print(f"\n{'='*60}")
    print(f"Real Madrid vs Getafe - Sürpriz Analizi")
    print(f"{'='*60}")
    print(f"Sürpriz Skoru: {result.upset_score}/100")
    print(f"Seviye: {result.upset_level}")
    print(f"\nNedenler:")
    for reason in result.reasoning:
        print(f"  {reason}")