#!/usr/bin/env python3
"""
BetPredictAI - Historical Betting Slips Generator
Genera bollette storiche basate sui 400 match di verifica
Calcola profitto/perdita reale basato sulle quote simulate
"""

import json
import os
from datetime import datetime, timedelta
from collections import defaultdict
import random

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
DATA_DIR = os.path.join(BASE_DIR, '..', 'data')

# League flags
LEAGUE_FLAGS = {
    'E0': '🏴󠁧󠁢󠁥󠁮󠁧󠁿',
    'D1': '🇩🇪',
    'I1': '🇮🇹',
    'SP1': '🇪🇸',
    'F1': '🇫🇷'
}

LEAGUE_NAMES = {
    'E0': 'Premier League',
    'D1': 'Bundesliga',
    'I1': 'Serie A',
    'SP1': 'La Liga',
    'F1': 'Ligue 1'
}


def calculate_odds(prediction, home_prob, draw_prob, away_prob, correct):
    """
    Calcola quote realistiche basate sulle probabilità
    Quote più alte per eventi meno probabili
    """
    prob_map = {
        'HOME': home_prob / 100,
        'DRAW': draw_prob / 100,
        'AWAY': away_prob / 100
    }

    prob = prob_map.get(prediction, 0.33)

    # Calcola quota base (1/prob) con margine bookmaker 5-10%
    if prob > 0:
        base_odds = 1 / prob
        margin = random.uniform(0.92, 0.96)  # Margine bookmaker
        odds = round(base_odds * margin, 2)
        odds = max(1.10, min(odds, 15.00))  # Limiti realistici
    else:
        odds = 3.00

    return odds


def group_matches_by_date(results):
    """Raggruppa i match per data"""
    by_date = defaultdict(list)
    for match in results:
        by_date[match['date']].append(match)
    return dict(sorted(by_date.items()))


def calculate_slip_stake():
    """Puntata standard per ogni bolletta"""
    return 10.0  # €10 per bolletta


def generate_daily_slips(matches_by_date, min_confidence=55, max_selections=4):
    """
    Genera bollette giornaliere
    - Seleziona solo match con confidence >= min_confidence
    - Massimo max_selections per bolletta
    - Priorità ai match con confidence più alta
    """
    slips = []
    slip_id = 1

    for date, matches in matches_by_date.items():
        # Filtra match con confidence sufficiente
        high_conf_matches = [m for m in matches if m['confidence'] >= min_confidence]

        if len(high_conf_matches) < 2:
            continue  # Skip giorni con meno di 2 match validi

        # Ordina per confidence decrescente
        high_conf_matches.sort(key=lambda x: x['confidence'], reverse=True)

        # Prendi i migliori match (max_selections)
        selected = high_conf_matches[:max_selections]

        # Crea bolletta
        slip_matches = []
        total_odds = 1.0
        all_correct = True

        for match in selected:
            odds = calculate_odds(
                match['predicted'],
                match['home_prob'],
                match['draw_prob'],
                match['away_prob'],
                match['correct']
            )

            total_odds *= odds
            if not match['correct']:
                all_correct = False

            slip_matches.append({
                'id': f"h_{match['home_team']}_{match['away_team']}_{match['date']}",
                'home_team': match['home_team'],
                'away_team': match['away_team'],
                'league': match['league'],
                'league_name': match['league_name'],
                'flag': LEAGUE_FLAGS.get(match['league'], '⚽'),
                'date': match['date'],
                'time': match.get('time', '15:00'),
                'prediction': match['predicted'],
                'predicted_sign': '1' if match['predicted'] == 'HOME' else ('X' if match['predicted'] == 'DRAW' else '2'),
                'actual_result': match['actual'],
                'actual_sign': '1' if match['actual'] == 'HOME' else ('X' if match['actual'] == 'DRAW' else '2'),
                'home_goals': match['home_goals'],
                'away_goals': match['away_goals'],
                'confidence': match['confidence'],
                'odds': odds,
                'is_correct': match['correct'],
                'home_prob': match['home_prob'],
                'draw_prob': match['draw_prob'],
                'away_prob': match['away_prob']
            })

        stake = calculate_slip_stake()
        potential_win = round(stake * total_odds, 2)
        actual_win = potential_win if all_correct else 0
        profit = actual_win - stake

        # Calcola probabilità combinata
        win_probability = 1.0
        for m in slip_matches:
            prob_map = {'HOME': m['home_prob'], 'DRAW': m['draw_prob'], 'AWAY': m['away_prob']}
            win_probability *= prob_map[m['prediction']] / 100

        slip = {
            'id': f"SLIP-{date.replace('-', '')}-{slip_id:03d}",
            'date': date,
            'created_at': f"{date}T12:00:00",
            'strategy': f"AI High Confidence (>={min_confidence}%)",
            'matches': slip_matches,
            'total_odds': round(total_odds, 2),
            'stake': stake,
            'potential_win': potential_win,
            'win_probability': round(win_probability * 100, 2),
            'status': 'won' if all_correct else 'lost',
            'actual_win': actual_win,
            'profit': profit,
            'correct_predictions': sum(1 for m in slip_matches if m['is_correct']),
            'total_predictions': len(slip_matches)
        }

        slips.append(slip)
        slip_id += 1

    return slips


def calculate_statistics(slips):
    """Calcola statistiche aggregate"""
    total_slips = len(slips)
    won_slips = sum(1 for s in slips if s['status'] == 'won')
    lost_slips = sum(1 for s in slips if s['status'] == 'lost')

    total_staked = sum(s['stake'] for s in slips)
    total_won = sum(s['actual_win'] for s in slips)
    total_profit = sum(s['profit'] for s in slips)

    win_rate = (won_slips / total_slips * 100) if total_slips > 0 else 0
    roi = (total_profit / total_staked * 100) if total_staked > 0 else 0

    # Calcola streak
    current_streak = 0
    max_win_streak = 0
    max_loss_streak = 0
    temp_streak = 0
    last_status = None

    for slip in sorted(slips, key=lambda x: x['date']):
        if slip['status'] == last_status:
            temp_streak += 1
        else:
            if last_status == 'won':
                max_win_streak = max(max_win_streak, temp_streak)
            elif last_status == 'lost':
                max_loss_streak = max(max_loss_streak, temp_streak)
            temp_streak = 1
        last_status = slip['status']

    # Final streak
    if last_status == 'won':
        max_win_streak = max(max_win_streak, temp_streak)
        current_streak = temp_streak
    elif last_status == 'lost':
        max_loss_streak = max(max_loss_streak, temp_streak)
        current_streak = -temp_streak

    # Statistiche per lega
    by_league = defaultdict(lambda: {'won': 0, 'lost': 0, 'profit': 0, 'staked': 0})
    for slip in slips:
        for match in slip['matches']:
            league = match['league']
            by_league[league]['staked'] += slip['stake'] / len(slip['matches'])
            if match['is_correct']:
                by_league[league]['won'] += 1
            else:
                by_league[league]['lost'] += 1

    league_stats = {}
    for league, stats in by_league.items():
        total = stats['won'] + stats['lost']
        league_stats[league] = {
            'name': LEAGUE_NAMES.get(league, league),
            'flag': LEAGUE_FLAGS.get(league, '⚽'),
            'matches': total,
            'won': stats['won'],
            'lost': stats['lost'],
            'accuracy': round(stats['won'] / total * 100, 1) if total > 0 else 0
        }

    # Best e worst days
    sorted_by_profit = sorted(slips, key=lambda x: x['profit'], reverse=True)
    best_days = sorted_by_profit[:5]
    worst_days = sorted_by_profit[-5:]

    # Monthly breakdown
    monthly = defaultdict(lambda: {'slips': 0, 'won': 0, 'staked': 0, 'profit': 0})
    for slip in slips:
        month = slip['date'][:7]  # YYYY-MM
        monthly[month]['slips'] += 1
        monthly[month]['staked'] += slip['stake']
        monthly[month]['profit'] += slip['profit']
        if slip['status'] == 'won':
            monthly[month]['won'] += 1

    monthly_stats = []
    for month, stats in sorted(monthly.items()):
        monthly_stats.append({
            'month': month,
            'slips': stats['slips'],
            'won': stats['won'],
            'win_rate': round(stats['won'] / stats['slips'] * 100, 1) if stats['slips'] > 0 else 0,
            'staked': round(stats['staked'], 2),
            'profit': round(stats['profit'], 2),
            'roi': round(stats['profit'] / stats['staked'] * 100, 1) if stats['staked'] > 0 else 0
        })

    return {
        'total_slips': total_slips,
        'won_slips': won_slips,
        'lost_slips': lost_slips,
        'win_rate': round(win_rate, 1),
        'total_staked': round(total_staked, 2),
        'total_won': round(total_won, 2),
        'total_profit': round(total_profit, 2),
        'roi': round(roi, 1),
        'avg_odds': round(sum(s['total_odds'] for s in slips) / total_slips, 2) if total_slips > 0 else 0,
        'avg_stake': round(total_staked / total_slips, 2) if total_slips > 0 else 0,
        'current_streak': current_streak,
        'max_win_streak': max_win_streak,
        'max_loss_streak': max_loss_streak,
        'by_league': league_stats,
        'best_days': [{'date': s['date'], 'profit': s['profit'], 'odds': s['total_odds']} for s in best_days],
        'worst_days': [{'date': s['date'], 'profit': s['profit'], 'odds': s['total_odds']} for s in worst_days[-5:][::-1]],
        'monthly': monthly_stats
    }


def generate_single_bets(results, min_confidence=60):
    """
    Genera scommesse singole (1 match per scommessa)
    Mostra la vera accuratezza del modello
    """
    bets = []

    # Filtra per confidence
    high_conf = [m for m in results if m['confidence'] >= min_confidence]

    for match in high_conf:
        odds = calculate_odds(
            match['predicted'],
            match['home_prob'],
            match['draw_prob'],
            match['away_prob'],
            match['correct']
        )

        stake = 10.0
        actual_win = stake * odds if match['correct'] else 0
        profit = actual_win - stake

        bets.append({
            'id': f"BET-{match['date'].replace('-', '')}-{match['home_team'][:3].upper()}",
            'date': match['date'],
            'time': match.get('time', '15:00'),
            'home_team': match['home_team'],
            'away_team': match['away_team'],
            'league': match['league'],
            'league_name': match['league_name'],
            'flag': LEAGUE_FLAGS.get(match['league'], '⚽'),
            'prediction': match['predicted'],
            'predicted_sign': '1' if match['predicted'] == 'HOME' else ('X' if match['predicted'] == 'DRAW' else '2'),
            'actual_result': match['actual'],
            'actual_sign': '1' if match['actual'] == 'HOME' else ('X' if match['actual'] == 'DRAW' else '2'),
            'home_goals': match['home_goals'],
            'away_goals': match['away_goals'],
            'confidence': match['confidence'],
            'odds': odds,
            'stake': stake,
            'potential_win': round(stake * odds, 2),
            'actual_win': round(actual_win, 2),
            'profit': round(profit, 2),
            'is_correct': match['correct']
        })

    return bets


def calculate_single_bet_stats(bets):
    """Statistiche per scommesse singole"""
    total = len(bets)
    won = sum(1 for b in bets if b['is_correct'])
    lost = total - won

    total_staked = sum(b['stake'] for b in bets)
    total_won = sum(b['actual_win'] for b in bets)
    total_profit = sum(b['profit'] for b in bets)

    win_rate = (won / total * 100) if total > 0 else 0
    roi = (total_profit / total_staked * 100) if total_staked > 0 else 0

    # By league
    by_league = defaultdict(lambda: {'won': 0, 'lost': 0, 'profit': 0, 'staked': 0})
    for bet in bets:
        league = bet['league']
        by_league[league]['staked'] += bet['stake']
        by_league[league]['profit'] += bet['profit']
        if bet['is_correct']:
            by_league[league]['won'] += 1
        else:
            by_league[league]['lost'] += 1

    league_stats = {}
    for league, stats in by_league.items():
        total_l = stats['won'] + stats['lost']
        league_stats[league] = {
            'name': LEAGUE_NAMES.get(league, league),
            'flag': LEAGUE_FLAGS.get(league, '⚽'),
            'total': total_l,
            'won': stats['won'],
            'lost': stats['lost'],
            'win_rate': round(stats['won'] / total_l * 100, 1) if total_l > 0 else 0,
            'profit': round(stats['profit'], 2),
            'roi': round(stats['profit'] / stats['staked'] * 100, 1) if stats['staked'] > 0 else 0
        }

    # By confidence band
    by_confidence = {}
    for band in [(60, 65), (65, 70), (70, 75), (75, 100)]:
        band_bets = [b for b in bets if band[0] <= b['confidence'] < band[1]]
        if band_bets:
            band_won = sum(1 for b in band_bets if b['is_correct'])
            band_profit = sum(b['profit'] for b in band_bets)
            band_staked = sum(b['stake'] for b in band_bets)
            by_confidence[f"{band[0]}-{band[1]}"] = {
                'range': f"{band[0]}%-{band[1]}%",
                'total': len(band_bets),
                'won': band_won,
                'win_rate': round(band_won / len(band_bets) * 100, 1),
                'profit': round(band_profit, 2),
                'roi': round(band_profit / band_staked * 100, 1) if band_staked > 0 else 0
            }

    # Recent performance (last 20)
    recent = sorted(bets, key=lambda x: x['date'], reverse=True)[:20]
    recent_won = sum(1 for b in recent if b['is_correct'])
    recent_profit = sum(b['profit'] for b in recent)

    return {
        'total_bets': total,
        'won': won,
        'lost': lost,
        'win_rate': round(win_rate, 1),
        'total_staked': round(total_staked, 2),
        'total_won': round(total_won, 2),
        'total_profit': round(total_profit, 2),
        'roi': round(roi, 1),
        'avg_odds': round(sum(b['odds'] for b in bets) / total, 2) if total > 0 else 0,
        'by_league': league_stats,
        'by_confidence': by_confidence,
        'recent_20': {
            'won': recent_won,
            'win_rate': round(recent_won / len(recent) * 100, 1) if recent else 0,
            'profit': round(recent_profit, 2)
        }
    }


def main():
    print("=" * 70)
    print("BetPredictAI - Historical Betting Slips Generator")
    print("=" * 70)

    # Load verification results
    verification_path = os.path.join(DATA_DIR, 'verification_results.json')

    if not os.path.exists(verification_path):
        print(" ERROR: verification_results.json not found!")
        print("  Run train_model_v4_robust.py first.")
        return

    with open(verification_path, 'r') as f:
        verification = json.load(f)

    results = verification.get('results', [])
    print(f"\n  Loaded {len(results)} verified matches")

    # Group by date
    matches_by_date = group_matches_by_date(results)
    print(f"  Spanning {len(matches_by_date)} unique dates")

    # ===== SINGLE BETS (recommended) =====
    print("\n" + "=" * 50)
    print(" SINGLE BETS (Recommended Strategy)")
    print("=" * 50)

    single_bets = generate_single_bets(results, min_confidence=60)
    single_stats = calculate_single_bet_stats(single_bets)

    print(f"\n  Total Single Bets: {single_stats['total_bets']}")
    print(f"  Win Rate: {single_stats['win_rate']:.1f}%")
    print(f"  ROI: {single_stats['roi']:+.1f}%")
    print(f"  Total Profit: €{single_stats['total_profit']:+.2f}")

    single_output = {
        'generated_at': datetime.now().isoformat(),
        'strategy': 'single_bets',
        'confidence_threshold': 60,
        'statistics': single_stats,
        'bets': single_bets
    }

    # ===== MULTIPLE BETS =====
    print("\n" + "=" * 50)
    print(" MULTIPLE BETS (Higher Risk/Reward)")
    print("=" * 50)

    # Generate slips at different confidence levels
    confidence_levels = [50, 55, 60, 65]
    all_outputs = {'single_bets': single_output}

    for conf in confidence_levels:
        print(f"\n Generating slips with confidence >= {conf}%...")
        slips = generate_daily_slips(matches_by_date, min_confidence=conf, max_selections=4)
        stats = calculate_statistics(slips)

        output = {
            'generated_at': datetime.now().isoformat(),
            'confidence_threshold': conf,
            'statistics': stats,
            'slips': slips
        }

        all_outputs[f"conf_{conf}"] = output

        print(f"    Generated {len(slips)} slips")
        print(f"    Win Rate: {stats['win_rate']:.1f}%")
        print(f"    ROI: {stats['roi']:+.1f}%")
        print(f"    Total Profit: €{stats['total_profit']:+.2f}")

    # Choose best performing strategy (default 60%)
    best_conf = 60
    primary_output = all_outputs[f"conf_{best_conf}"]

    # Save outputs
    print("\n Saving outputs...")

    # Save single bets (recommended strategy)
    with open(os.path.join(DATA_DIR, 'historical_single_bets.json'), 'w') as f:
        json.dump(single_output, f, indent=2)

    # Save primary (conf_60) as main file
    with open(os.path.join(DATA_DIR, 'historical_slips.json'), 'w') as f:
        json.dump(primary_output, f, indent=2)

    # Save all strategies
    with open(os.path.join(DATA_DIR, 'historical_slips_all.json'), 'w') as f:
        json.dump(all_outputs, f, indent=2)

    # Create a summary for the frontend
    frontend_stats = {
        'generated_at': datetime.now().isoformat(),
        'single_bets': {
            'total': single_stats['total_bets'],
            'won': single_stats['won'],
            'win_rate': single_stats['win_rate'],
            'roi': single_stats['roi'],
            'profit': single_stats['total_profit'],
            'by_confidence': single_stats['by_confidence'],
            'by_league': single_stats['by_league']
        },
        'model_accuracy': {
            'overall': verification.get('summary', {}).get('accuracy', 53.8),
            'by_confidence': verification.get('by_confidence', {}),
            'training_matches': verification.get('training_info', {}).get('training_matches', 17611),
            'test_matches': verification.get('training_info', {}).get('test_matches', 400)
        },
        'improvement_over_random': {
            'random_probability': 33.3,  # 1/3 for 3 outcomes
            'ai_probability': single_stats['win_rate'],
            'improvement_factor': round(single_stats['win_rate'] / 33.3, 2),
            'high_confidence_accuracy': single_stats['by_confidence'].get('65-70', {}).get('win_rate', single_stats['win_rate'])
        }
    }

    with open(os.path.join(DATA_DIR, 'frontend_stats.json'), 'w') as f:
        json.dump(frontend_stats, f, indent=2)

    # Print summary
    print("\n" + "=" * 70)
    print("GENERATION COMPLETE")
    print("=" * 70)

    print(f"\n  SINGLE BETS (Recommended):")
    print(f"    Total Bets:   {single_stats['total_bets']}")
    print(f"    Win Rate:     {single_stats['win_rate']:.1f}%")
    print(f"    ROI:          {single_stats['roi']:+.1f}%")
    print(f"    Profit:       €{single_stats['total_profit']:+.2f}")

    print(f"\n  By Confidence Band:")
    for band, bs in single_stats['by_confidence'].items():
        print(f"    {bs['range']}: {bs['win_rate']:.1f}% ({bs['won']}/{bs['total']}) ROI: {bs['roi']:+.1f}%")

    print(f"\n  IMPROVEMENT OVER RANDOM:")
    print(f"    Random (1/3):  33.3%")
    print(f"    AI System:     {single_stats['win_rate']:.1f}%")
    print(f"    Improvement:   {single_stats['win_rate'] / 33.3:.2f}x")

    stats = primary_output['statistics']

    print(f"\n  MULTIPLE BETS (Higher Risk):")
    print(f"    Total Slips:    {stats['total_slips']}")
    print(f"    Won:            {stats['won_slips']} ({stats['win_rate']:.1f}%)")
    print(f"    Lost:           {stats['lost_slips']}")

    print(f"\n  By League (Single Bets):")
    for league, ls in single_stats['by_league'].items():
        print(f"    {ls['flag']} {ls['name']}: {ls['win_rate']:.1f}% ({ls['won']}/{ls['total']})")

    print(f"\n  Files saved:")
    print(f"    - {os.path.join(DATA_DIR, 'historical_single_bets.json')}")
    print(f"    - {os.path.join(DATA_DIR, 'historical_slips.json')}")
    print(f"    - {os.path.join(DATA_DIR, 'historical_slips_all.json')}")
    print(f"    - {os.path.join(DATA_DIR, 'frontend_stats.json')}")


if __name__ == '__main__':
    main()
