#!/usr/bin/env python3
"""
Backtest - Analyse des performances des prédictions
Calcule ROI, précision, et métriques par type de pari
"""

import sqlite3
import os
from datetime import datetime, timedelta
from collections import defaultdict

DB_PATH = os.environ.get("DB_PATH", "/home/h3r7/turf_scraper/turf.db")


def get_db():
    return sqlite3.connect(DB_PATH)


def calculate_backtest(start_date=None, end_date=None):
    """Calcule les statistiques de backtest"""
    conn = get_db()
    
    if not start_date:
        start_date = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d')
    if not end_date:
        end_date = datetime.now().strftime('%Y-%m-%d')
    
    # Récupérer toutes les recommandations avec résultats
    query = """
        SELECT 
            r.date,
            r.race_name,
            r.type_pari,
            r.cheval1,
            r.cheval2,
            r.numero1,
            r.numero2,
            r.cote,
            r.mise,
            r.resultat,
            r.gain_potentiel,
            h.position as position_reel
        FROM recommendations r
        LEFT JOIN results h ON h.date = r.date 
            AND h.race_name LIKE '%' || SUBSTR(r.race_name, 1, 20) || '%'
            AND h.horse_name = r.cheval1
        WHERE r.resultat IS NOT NULL 
            AND r.resultat != ''
            AND r.date BETWEEN ? AND ?
    """
    
    cursor = conn.execute(query, (start_date, end_date))
    rows = cursor.fetchall()
    
    if not rows:
        conn.close()
        return {
            'summary': {
                'total_bets': 0,
                'message': 'Aucune donnée disponible pour cette période'
            }
        }
    
    # Métriques globales
    stats = {
        'total_bets': len(rows),
        'gagne': 0,
        'perdu': 0,
        'mise_totale': 0,
        'gain_total': 0,
        'by_type': defaultdict(lambda: {
            'count': 0, 'gagne': 0, 'mise': 0, 'gain': 0
        })
    }
    
    details = []
    
    for row in rows:
        date, race_name, type_pari, cheval1, cheval2, numero1, numero2, cote, mise, resultat, gain_potentiel, position = row
        
        mise = float(mise or 1)
        cote = float(cote or 1)
        
        stats['mise_totale'] += mise
        stats['by_type'][type_pari]['mise'] += mise
        
        if resultat == 'GAGNE':
            stats['gagne'] += 1
            stats['perdu'] += 0
            stats['gain_total'] += mise * cote
            stats['by_type'][type_pari]['gagne'] += 1
            stats['by_type'][type_pari]['gain'] += mise * cote
            result = 'GAGNE'
        else:
            stats['perdu'] += 1
            stats['gain_total'] += 0
            result = 'PERDU'
        
        details.append({
            'date': date,
            'race_name': race_name[:30] if race_name else '',
            'type_pari': type_pari,
            'cheval': cheval1,
            'cote': cote,
            'mise': mise,
            'resultat': result,
            'gain': mise * cote if result == 'GAGNE' else 0
        })
    
    # Calculer ROI
    roi = 0
    if stats['mise_totale'] > 0:
        roi = ((stats['gain_total'] - stats['mise_totale']) / stats['mise_totale']) * 100
    
    # Calculer précision
    precision = 0
    if stats['total_bets'] > 0:
        precision = (stats['gagne'] / stats['total_bets']) * 100
    
    # Métriques par type de pari
    by_type_results = {}
    for pari_type, data in stats['by_type'].items():
        pari_roi = 0
        if data['mise'] > 0:
            pari_roi = ((data['gain'] - data['mise']) / data['mise']) * 100
        
        pari_precision = 0
        if data['count'] > 0:
            pari_precision = (data['gagne'] / data['count']) * 100
        
        by_type_results[pari_type] = {
            'count': data['count'],
            'gagne': data['gagne'],
            'mise': data['mise'],
            'gain': data['gain'],
            'roi': round(pari_roi, 1),
            'precision': round(pari_precision, 1)
        }
    
    # Précision par rang de prédiction
    precision_by_rank = get_precision_by_rank(conn, start_date, end_date)
    
    conn.close()
    
    return {
        'period': {
            'start': start_date,
            'end': end_date
        },
        'summary': {
            'total_bets': stats['total_bets'],
            'gagne': stats['gagne'],
            'perdu': stats['perdu'],
            'precision': round(precision, 1),
            'mise_totale': round(stats['mise_totale'], 2),
            'gain_total': round(stats['gain_total'], 2),
            'roi': round(roi, 1)
        },
        'by_type': by_type_results,
        'precision_by_rank': precision_by_rank,
        'details': details[-50:]  # Last 50 bets
    }


def get_precision_by_rank(conn, start_date, end_date):
    """Calcule la précision par rang de prédiction"""
    
    query = """
        SELECT 
            p.prediction_rank,
            COUNT(*) as total,
            SUM(CASE WHEN p.prediction_rank = r.position THEN 1 ELSE 0 END) as hits,
            SUM(CASE WHEN r.position <= 3 THEN 1 ELSE 0 END) as top3
        FROM predictions p
        INNER JOIN results r ON r.date = p.date 
            AND r.horse_name = p.horse_name
        WHERE p.date BETWEEN ? AND ?
            AND p.prediction_rank > 0
            AND r.position > 0
        GROUP BY p.prediction_rank
        ORDER BY p.prediction_rank
    """
    
    cursor = conn.execute(query, (start_date, end_date))
    rows = cursor.fetchall()
    
    results = {}
    for rank, total, hits, top3 in rows:
        precision = (hits / total * 100) if total > 0 else 0
        top3_rate = (top3 / total * 100) if total > 0 else 0
        results[f'rank_{rank}'] = {
            'total': total,
            'hits': hits,
            'precision': round(precision, 1),
            'top3': top3,
            'top3_rate': round(top3_rate, 1)
        }
    
    return results


def get_daily_stats(days=30):
    """Statistiques quotidiennes sur les N derniers jours"""
    conn = get_db()
    
    end_date = datetime.now().strftime('%Y-%m-%d')
    start_date = (datetime.now() - timedelta(days=days)).strftime('%Y-%m-%d')
    
    query = """
        SELECT 
            date,
            COUNT(*) as total_bets,
            SUM(CASE WHEN resultat = 'GAGNE' THEN 1 ELSE 0 END) as gagne,
            SUM(CASE WHEN resultat = 'PERDU' THEN 1 ELSE 0 END) as perdu,
            SUM(CASE WHEN resultat = 'GAGNE' THEN mise * cote ELSE 0 END) as gains,
            SUM(mise) as mises
        FROM recommendations
        WHERE date BETWEEN ? AND ?
            AND resultat IS NOT NULL 
            AND resultat != ''
        GROUP BY date
        ORDER BY date DESC
    """
    
    cursor = conn.execute(query, (start_date, end_date))
    rows = cursor.fetchall()
    
    daily = []
    for date, total, gagne, perdu, gains, mises in rows:
        roi = ((gains - mises) / mises * 100) if mises > 0 else 0
        precision = (gagne / total * 100) if total > 0 else 0
        
        daily.append({
            'date': date,
            'total_bets': total,
            'gagne': gagne,
            'perdu': perdu,
            'precision': round(precision, 1),
            'mises': round(mises, 2),
            'gains': round(gains, 2),
            'roi': round(roi, 1)
        })
    
    conn.close()
    return daily


def get_weekly_summary():
    """Résumé hebdomadaire"""
    conn = get_db()
    
    # Semaine en cours
    today = datetime.now()
    week_start = today - timedelta(days=today.weekday())
    week_start_str = week_start.strftime('%Y-%m-%d')
    
    query = """
        SELECT 
            COUNT(*) as total,
            SUM(CASE WHEN resultat = 'GAGNE' THEN 1 ELSE 0 END) as gagne,
            SUM(mise) as mise,
            SUM(CASE WHEN resultat = 'GAGNE' THEN mise * cote ELSE 0 END) as gain
        FROM recommendations
        WHERE date >= ? AND resultat IS NOT NULL AND resultat != ''
    """
    
    cursor = conn.execute(query, (week_start_str,))
    row = cursor.fetchone()
    
    total, gagne, mise, gain = row
    
    weekly = {
        'week_start': week_start_str,
        'total_bets': total or 0,
        'gagne': gagne or 0,
        'mise': round(mise or 0, 2),
        'gain': round(gain or 0, 2),
        'roi': round(((gain - mise) / mise * 100) if mise and mise > 0 else 0, 1),
        'precision': round((gagne / total * 100) if total and total > 0 else 0, 1)
    }
    
    # Semaine dernière
    last_week_start = week_start - timedelta(days=7)
    last_week_end = week_start - timedelta(days=1)
    
    query = """
        SELECT 
            COUNT(*) as total,
            SUM(CASE WHEN resultat = 'GAGNE' THEN 1 ELSE 0 END) as gagne,
            SUM(mise) as mise,
            SUM(CASE WHEN resultat = 'GAGNE' THEN mise * cote ELSE 0 END) as gain
        FROM recommendations
        WHERE date BETWEEN ? AND ?
            AND resultat IS NOT NULL 
            AND resultat != ''
    """
    
    cursor = conn.execute(query, (last_week_start.strftime('%Y-%m-%d'), last_week_end.strftime('%Y-%m-%d')))
    row = cursor.fetchone()
    
    total, gagne, mise, gain = row
    
    weekly['last_week'] = {
        'total_bets': total or 0,
        'gagne': gagne or 0,
        'mise': round(mise or 0, 2),
        'gain': round(gain or 0, 2),
        'roi': round(((gain - mise) / mise * 100) if mise and mise > 0 else 0, 1),
        'precision': round((gagne / total * 100) if total and total > 0 else 0, 1)
    }
    
    conn.close()
    return weekly


if __name__ == "__main__":
    import json
    
    print("="*60)
    print("BACKTEST - Analyse des performances")
    print("="*60)
    
    # Test
    result = calculate_backtest()
    print(json.dumps(result, indent=2, default=str))
