"""
Upset Engine - Dev Avcısı Tespit Sistemi
V9 Model için Galatasaray-Liverpool tarzı sürpriz maçları tespit eder.

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

import os
import sys
from typing import Dict, Any, Optional, Tuple
from dataclasses import dataclass, field

# Add parent directory to path for imports
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

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


@dataclass
class UpsetFactors:
    """Upset potansiyelini etkileyen faktörler"""
    atmosphere_score: float = 0.0      # Atmosfer etkisi (0-1)
    motivation_score: float = 0.0       # Motivasyon asimetrisi (0-1)
    fatigue_score: float = 0.0          # Yorgunluk farkı (0-1)
    historical_upset_rate: float = 0.0  # Tarihsel upset oranı (0-1)
    total_upset_potential: float = 0.0  # Toplam upset potansiyeli (0-1)
    reasoning: list = field(default_factory=list)


class UpsetEngine:
    """
    Favori takımın kaybedeceği maçları tespit eder.
    Galatasaray-Liverpool tarzı sürprizleri yakalar.
    """
    
    # Yüksek atmosferli stadyumlar (manuel tanımlı + hesaplanabilir)
    HIGH_ATMOSPHERE_TEAMS = {
        # Türkiye
        "galatasaray", "fenerbahce", "besiktas", "trabzonspor",
        # İngiltere
        "liverpool", "newcastle", "leeds",
        # Almanya
        "dortmund", "union berlin",
        # Yunanistan
        "olympiacos", "panathinaikos", "aek athens",
        # Arjantin
        "boca juniors", "river plate",
        # Diğer
        "celtic", "rangers", "red star belgrade"
    }
    
    # Avrupa kupaları (yüksek motivasyon)
    EUROPEAN_COMPETITIONS = {
        "şampiyonlar ligi", "champions league", "uefa champions league",
        "avrupa ligi", "europa league", "uefa europa league",
        "konferans ligi", "conference league", "uefa conference league"
    }
    
    def __init__(self):
        self.conn = None
        self._connect_db()
    
    def _connect_db(self):
        """Veritabanına bağlan"""
        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"[UpsetEngine] DB connection failed: {e}")
            self.conn = None
    
    def _get_conn(self):
        """Bağlantıyı kontrol et ve döndür"""
        if self.conn is None or self.conn.closed:
            self._connect_db()
        return self.conn
    
    def calculate_atmosphere_score(
        self, 
        home_team_name: str,
        league_name: str,
        is_cup_match: bool = False
    ) -> Tuple[float, list]:
        """
        Atmosfer skorunu hesapla.
        Yüksek atmosferli stadyumlar upset potansiyelini artırır.
        """
        score = 0.0
        reasons = []
        
        # Yüksek atmosferli takım mı?
        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
        
        # Avrupa kupası mı?
        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
        
        # Kupa maçı mı? (tek maç eliminasyon)
        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,
        home_points_to_safety: Optional[int] = None,
        away_already_champion: bool = False,
        total_teams: int = 20
    ) -> Tuple[float, list]:
        """
        Motivasyon asimetrisini hesapla.
        Alt sıradaki takımın üst sıradakine karşı ekstra motivasyonu.
        """
        score = 0.0
        reasons = []
        
        # Pozisyon farkı
        position_diff = 0
        if away_position is not None and home_position is not None:
            position_diff = away_position - home_position  # Negatif = deplasman daha iyi sırada
        
        # Küme düşme hattı vs üst sıra (en güçlü upset faktörü)
        relegation_zone = total_teams - 3  # Son 3 takım
        if home_position is not None and away_position is not None:
            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 - ekstra motivasyon")
        elif home_position is not None and home_position >= relegation_zone:
            score += 0.15
            reasons.append("🔥 Ev sahibi küme düşme hattında - ekstra motivasyon")
        
        # Deplasman takımı zaten şampiyon mu?
        if away_already_champion:
            score += 0.20
            reasons.append("😴 Deplasman takımı zaten şampiyon - motivasyon düşük")
        
        # Büyük pozisyon farkı (underdog evinde)
        if position_diff < -10:
            score += 0.15
            reasons.append(f"📊 {abs(position_diff)} sıra fark - büyük maç heyecanı")
        elif position_diff < -5:
            score += 0.08
        
        return min(score, 1.0), reasons
    
    def calculate_fatigue_score(
        self,
        home_matches_last_14d: int = 0,
        away_matches_last_14d: int = 0,
        home_days_rest: int = 7,
        away_days_rest: int = 7,
        away_travel_km: float = 0
    ) -> Tuple[float, list]:
        """
        Yorgunluk farkını hesapla.
        Yorgun deplasman takımı = yüksek upset potansiyeli.
        """
        score = 0.0
        reasons = []
        
        # Maç yoğunluğu farkı
        match_diff = away_matches_last_14d - home_matches_last_14d
        if match_diff >= 3:
            score += 0.20
            reasons.append(f"🏃 Deplasman {match_diff} maç daha fazla oynamış")
        elif match_diff >= 2:
            score += 0.10
        
        # Dinlenme süresi farkı
        rest_diff = home_days_rest - away_days_rest
        if rest_diff >= 4:
            score += 0.15
            reasons.append(f"💤 Ev sahibi {rest_diff} gün daha fazla dinlenmiş")
        elif rest_diff >= 2:
            score += 0.08
        
        # Uzun deplasman
        if away_travel_km > 3000:
            score += 0.15
            reasons.append(f"✈️ Uzun deplasman ({int(away_travel_km)} km)")
        elif away_travel_km > 1500:
            score += 0.08
        
        return min(score, 1.0), reasons
    
    def get_historical_upset_rate(
        self,
        home_team_id: str,
        before_date_ms: int,
        lookback_matches: int = 20
    ) -> Tuple[float, list]:
        """
        Ev sahibi takımın tarihsel upset oranını hesapla.
        Üst sıradaki takımlara karşı galibiyetler.
        """
        reasons = []
        
        conn = self._get_conn()
        if conn is None:
            return 0.0, reasons
        
        try:
            cursor = conn.cursor(cursor_factory=RealDictCursor)
            
            # Ev sahibi olarak oynadığı ve sıralamada geride olduğu maçlar
            query = """
            WITH home_matches AS (
                SELECT 
                    m.id,
                    m.score_home,
                    m.score_away,
                    m.home_team_id,
                    m.away_team_id
                FROM matches m
                WHERE m.home_team_id = %s
                    AND m.mst_utc < %s
                    AND m.score_home IS NOT NULL
                    AND m.score_away IS NOT NULL
                ORDER BY m.mst_utc DESC
                LIMIT %s
            )
            SELECT 
                COUNT(*) as total,
                SUM(CASE WHEN score_home > score_away THEN 1 ELSE 0 END) as wins
            FROM home_matches
            """
            
            cursor.execute(query, (home_team_id, before_date_ms, lookback_matches))
            result = cursor.fetchone()
            
            if result and result['total'] > 0:
                win_rate = result['wins'] / result['total']
                # Ev sahibi kazanma oranı yüksekse, upset potansiyeli de yüksek
                if win_rate > 0.5:
                    rate = min((win_rate - 0.4) * 0.5, 0.3)
                    reasons.append(f"📈 Güçlü ev sahibi performansı (%{int(win_rate*100)} kazanma)")
                    return rate, reasons
            
            return 0.0, reasons
            
        except Exception as e:
            print(f"[UpsetEngine] Historical query error: {e}")
            return 0.0, reasons
    
    def calculate_upset_potential(
        self,
        home_team_name: str,
        home_team_id: str,
        away_team_name: str,
        league_name: str,
        home_position: int,
        away_position: int,
        match_date_ms: int,
        is_cup_match: bool = False,
        home_matches_last_14d: int = 2,
        away_matches_last_14d: int = 2,
        home_days_rest: int = 7,
        away_days_rest: int = 7,
        away_travel_km: float = 0,
        total_teams: int = 20
    ) -> UpsetFactors:
        """
        Tüm faktörleri birleştirerek upset potansiyelini hesapla.
        
        Returns:
            UpsetFactors: Tüm faktörler ve toplam skor
        """
        factors = UpsetFactors()
        all_reasons = []
        
        # 1. Atmosfer
        atm_score, atm_reasons = self.calculate_atmosphere_score(
            home_team_name, league_name, is_cup_match
        )
        factors.atmosphere_score = atm_score
        all_reasons.extend(atm_reasons)
        
        # 2. Motivasyon
        mot_score, mot_reasons = self.calculate_motivation_score(
            home_position, away_position,
            total_teams=total_teams
        )
        factors.motivation_score = mot_score
        all_reasons.extend(mot_reasons)
        
        # 3. Yorgunluk
        fat_score, fat_reasons = self.calculate_fatigue_score(
            home_matches_last_14d, away_matches_last_14d,
            home_days_rest, away_days_rest,
            away_travel_km
        )
        factors.fatigue_score = fat_score
        all_reasons.extend(fat_reasons)
        
        # 4. Tarihsel (sadece DB varsa)
        hist_score, hist_reasons = self.get_historical_upset_rate(
            home_team_id, match_date_ms
        )
        factors.historical_upset_rate = hist_score
        all_reasons.extend(hist_reasons)
        
        # Toplam skor (weighted average)
        factors.total_upset_potential = min(
            factors.atmosphere_score * 0.25 +
            factors.motivation_score * 0.35 +
            factors.fatigue_score * 0.25 +
            factors.historical_upset_rate * 0.15,
            1.0
        )
        
        factors.reasoning = all_reasons
        
        return factors
    
    def get_features(
        self,
        home_team_name: str,
        home_team_id: str,
        away_team_name: str,
        league_name: str,
        home_position: int,
        away_position: int,
        match_date_ms: int,
        **kwargs
    ) -> Dict[str, float]:
        """
        Model için feature dict döndür.
        Training ve inference'da kullanılır.
        """
        factors = self.calculate_upset_potential(
            home_team_name=home_team_name,
            home_team_id=home_team_id,
            away_team_name=away_team_name,
            league_name=league_name,
            home_position=home_position,
            away_position=away_position,
            match_date_ms=match_date_ms,
            **kwargs
        )
        
        return {
            "upset_atmosphere": factors.atmosphere_score,
            "upset_motivation": factors.motivation_score,
            "upset_fatigue": factors.fatigue_score,
            "upset_historical": factors.historical_upset_rate,
            "upset_potential": factors.total_upset_potential,
        }


# Singleton instance
_engine_instance = None

def get_upset_engine() -> UpsetEngine:
    """Singleton pattern ile engine döndür"""
    global _engine_instance
    if _engine_instance is None:
        _engine_instance = UpsetEngine()
    return _engine_instance


# Test
if __name__ == "__main__":
    engine = get_upset_engine()
    
    # Galatasaray vs Liverpool örneği
    factors = engine.calculate_upset_potential(
        home_team_name="Galatasaray",
        home_team_id="test-gs-id",
        away_team_name="Liverpool",
        league_name="UEFA Champions League",
        home_position=12,
        away_position=1,
        match_date_ms=1700000000000,
        is_cup_match=False,
        away_matches_last_14d=5,
        home_matches_last_14d=2,
        away_days_rest=3,
        home_days_rest=7,
        away_travel_km=2800,
        total_teams=20
    )
    
    print("=" * 60)
    print("GALATASARAY vs LIVERPOOL - UPSET ANALİZİ")
    print("=" * 60)
    print(f"🏟️ Atmosfer Skoru: {factors.atmosphere_score:.2f}")
    print(f"💪 Motivasyon Skoru: {factors.motivation_score:.2f}")
    print(f"😓 Yorgunluk Skoru: {factors.fatigue_score:.2f}")
    print(f"📊 Tarihsel Skor: {factors.historical_upset_rate:.2f}")
    print(f"\n🎯 TOPLAM UPSET POTANSİYELİ: {factors.total_upset_potential:.2f}")
    print("\n📝 Sebepler:")
    for reason in factors.reasoning:
        print(f"   {reason}")
