"""
VQWEN Final Backtest
====================
Tests the Final Model (ELO + Rest + Context).
"""

import os
import sys
import json
import pickle
import pandas as pd
import numpy as np
import psycopg2
from psycopg2.extras import RealDictCursor

AI_DIR = os.path.dirname(os.path.abspath(__file__))
ROOT_DIR = os.path.dirname(AI_DIR)
PROJECT_ROOT = os.path.dirname(ROOT_DIR)

def get_clean_dsn() -> str:
    return "postgresql://suggestbet:SuGGesT2026SecuRe@localhost:15432/boilerplate_db"

def run_final_backtest():
    print("🧠 VQWEN FINAL BACKTEST (ELO + REST)")
    print("="*60)
    
    # Load Models
    mdir = os.path.join(ROOT_DIR, 'models', 'vqwen')
    try:
        with open(os.path.join(mdir, 'vqwen_ms.pkl'), 'rb') as f: model_ms = pickle.load(f)
        with open(os.path.join(mdir, 'vqwen_ou25.pkl'), 'rb') as f: model_ou = pickle.load(f)
        with open(os.path.join(mdir, 'vqwen_btts.pkl'), 'rb') as f: model_btts = pickle.load(f)
        print("✅ VQWEN Final modelleri yüklendi.")
    except Exception as e:
        print(f"❌ Model hatası: {e}")
        return

    with open(os.path.join(PROJECT_ROOT, "top_leagues.json"), 'r') as f:
        league_ids = tuple(str(lid) for lid in json.load(f))

    dsn = get_clean_dsn()
    conn = psycopg2.connect(dsn)
    cur = conn.cursor(cursor_factory=RealDictCursor)

    cur.execute("""
        SELECT m.id, m.home_team_id, m.away_team_id, m.score_home, m.score_away,
               m.mst_utc,
               t1.name as home_team, t2.name as away_team,
               maf.home_elo, maf.away_elo,
               COALESCE((SELECT AVG(m2.score_home) FROM matches m2 WHERE m2.home_team_id = m.home_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc), 1.2) as h_home_goals,
               COALESCE((SELECT AVG(m2.score_away) FROM matches m2 WHERE m2.away_team_id = m.away_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc), 1.2) as a_away_goals,
               COALESCE(EXTRACT(EPOCH FROM (to_timestamp(m.mst_utc/1000) - (SELECT MAX(to_timestamp(m2.mst_utc/1000)) FROM matches m2 WHERE m2.home_team_id = m.home_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc)) / 86400), 7) as h_rest,
               COALESCE(EXTRACT(EPOCH FROM (to_timestamp(m.mst_utc/1000) - (SELECT MAX(to_timestamp(m2.mst_utc/1000)) FROM matches m2 WHERE m2.away_team_id = m.away_team_id AND m2.status = 'FT' AND m2.mst_utc < m.mst_utc)) / 86400), 7) as a_rest,
               COALESCE((SELECT COUNT(*) FROM match_player_participation mp WHERE mp.match_id = m.id AND mp.team_id = m.home_team_id AND mp.is_starting = true), 11) as h_xi,
               COALESCE((SELECT COUNT(*) FROM match_player_participation mp WHERE mp.match_id = m.id AND mp.team_id = m.away_team_id AND mp.is_starting = true), 11) as a_xi,
               COALESCE((SELECT COUNT(*) FROM match_player_events mpe WHERE mpe.match_id = m.id AND mpe.event_type = 'card'), 4) as cards,
               (SELECT os.odd_value FROM odd_categories oc JOIN odd_selections os ON os.odd_category_db_id = oc.db_id WHERE oc.match_id = m.id AND oc.name ILIKE 'Maç Sonucu' AND os.name = '1' LIMIT 1) as oh,
               (SELECT os.odd_value FROM odd_categories oc JOIN odd_selections os ON os.odd_category_db_id = oc.db_id WHERE oc.match_id = m.id AND oc.name ILIKE 'Maç Sonucu' AND os.name = 'X' LIMIT 1) as od,
               (SELECT os.odd_value FROM odd_categories oc JOIN odd_selections os ON os.odd_category_db_id = oc.db_id WHERE oc.match_id = m.id AND oc.name ILIKE 'Maç Sonucu' AND os.name = '2' LIMIT 1) as oa
        FROM matches m
        LEFT JOIN teams t1 ON m.home_team_id = t1.id
        LEFT JOIN teams t2 ON m.away_team_id = t2.id
        LEFT JOIN football_ai_features maf ON maf.match_id = m.id
        WHERE m.league_id IN %s AND m.status = 'FT' AND m.score_home IS NOT NULL
        ORDER BY m.mst_utc DESC
        LIMIT 1000
    """, (league_ids,))
    
    rows = cur.fetchall()
    print(f"📊 {len(rows)} maç analiz ediliyor...")

    results = {'ms': {'bet': 0, 'won': 0, 'profit': 0}, 'ou25': {'bet': 0, 'won': 0, 'profit': 0}, 'btts': {'bet': 0, 'won': 0, 'profit': 0}}

    for row in rows:
        oh = float(row['oh'] or 0)
        od = float(row['od'] or 0)
        oa = float(row['oa'] or 0)
        if oh <= 1.0 or od <= 1.0 or oa <= 1.0: continue

        # Features
        h_elo = float(row['home_elo'] or 1500)
        a_elo = float(row['away_elo'] or 1500)
        h_home_goals = float(row['h_home_goals'] or 1.2)
        a_away_goals = float(row['a_away_goals'] or 1.2)
        h_rest = float(row['h_rest'] or 7)
        a_rest = float(row['a_rest'] or 7)
        h_xi = float(row['h_xi'] or 11)
        a_xi = float(row['a_xi'] or 11)
        cards = float(row['cards'] or 4)

        def fatigue(rest):
            if rest < 3: return 0.85
            if rest < 5: return 0.95
            return 1.0

        h_fat = fatigue(h_rest)
        a_fat = fatigue(a_rest)

        h_xg = h_home_goals * h_fat
        a_xg = a_away_goals * a_fat
        total_xg = h_xg + a_xg
        
        margin = (1/oh) + (1/od) + (1/oa)
        f = pd.DataFrame([{
            'elo_diff': h_elo - a_elo,
            'h_xg': h_xg, 'a_xg': a_xg,
            'total_xg': total_xg,
            'pow_diff': (h_elo/100)*h_fat - (a_elo/100)*a_fat,
            'rest_diff': h_rest - a_rest,
            'h_fatigue': h_fat, 'a_fatigue': a_fat,
            'imp_h': (1/oh)/margin, 'imp_d': (1/od)/margin, 'imp_a': (1/oa)/margin,
            'h_xi': h_xi, 'a_xi': a_xi,
            'cards': cards
        }])

        # MS
        ms_probs = model_ms.predict(f)[0]
        for i, (pick, prob, odd) in enumerate(zip(['1', 'X', '2'], ms_probs, [oh, od, oa])):
            if odd <= 1.0: continue
            edge = prob - (1/odd)
            if edge > 0.05 and prob > 0.45:
                results['ms']['bet'] += 1
                h, a = row['score_home'], row['score_away']
                w = (pick=='1' and h>a) or (pick=='X' and h==a) or (pick=='2' and a>h)
                if w: results['ms']['won'] += 1; results['ms']['profit'] += (odd - 1.0)
                else: results['ms']['profit'] -= 1.0
                break

        # OU2.5
        p_over = float(model_ou.predict(f)[0])
        if p_over > 0.55:
            results['ou25']['bet'] += 1
            if (row['score_home'] + row['score_away']) > 2.5: results['ou25']['won'] += 1; results['ou25']['profit'] += 0.85
            else: results['ou25']['profit'] -= 1.0

        # BTTS
        p_btts = float(model_btts.predict(f)[0])
        if p_btts > 0.55:
            results['btts']['bet'] += 1
            if row['score_home'] > 0 and row['score_away'] > 0: results['btts']['won'] += 1; results['btts']['profit'] += 0.85
            else: results['btts']['profit'] -= 1.0

    print("\n" + "="*60)
    print("📊 VQWEN FINAL SONUÇLAR")
    print("="*60)
    for mkt in ['ms', 'ou25', 'btts']:
        r = results[mkt]
        wr = (r['won'] / r['bet'] * 100) if r['bet'] > 0 else 0
        print(f"{mkt.upper():<10} Oyn: {r['bet']:<5} Kaz: {r['won']:<5} WR: {wr:.1f}%  Kâr: {r['profit']:+.2f}")
    
    total = sum(r['profit'] for r in results.values())
    print(f"\n💰 TOPLAM: {total:+.2f} Units")
    print("🟢 PARA KAZANDIK!" if total > 0 else "🔴 ZARARDA")

    cur.close()
    conn.close()

if __name__ == "__main__":
    run_final_backtest()
