"""
Head-to-Head (H2H) Feature Engine
Takımların birbirine karşı geçmiş performansını analiz eder.
"""

import os
import psycopg2
from typing import Dict, Optional, Tuple
from dataclasses import dataclass
from functools import lru_cache

import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from data.db import get_clean_dsn


@dataclass
class H2HProfile:
    """Head-to-Head analiz sonucu"""
    total_matches: int
    home_wins: int
    draws: int
    away_wins: int
    home_goals_total: int
    away_goals_total: int
    btts_count: int  # Both teams to score
    over25_count: int
    
    @property
    def home_win_rate(self) -> float:
        return self.home_wins / self.total_matches if self.total_matches > 0 else 0.33
    
    @property
    def draw_rate(self) -> float:
        return self.draws / self.total_matches if self.total_matches > 0 else 0.33
    
    @property
    def away_win_rate(self) -> float:
        return self.away_wins / self.total_matches if self.total_matches > 0 else 0.33
    
    @property
    def avg_total_goals(self) -> float:
        return (self.home_goals_total + self.away_goals_total) / self.total_matches if self.total_matches > 0 else 2.5
    
    @property
    def btts_rate(self) -> float:
        return self.btts_count / self.total_matches if self.total_matches > 0 else 0.5
    
    @property
    def over25_rate(self) -> float:
        return self.over25_count / self.total_matches if self.total_matches > 0 else 0.5
    
    @property
    def home_dominance(self) -> float:
        """Ev sahibinin üstünlük skoru (-1 ile 1 arası)"""
        if self.total_matches == 0:
            return 0
        return (self.home_wins - self.away_wins) / self.total_matches
    
    def to_features(self) -> Dict[str, float]:
        """Feature dictionary döndür"""
        return {
            'h2h_total_matches': self.total_matches,
            'h2h_home_win_rate': self.home_win_rate,
            'h2h_draw_rate': self.draw_rate,
            'h2h_away_win_rate': self.away_win_rate,
            'h2h_avg_goals': self.avg_total_goals,
            'h2h_btts_rate': self.btts_rate,
            'h2h_over25_rate': self.over25_rate,
            'h2h_home_dominance': self.home_dominance,
        }


class H2HFeatureEngine:
    """
    Head-to-Head Feature Engine
    
    İki takım arasındaki geçmiş karşılaşmaları analiz eder.
    """
    
    def __init__(self):
        self.conn = None
        self._cache: Dict[Tuple[str, str], H2HProfile] = {}
    
    def get_conn(self):
        if self.conn is None or self.conn.closed:
            self.conn = psycopg2.connect(get_clean_dsn())
        return self.conn
    
    def get_h2h_profile(self, home_team_id: str, away_team_id: str, 
                        before_date: Optional[int] = None, 
                        limit: int = 20) -> H2HProfile:
        """
        İki takım arasındaki geçmiş karşılaşmaları analiz et.
        
        Args:
            home_team_id: Ev sahibi takım ID
            away_team_id: Deplasman takım ID
            before_date: Bu tarihten önceki maçlar (mst_utc, milliseconds)
            limit: Kaç maç geriye bakılacak
            
        Returns:
            H2HProfile: Head-to-head analiz sonucu
        """
        cache_key = (home_team_id, away_team_id)
        
        # Cache kontrolü (before_date yoksa)
        if before_date is None and cache_key in self._cache:
            return self._cache[cache_key]
        
        conn = self.get_conn()
        cur = conn.cursor()
        
        # Her iki yöndeki karşılaşmaları al
        # (A evde B deplasman + B evde A deplasman)
        query = """
            SELECT 
                home_team_id, away_team_id,
                score_home, score_away
            FROM matches
            WHERE (
                (home_team_id = %s AND away_team_id = %s)
                OR 
                (home_team_id = %s AND away_team_id = %s)
            )
            AND score_home IS NOT NULL
            AND score_away IS NOT NULL
        """
        
        params = [home_team_id, away_team_id, away_team_id, home_team_id]
        
        if before_date:
            query += " AND mst_utc < %s"
            params.append(before_date)
        
        query += " ORDER BY mst_utc DESC LIMIT %s"
        params.append(limit)
        
        cur.execute(query, params)
        matches = cur.fetchall()
        
        if not matches:
            return H2HProfile(
                total_matches=0, home_wins=0, draws=0, away_wins=0,
                home_goals_total=0, away_goals_total=0,
                btts_count=0, over25_count=0
            )
        
        # İstatistikleri hesapla
        home_wins = 0
        draws = 0
        away_wins = 0
        home_goals = 0
        away_goals = 0
        btts = 0
        over25 = 0
        
        for match in matches:
            m_home_id, m_away_id, score_h, score_a = match
            
            # Perspektifi normalize et (istenen takım açısından)
            if m_home_id == home_team_id:
                # Normal sıralama
                h_score, a_score = score_h, score_a
            else:
                # Ters sıralama (rakip evde oynamış)
                h_score, a_score = score_a, score_h
            
            # Sonuç
            if h_score > a_score:
                home_wins += 1
            elif h_score < a_score:
                away_wins += 1
            else:
                draws += 1
            
            # Goller
            home_goals += h_score
            away_goals += a_score
            
            # BTTS
            if h_score > 0 and a_score > 0:
                btts += 1
            
            # Over 2.5
            if h_score + a_score > 2.5:
                over25 += 1
        
        profile = H2HProfile(
            total_matches=len(matches),
            home_wins=home_wins,
            draws=draws,
            away_wins=away_wins,
            home_goals_total=home_goals,
            away_goals_total=away_goals,
            btts_count=btts,
            over25_count=over25
        )
        
        # Cache'e kaydet
        if before_date is None:
            self._cache[cache_key] = profile
        
        return profile
    
    def get_features(self, home_team_id: str, away_team_id: str, 
                     before_date: Optional[int] = None) -> Dict[str, float]:
        """Feature dictionary döndür"""
        profile = self.get_h2h_profile(home_team_id, away_team_id, before_date)
        return profile.to_features()
    
    def get_momentum(self, home_team_id: str, away_team_id: str,
                     before_date: Optional[int] = None) -> Dict[str, float]:
        """
        Son karşılaşmalardaki momentum/trend analizi.
        Son 5 maçtaki trend'e bakar.
        """
        profile = self.get_h2h_profile(home_team_id, away_team_id, before_date, limit=5)
        
        # Streak hesapla (ardışık sonuçlar)
        conn = self.get_conn()
        cur = conn.cursor()
        
        query = """
            SELECT home_team_id, score_home, score_away
            FROM matches
            WHERE (
                (home_team_id = %s AND away_team_id = %s)
                OR 
                (home_team_id = %s AND away_team_id = %s)
            )
            AND score_home IS NOT NULL
        """
        params = [home_team_id, away_team_id, away_team_id, home_team_id]
        if before_date:
            query += " AND mst_utc < %s"
            params.append(before_date)
        query += " ORDER BY mst_utc DESC LIMIT 5"
        
        cur.execute(query, params)
        recent = cur.fetchall()
        
        streak = 0
        streak_type = None  # 'home', 'away', 'draw'
        
        for match in recent:
            m_home_id, score_h, score_a = match
            
            # Perspektifi normalize et
            if m_home_id == home_team_id:
                result = 'home' if score_h > score_a else ('away' if score_h < score_a else 'draw')
            else:
                result = 'away' if score_h > score_a else ('home' if score_h < score_a else 'draw')
            
            if streak_type is None:
                streak_type = result
                streak = 1
            elif result == streak_type:
                streak += 1
            else:
                break
        
        return {
            'h2h_recent_home_dominance': profile.home_dominance,
            'h2h_streak_length': streak,
            'h2h_streak_home': 1 if streak_type == 'home' else 0,
            'h2h_streak_away': 1 if streak_type == 'away' else 0,
            'h2h_streak_draw': 1 if streak_type == 'draw' else 0,
        }


# Singleton
_engine = None

def get_h2h_engine() -> H2HFeatureEngine:
    global _engine
    if _engine is None:
        _engine = H2HFeatureEngine()
    return _engine


if __name__ == "__main__":
    # Test
    engine = get_h2h_engine()
    
    # Örnek: Fenerbahçe vs Galatasaray (ID'leri bulunmalı)
    # Test için veritabanından bir karşılaşma çekelim
    conn = engine.get_conn()
    cur = conn.cursor()
    cur.execute("""
        SELECT home_team_id, away_team_id, match_name
        FROM matches
        WHERE score_home IS NOT NULL
        LIMIT 1
    """)
    result = cur.fetchone()
    
    if result:
        home_id, away_id, name = result
        print(f"\n🧪 Test: {name}")
        print(f"   Home ID: {home_id}")
        print(f"   Away ID: {away_id}")
        
        profile = engine.get_h2h_profile(home_id, away_id)
        print(f"\n📊 H2H Profil:")
        print(f"   Toplam Maç: {profile.total_matches}")
        print(f"   Ev Sahibi Kazanma: {profile.home_win_rate:.1%}")
        print(f"   Beraberlik: {profile.draw_rate:.1%}")
        print(f"   Deplasman Kazanma: {profile.away_win_rate:.1%}")
        print(f"   Ortalama Gol: {profile.avg_total_goals:.2f}")
        print(f"   BTTS Oranı: {profile.btts_rate:.1%}")
        print(f"   Üst 2.5 Oranı: {profile.over25_rate:.1%}")
        print(f"   Ev Dominance: {profile.home_dominance:+.2f}")
        
        features = engine.get_features(home_id, away_id)
        print(f"\n🔧 Features: {features}")
