"""
Referee Engine - V9 Feature
Hakem profilleri ve maç etki analizi.

Analiz Edilen Metrikler:
- Ortalama kart sayısı (sarı/kırmızı)
- Penaltı verme eğilimi
- Ev sahibi lehine karar oranı
- Maç başına toplam gol ortalaması
"""

import os
from typing import Dict, Optional, List
from dataclasses import dataclass, field
from datetime import datetime

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


@dataclass
class RefereeProfile:
    """Hakem profili"""
    referee_name: str
    matches_count: int = 0
    
    # Kart istatistikleri
    avg_yellow_cards: float = 0.0
    avg_red_cards: float = 0.0
    total_cards_per_match: float = 0.0
    
    # Penaltı istatistikleri
    penalty_rate: float = 0.0  # Penaltı verdiği maç oranı
    
    # Ev sahibi eğilimi
    home_win_rate: float = 0.0
    home_bias: float = 0.0  # -1 (away bias) to +1 (home bias)
    
    # Gol istatistikleri
    avg_goals_per_match: float = 0.0
    over_25_rate: float = 0.0


@dataclass
class RefereeFeatures:
    """Model için hakem feature'ları"""
    referee_name: str = ""
    referee_matches: int = 0
    referee_avg_yellow: float = 0.0
    referee_avg_red: float = 0.0
    referee_cards_total: float = 0.0
    referee_penalty_rate: float = 0.0
    referee_home_bias: float = 0.0
    referee_avg_goals: float = 0.0
    referee_over25_rate: float = 0.0
    referee_experience: float = 0.0  # 0-1 normalized
    
    def to_dict(self) -> Dict[str, float]:
        return {
            'referee_matches': float(self.referee_matches),
            'referee_avg_yellow': self.referee_avg_yellow,
            'referee_avg_red': self.referee_avg_red,
            'referee_cards_total': self.referee_cards_total,
            'referee_penalty_rate': self.referee_penalty_rate,
            'referee_home_bias': self.referee_home_bias,
            'referee_avg_goals': self.referee_avg_goals,
            'referee_over25_rate': self.referee_over25_rate,
            'referee_experience': self.referee_experience,
        }


class RefereeEngine:
    """
    Hakem analiz motoru.
    
    Hakemlerin geçmiş maçlarını analiz ederek:
    - Kart eğilimlerini
    - Ev sahibi bias'ını
    - Gol ortalamasını
    hesaplar.
    """
    
    # Ana hakem rolü ID'si (genellikle 1 veya "Hakem")
    MAIN_REFEREE_ROLE_ID = 1
    
    def __init__(self):
        self.conn = None
        self._referee_cache: Dict[str, RefereeProfile] = {}
        self._cache_loaded = False
    
    def _connect_db(self):
        if psycopg2 is None:
            return None
        try:
            from data.db import get_clean_dsn
            self.conn = psycopg2.connect(get_clean_dsn())
            return self.conn
        except Exception as e:
            print(f"[RefereeEngine] DB connection failed: {e}")
            return None
    
    def get_conn(self):
        if self.conn is None or self.conn.closed:
            self._connect_db()
        return self.conn
    
    def _get_main_referee_role_id(self) -> int:
        """Ana hakem rolü ID'sini bul"""
        conn = self.get_conn()
        if conn is None:
            return self.MAIN_REFEREE_ROLE_ID
        
        try:
            with conn.cursor() as cur:
                cur.execute("""
                    SELECT id FROM official_roles 
                    WHERE LOWER(name) LIKE '%%hakem%%' 
                      AND LOWER(name) NOT LIKE '%%yardımcı%%'
                      AND LOWER(name) NOT LIKE '%%dördüncü%%'
                    LIMIT 1
                """)
                result = cur.fetchone()
                if result:
                    return result[0]
        except Exception:
            pass
        
        return self.MAIN_REFEREE_ROLE_ID
    
    def get_referee_for_match(self, match_id: str) -> Optional[str]:
        """Maçın ana hakemini bul"""
        conn = self.get_conn()
        if conn is None:
            return None
        
        try:
            main_role_id = self._get_main_referee_role_id()
            
            with conn.cursor() as cur:
                cur.execute("""
                    SELECT name FROM match_officials
                    WHERE match_id = %s AND role_id = %s
                    LIMIT 1
                """, (match_id, main_role_id))
                result = cur.fetchone()
                return result[0] if result else None
        except Exception as e:
            print(f"[RefereeEngine] Error getting referee: {e}")
            return None
    
    def calculate_referee_profile(self, referee_name: str, league_id: str = None) -> RefereeProfile:
        """Hakemin maçlarını analiz et. league_id verilirse sadece o ligteki maçları kullanır."""
        
        # Composite cache key — aynı isim farklı liglerde farklı profil
        cache_key = (referee_name, league_id)
        if cache_key in self._referee_cache:
            return self._referee_cache[cache_key]
        
        profile = RefereeProfile(referee_name=referee_name)
        
        conn = self.get_conn()
        if conn is None:
            return profile
        
        try:
            main_role_id = self._get_main_referee_role_id()
            
            with conn.cursor(cursor_factory=RealDictCursor) as cur:
                # Bu hakemin yönettiği maçları al (league_id varsa sadece o lig)
                if league_id:
                    cur.execute("""
                        SELECT m.id, m.score_home, m.score_away, m.home_team_id, m.away_team_id
                        FROM matches m
                        JOIN match_officials mo ON m.id = mo.match_id
                        WHERE mo.name = %s 
                          AND mo.role_id = %s
                          AND m.league_id = %s
                          AND m.score_home IS NOT NULL 
                          AND m.score_away IS NOT NULL
                        ORDER BY m.mst_utc DESC
                        LIMIT 100
                    """, (referee_name, main_role_id, league_id))
                else:
                    cur.execute("""
                        SELECT m.id, m.score_home, m.score_away, m.home_team_id, m.away_team_id
                        FROM matches m
                        JOIN match_officials mo ON m.id = mo.match_id
                        WHERE mo.name = %s 
                          AND mo.role_id = %s
                          AND m.score_home IS NOT NULL 
                          AND m.score_away IS NOT NULL
                        ORDER BY m.mst_utc DESC
                        LIMIT 100
                    """, (referee_name, main_role_id))
                
                matches = cur.fetchall()
                profile.matches_count = len(matches)
                
                if profile.matches_count == 0:
                    return profile
                
                match_ids = [m['id'] for m in matches]
                
                # Kart istatistikleri
                cur.execute("""
                    SELECT 
                        COUNT(*) FILTER (WHERE event_subtype ILIKE '%%yellow%%') as yellow_count,
                        COUNT(*) FILTER (WHERE event_subtype ILIKE '%%red%%' OR event_subtype ILIKE '%%second%%') as red_count
                    FROM match_player_events
                    WHERE match_id = ANY(%s) AND event_type = 'card'
                """, (match_ids,))
                
                card_stats = cur.fetchone()
                if card_stats:
                    profile.avg_yellow_cards = (card_stats['yellow_count'] or 0) / profile.matches_count
                    profile.avg_red_cards = (card_stats['red_count'] or 0) / profile.matches_count
                    profile.total_cards_per_match = profile.avg_yellow_cards + profile.avg_red_cards
                
                # Penaltı istatistikleri
                cur.execute("""
                    SELECT COUNT(DISTINCT match_id) as penalty_matches
                    FROM match_player_events
                    WHERE match_id = ANY(%s) 
                      AND event_type = 'goal' 
                      AND event_subtype ILIKE '%%penaltı%%'
                """, (match_ids,))
                
                penalty_stats = cur.fetchone()
                if penalty_stats:
                    profile.penalty_rate = (penalty_stats['penalty_matches'] or 0) / profile.matches_count
                
                # Ev sahibi eğilimi ve gol ortalaması
                home_wins = 0
                away_wins = 0
                draws = 0
                total_goals = 0
                over_25_count = 0
                
                for m in matches:
                    goals = (m['score_home'] or 0) + (m['score_away'] or 0)
                    total_goals += goals
                    
                    if goals > 2.5:
                        over_25_count += 1
                    
                    if m['score_home'] > m['score_away']:
                        home_wins += 1
                    elif m['score_home'] < m['score_away']:
                        away_wins += 1
                    else:
                        draws += 1
                
                profile.avg_goals_per_match = total_goals / profile.matches_count
                profile.over_25_rate = over_25_count / profile.matches_count
                profile.home_win_rate = home_wins / profile.matches_count
                
                # Home bias: -1 (away favors) to +1 (home favors)
                # Normal lig ortalaması ~%46 ev sahibi, buna göre normalize
                expected_home_rate = 0.46
                profile.home_bias = (profile.home_win_rate - expected_home_rate) * 2
                profile.home_bias = max(-1, min(1, profile.home_bias))
            
            # Cache'e ekle
            self._referee_cache[cache_key] = profile
            return profile
            
        except Exception as e:
            print(f"[RefereeEngine] Error calculating profile: {e}")
            return profile
    
    def get_features(self, match_id: str, league_id: str = None) -> Dict[str, float]:
        """
        Maç için hakem feature'larını hesapla.
        
        Args:
            match_id: Maç ID'si
            league_id: Lig ID'si (opsiyonel — isim çakışmalarını önlemek için)
            
        Returns:
            Hakem feature'ları dict olarak
        """
        features = RefereeFeatures()
        
        # Hakemi bul
        referee_name = self.get_referee_for_match(match_id)
        if referee_name is None:
            return features.to_dict()
        
        features.referee_name = referee_name
        
        # Profili hesapla (league_id ile scope'lanmış)
        profile = self.calculate_referee_profile(referee_name, league_id=league_id)
        
        features.referee_matches = profile.matches_count
        features.referee_avg_yellow = profile.avg_yellow_cards
        features.referee_avg_red = profile.avg_red_cards
        features.referee_cards_total = profile.total_cards_per_match
        features.referee_penalty_rate = profile.penalty_rate
        features.referee_home_bias = profile.home_bias
        features.referee_avg_goals = profile.avg_goals_per_match
        features.referee_over25_rate = profile.over_25_rate
        
        # Deneyim: 50+ maç = 1.0, 0 maç = 0.0
        features.referee_experience = min(profile.matches_count / 50, 1.0)
        
        return features.to_dict()
    
    def get_features_by_name(self, referee_name: str, league_id: str = None) -> Dict[str, float]:
        """
        Hakem ismiyle feature'ları hesapla.
        
        Args:
            referee_name: Hakem ismi
            league_id: Lig ID'si (opsiyonel — isim çakışmalarını önlemek için)
            
        Returns:
            Hakem feature'ları dict olarak
        """
        features = RefereeFeatures()
        
        if not referee_name:
            return features.to_dict()
        
        features.referee_name = referee_name
        profile = self.calculate_referee_profile(referee_name, league_id=league_id)
        
        features.referee_matches = profile.matches_count
        features.referee_avg_yellow = profile.avg_yellow_cards
        features.referee_avg_red = profile.avg_red_cards
        features.referee_cards_total = profile.total_cards_per_match
        features.referee_penalty_rate = profile.penalty_rate
        features.referee_home_bias = profile.home_bias
        features.referee_avg_goals = profile.avg_goals_per_match
        features.referee_over25_rate = profile.over_25_rate
        features.referee_experience = min(profile.matches_count / 50, 1.0)
        
        return features.to_dict()


# Singleton instance
_engine: Optional[RefereeEngine] = None


def get_referee_engine() -> RefereeEngine:
    """Singleton referee engine instance döndür"""
    global _engine
    if _engine is None:
        _engine = RefereeEngine()
    return _engine


if __name__ == "__main__":
    # Test
    engine = get_referee_engine()
    
    print("\n🧪 Referee Engine Test")
    print("=" * 50)
    
    # Test with a known referee name
    test_referee = "Cüneyt Çakır"
    features = engine.get_features_by_name(test_referee)
    
    print(f"\n📊 Hakem: {test_referee}")
    for key, value in features.items():
        print(f"   {key}: {value:.3f}")
