"""
BET.CUTTALO.COM - FIXTURE COLLECTOR
Raccoglie partite future con data e ora da API gratuite
"""

import requests
import pandas as pd
import json
import os
from datetime import datetime, timedelta
from typing import List, Dict
import time

DATA_DIR = os.path.join(os.path.dirname(__file__), '..', 'data')
os.makedirs(DATA_DIR, exist_ok=True)

# Stadium coordinates for major teams (for timezone/location info)
TEAM_LOCATIONS = {
    # Premier League
    'Arsenal': {'city': 'London', 'stadium': 'Emirates Stadium', 'country': 'England'},
    'Aston Villa': {'city': 'Birmingham', 'stadium': 'Villa Park', 'country': 'England'},
    'Bournemouth': {'city': 'Bournemouth', 'stadium': 'Vitality Stadium', 'country': 'England'},
    'Brentford': {'city': 'London', 'stadium': 'Gtech Community Stadium', 'country': 'England'},
    'Brighton': {'city': 'Brighton', 'stadium': 'Amex Stadium', 'country': 'England'},
    'Chelsea': {'city': 'London', 'stadium': 'Stamford Bridge', 'country': 'England'},
    'Crystal Palace': {'city': 'London', 'stadium': 'Selhurst Park', 'country': 'England'},
    'Everton': {'city': 'Liverpool', 'stadium': 'Goodison Park', 'country': 'England'},
    'Fulham': {'city': 'London', 'stadium': 'Craven Cottage', 'country': 'England'},
    'Ipswich': {'city': 'Ipswich', 'stadium': 'Portman Road', 'country': 'England'},
    'Leicester': {'city': 'Leicester', 'stadium': 'King Power Stadium', 'country': 'England'},
    'Liverpool': {'city': 'Liverpool', 'stadium': 'Anfield', 'country': 'England'},
    'Man City': {'city': 'Manchester', 'stadium': 'Etihad Stadium', 'country': 'England'},
    'Man United': {'city': 'Manchester', 'stadium': 'Old Trafford', 'country': 'England'},
    'Newcastle': {'city': 'Newcastle', 'stadium': "St James' Park", 'country': 'England'},
    "Nott'm Forest": {'city': 'Nottingham', 'stadium': 'City Ground', 'country': 'England'},
    'Southampton': {'city': 'Southampton', 'stadium': "St Mary's Stadium", 'country': 'England'},
    'Tottenham': {'city': 'London', 'stadium': 'Tottenham Hotspur Stadium', 'country': 'England'},
    'West Ham': {'city': 'London', 'stadium': 'London Stadium', 'country': 'England'},
    'Wolves': {'city': 'Wolverhampton', 'stadium': 'Molineux Stadium', 'country': 'England'},

    # Serie A
    'AC Milan': {'city': 'Milan', 'stadium': 'San Siro', 'country': 'Italy'},
    'Milan': {'city': 'Milan', 'stadium': 'San Siro', 'country': 'Italy'},
    'Inter': {'city': 'Milan', 'stadium': 'San Siro', 'country': 'Italy'},
    'Juventus': {'city': 'Turin', 'stadium': 'Allianz Stadium', 'country': 'Italy'},
    'Napoli': {'city': 'Naples', 'stadium': 'Diego Armando Maradona', 'country': 'Italy'},
    'Roma': {'city': 'Rome', 'stadium': 'Stadio Olimpico', 'country': 'Italy'},
    'Lazio': {'city': 'Rome', 'stadium': 'Stadio Olimpico', 'country': 'Italy'},
    'Atalanta': {'city': 'Bergamo', 'stadium': 'Gewiss Stadium', 'country': 'Italy'},
    'Fiorentina': {'city': 'Florence', 'stadium': 'Stadio Artemio Franchi', 'country': 'Italy'},
    'Bologna': {'city': 'Bologna', 'stadium': 'Stadio Renato Dall\'Ara', 'country': 'Italy'},
    'Torino': {'city': 'Turin', 'stadium': 'Stadio Olimpico Grande Torino', 'country': 'Italy'},

    # La Liga
    'Real Madrid': {'city': 'Madrid', 'stadium': 'Santiago Bernabeu', 'country': 'Spain'},
    'Barcelona': {'city': 'Barcelona', 'stadium': 'Spotify Camp Nou', 'country': 'Spain'},
    'Ath Madrid': {'city': 'Madrid', 'stadium': 'Civitas Metropolitano', 'country': 'Spain'},
    'Sevilla': {'city': 'Seville', 'stadium': 'Ramon Sanchez Pizjuan', 'country': 'Spain'},
    'Valencia': {'city': 'Valencia', 'stadium': 'Mestalla', 'country': 'Spain'},
    'Villarreal': {'city': 'Villarreal', 'stadium': 'Estadio de la Ceramica', 'country': 'Spain'},
    'Real Betis': {'city': 'Seville', 'stadium': 'Benito Villamarin', 'country': 'Spain'},
    'Ath Bilbao': {'city': 'Bilbao', 'stadium': 'San Mames', 'country': 'Spain'},

    # Bundesliga
    'Bayern Munich': {'city': 'Munich', 'stadium': 'Allianz Arena', 'country': 'Germany'},
    'Dortmund': {'city': 'Dortmund', 'stadium': 'Signal Iduna Park', 'country': 'Germany'},
    'RB Leipzig': {'city': 'Leipzig', 'stadium': 'Red Bull Arena', 'country': 'Germany'},
    'Leverkusen': {'city': 'Leverkusen', 'stadium': 'BayArena', 'country': 'Germany'},
    'Ein Frankfurt': {'city': 'Frankfurt', 'stadium': 'Deutsche Bank Park', 'country': 'Germany'},
    'Wolfsburg': {'city': 'Wolfsburg', 'stadium': 'Volkswagen Arena', 'country': 'Germany'},
    "M'gladbach": {'city': 'Monchengladbach', 'stadium': 'Borussia-Park', 'country': 'Germany'},
    'Stuttgart': {'city': 'Stuttgart', 'stadium': 'MHPArena', 'country': 'Germany'},

    # Ligue 1
    'Paris SG': {'city': 'Paris', 'stadium': 'Parc des Princes', 'country': 'France'},
    'Marseille': {'city': 'Marseille', 'stadium': 'Stade Velodrome', 'country': 'France'},
    'Lyon': {'city': 'Lyon', 'stadium': 'Groupama Stadium', 'country': 'France'},
    'Monaco': {'city': 'Monaco', 'stadium': 'Stade Louis II', 'country': 'France'},
    'Lille': {'city': 'Lille', 'stadium': 'Stade Pierre-Mauroy', 'country': 'France'},
    'Nice': {'city': 'Nice', 'stadium': 'Allianz Riviera', 'country': 'France'},
}


class FixtureCollector:
    """
    Raccoglie fixture future da API gratuite
    """

    def __init__(self):
        self.session = requests.Session()
        self.session.headers.update({
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        })

    def get_fixtures_openligadb(self, league: str = 'bl1', season: int = 2024) -> List[Dict]:
        """
        Ottieni fixture da OpenLigaDB (gratuito, no key)
        Supporta: bl1 (Bundesliga), bl2, bl3, dfb (DFB Pokal)
        """
        fixtures = []

        try:
            url = f"https://api.openligadb.de/getmatchdata/{league}/{season}"
            response = self.session.get(url, timeout=30)
            data = response.json()

            now = datetime.now()

            for match in data:
                match_date = datetime.fromisoformat(match['matchDateTime'].replace('Z', '+00:00'))

                # Solo partite future non ancora giocate
                if match_date.replace(tzinfo=None) > now and not match.get('matchIsFinished', True):
                    home_team = match['team1']['teamName']
                    away_team = match['team2']['teamName']

                    fixtures.append({
                        'id': f"openliga_{match['matchID']}",
                        'source': 'OpenLigaDB',
                        'league_code': 'D1',
                        'league_name': 'Bundesliga',
                        'country': 'Germany',
                        'matchday': match.get('group', {}).get('groupOrderID', 0),
                        'date': match_date.strftime('%Y-%m-%d'),
                        'time': match_date.strftime('%H:%M'),
                        'datetime': match_date.isoformat(),
                        'timestamp': int(match_date.timestamp()),
                        'home_team': home_team,
                        'away_team': away_team,
                        'home_team_logo': match['team1'].get('teamIconUrl', ''),
                        'away_team_logo': match['team2'].get('teamIconUrl', ''),
                        'venue': TEAM_LOCATIONS.get(home_team, {}).get('stadium', ''),
                        'city': TEAM_LOCATIONS.get(home_team, {}).get('city', ''),
                        'status': 'SCHEDULED'
                    })

            print(f"OpenLigaDB: {len(fixtures)} fixture Bundesliga")

        except Exception as e:
            print(f"Errore OpenLigaDB: {e}")

        return fixtures

    def get_fixtures_from_footballdata(self) -> List[Dict]:
        """
        Scarica fixture REALI da football-data.co.uk
        Include molte più leghe con quote vere
        """
        fixtures = []

        # Tutte le leghe disponibili su football-data.co.uk
        LEAGUES_INFO = {
            # Inghilterra
            'E0': {'name': 'Premier League', 'country': 'England', 'tier': 1, 'flag': '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'color': '#38003c'},
            'E1': {'name': 'Championship', 'country': 'England', 'tier': 2, 'flag': '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'color': '#ff6b00'},
            'E2': {'name': 'League One', 'country': 'England', 'tier': 3, 'flag': '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'color': '#e62333'},
            'E3': {'name': 'League Two', 'country': 'England', 'tier': 4, 'flag': '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'color': '#0057b8'},
            'EC': {'name': 'Conference', 'country': 'England', 'tier': 5, 'flag': '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'color': '#1e3a5f'},
            # Scozia
            'SC0': {'name': 'Scottish Premiership', 'country': 'Scotland', 'tier': 1, 'flag': '🏴󠁧󠁢󠁳󠁣󠁴󠁿', 'color': '#004b87'},
            'SC1': {'name': 'Scottish Championship', 'country': 'Scotland', 'tier': 2, 'flag': '🏴󠁧󠁢󠁳󠁣󠁴󠁿', 'color': '#4a7c59'},
            'SC2': {'name': 'Scottish League 1', 'country': 'Scotland', 'tier': 3, 'flag': '🏴󠁧󠁢󠁳󠁣󠁴󠁿', 'color': '#6b4423'},
            'SC3': {'name': 'Scottish League 2', 'country': 'Scotland', 'tier': 4, 'flag': '🏴󠁧󠁢󠁳󠁣󠁴󠁿', 'color': '#8b4513'},
            # Germania
            'D1': {'name': 'Bundesliga', 'country': 'Germany', 'tier': 1, 'flag': '🇩🇪', 'color': '#d20515'},
            'D2': {'name': '2. Bundesliga', 'country': 'Germany', 'tier': 2, 'flag': '🇩🇪', 'color': '#004d40'},
            # Italia
            'I1': {'name': 'Serie A', 'country': 'Italy', 'tier': 1, 'flag': '🇮🇹', 'color': '#024494'},
            'I2': {'name': 'Serie B', 'country': 'Italy', 'tier': 2, 'flag': '🇮🇹', 'color': '#005c3a'},
            # Spagna
            'SP1': {'name': 'La Liga', 'country': 'Spain', 'tier': 1, 'flag': '🇪🇸', 'color': '#ee324e'},
            'SP2': {'name': 'La Liga 2', 'country': 'Spain', 'tier': 2, 'flag': '🇪🇸', 'color': '#1a472a'},
            # Francia
            'F1': {'name': 'Ligue 1', 'country': 'France', 'tier': 1, 'flag': '🇫🇷', 'color': '#091c3e'},
            'F2': {'name': 'Ligue 2', 'country': 'France', 'tier': 2, 'flag': '🇫🇷', 'color': '#2d572c'},
            # Olanda
            'N1': {'name': 'Eredivisie', 'country': 'Netherlands', 'tier': 1, 'flag': '🇳🇱', 'color': '#ff6600'},
            # Belgio
            'B1': {'name': 'Jupiler Pro League', 'country': 'Belgium', 'tier': 1, 'flag': '🇧🇪', 'color': '#0a3d62'},
            # Portogallo
            'P1': {'name': 'Primeira Liga', 'country': 'Portugal', 'tier': 1, 'flag': '🇵🇹', 'color': '#006847'},
            # Turchia
            'T1': {'name': 'Super Lig', 'country': 'Turkey', 'tier': 1, 'flag': '🇹🇷', 'color': '#e30a17'},
            # Grecia
            'G1': {'name': 'Super League', 'country': 'Greece', 'tier': 1, 'flag': '🇬🇷', 'color': '#0d5eaf'},
        }

        try:
            print("\n📥 Scaricando fixture reali da football-data.co.uk...")
            url = "https://www.football-data.co.uk/fixtures.csv"
            response = self.session.get(url, timeout=30)
            response.raise_for_status()

            from io import StringIO
            # Remove BOM from text
            text = response.text.replace('\ufeff', '')
            if text.startswith('ï»¿'):
                text = text[3:]  # Remove BOM bytes

            df = pd.read_csv(StringIO(text))

            # Clean column names
            df.columns = [col.strip() for col in df.columns]

            now = datetime.now()

            for idx, row in df.iterrows():
                league_code = str(row.get('Div', '')).strip()
                if not league_code or league_code == 'nan' or league_code not in LEAGUES_INFO:
                    continue

                league = LEAGUES_INFO[league_code]
                home_team = str(row.get('HomeTeam', '')).strip()
                away_team = str(row.get('AwayTeam', '')).strip()

                if not home_team or not away_team:
                    continue

                # Parse date
                date_str = str(row.get('Date', ''))
                time_str = str(row.get('Time', '15:00'))

                try:
                    # Try different date formats
                    for fmt in ['%d/%m/%Y', '%Y-%m-%d', '%d/%m/%y']:
                        try:
                            match_date = datetime.strptime(date_str, fmt)
                            break
                        except:
                            continue
                    else:
                        continue

                    # Add time
                    if time_str and time_str != 'nan':
                        try:
                            time_parts = time_str.split(':')
                            match_date = match_date.replace(hour=int(time_parts[0]), minute=int(time_parts[1]) if len(time_parts) > 1 else 0)
                        except:
                            match_date = match_date.replace(hour=15, minute=0)
                    else:
                        match_date = match_date.replace(hour=15, minute=0)

                    # Only include future matches (not started yet)
                    # Skip matches that have already started (kickoff + 15 min buffer)
                    if match_date < now - timedelta(minutes=15):
                        continue

                except Exception as e:
                    continue

                # Get odds from the CSV (Bet365 primary, then average)
                try:
                    odds_home = float(row.get('B365H') or row.get('AvgH') or 2.0)
                    odds_draw = float(row.get('B365D') or row.get('AvgD') or 3.5)
                    odds_away = float(row.get('B365A') or row.get('AvgA') or 3.0)
                except:
                    odds_home, odds_draw, odds_away = 2.0, 3.5, 3.0

                # All matches here are future/upcoming
                is_past = False
                status = 'SCHEDULED'

                fixtures.append({
                    'id': f"fd_{league_code}_{idx}_{int(match_date.timestamp())}",
                    'source': 'football-data.co.uk',
                    'league_code': league_code,
                    'league_name': league['name'],
                    'country': league['country'],
                    'tier': league['tier'],
                    'flag': league['flag'],
                    'league_color': league['color'],
                    'matchday': 0,
                    'date': match_date.strftime('%Y-%m-%d'),
                    'time': match_date.strftime('%H:%M'),
                    'datetime': match_date.isoformat(),
                    'timestamp': int(match_date.timestamp()),
                    'home_team': home_team,
                    'away_team': away_team,
                    'home_team_logo': '',
                    'away_team_logo': '',
                    'venue': TEAM_LOCATIONS.get(home_team, {}).get('stadium', ''),
                    'city': TEAM_LOCATIONS.get(home_team, {}).get('city', ''),
                    'status': status,
                    'is_past': is_past,
                    'odds_home': odds_home,
                    'odds_draw': odds_draw,
                    'odds_away': odds_away,
                    'odds_source': 'Bet365'
                })

            # Count by league
            by_league = {}
            for f in fixtures:
                lc = f['league_code']
                by_league[lc] = by_league.get(lc, 0) + 1

            print(f"  ✓ {len(fixtures)} fixture reali scaricate")
            for lc, count in sorted(by_league.items()):
                if lc in LEAGUES_INFO:
                    print(f"    {LEAGUES_INFO[lc]['flag']} {LEAGUES_INFO[lc]['name']}: {count}")

        except Exception as e:
            print(f"  ✗ Errore scaricamento: {e}")
            import traceback
            traceback.print_exc()

        return fixtures

    def get_fixtures_from_csv(self) -> List[Dict]:
        """
        Genera fixture simulate basate sui dati storici
        per i campionati senza fixture reali
        """
        fixtures = []

        try:
            # Carica dati storici
            csv_path = os.path.join(DATA_DIR, 'historical_matches.csv')
            if not os.path.exists(csv_path):
                return fixtures

            df = pd.read_csv(csv_path)
            df['Date'] = pd.to_datetime(df['Date'], errors='coerce')

            # Principali leghe europee per cui generare fixture stimate
            leagues = {
                'E0': {'name': 'Premier League', 'country': 'England', 'teams': 20, 'flag': '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'tier': 1},
                'I1': {'name': 'Serie A', 'country': 'Italy', 'teams': 20, 'flag': '🇮🇹', 'tier': 1},
                'SP1': {'name': 'La Liga', 'country': 'Spain', 'teams': 20, 'flag': '🇪🇸', 'tier': 1},
                'D1': {'name': 'Bundesliga', 'country': 'Germany', 'teams': 18, 'flag': '🇩🇪', 'tier': 1},
                'F1': {'name': 'Ligue 1', 'country': 'France', 'teams': 18, 'flag': '🇫🇷', 'tier': 1},
            }

            now = datetime.now()

            for league_code, league_info in leagues.items():
                league_df = df[df['league_code'] == league_code]
                current_season = league_df['season'].iloc[-1] if len(league_df) > 0 else '2024/2025'

                # Ottieni squadre correnti
                season_df = league_df[league_df['season'] == current_season]
                teams = list(set(season_df['home_team'].unique()) | set(season_df['away_team'].unique()))

                if len(teams) < 2:
                    continue

                # Calcola ultima giornata giocata
                last_match_date = season_df['Date'].max()

                # Genera prossime partite (stima)
                matchday = len(season_df) // (len(teams) // 2) + 1

                # Genera fixture per i prossimi 14 giorni
                # Tipicamente: Sabato/Domenica + partite infrasettimanali
                time_slots_weekend = ['15:00', '17:30', '18:00', '20:45', '21:00']
                time_slots_midweek = ['18:30', '19:00', '20:45', '21:00']

                import random

                # Genera per i prossimi 14 giorni
                for day_offset in range(1, 15):  # Prossimi 14 giorni
                    match_date = now + timedelta(days=day_offset)
                    weekday = match_date.weekday()  # 0=Mon, 5=Sat, 6=Sun

                    # Determina quante partite per questo giorno
                    # Weekend: più partite, Infrasettimanale: meno
                    if weekday in [5, 6]:  # Weekend
                        max_matches = min(len(teams) // 2, 10)
                        time_slots = time_slots_weekend
                    elif weekday in [1, 2]:  # Martedì/Mercoledì - turni infrasettimanali
                        max_matches = min(len(teams) // 2, 6)
                        time_slots = time_slots_midweek
                    else:
                        max_matches = min(len(teams) // 2, 3)  # Altri giorni meno partite
                        time_slots = time_slots_midweek

                    # Seed per riproducibilità
                    random.seed(day_offset * 1000 + hash(league_code) + int(now.timestamp() // 86400))

                    available_teams = teams.copy()
                    random.shuffle(available_teams)

                    for i in range(max_matches):
                        if len(available_teams) < 2:
                            break

                        home = available_teams.pop()
                        away = available_teams.pop()
                        match_time = time_slots[i % len(time_slots)]

                        full_datetime = datetime.combine(
                            match_date.date(),
                            datetime.strptime(match_time, '%H:%M').time()
                        )

                        # Only add if match is in the future
                        if full_datetime < now - timedelta(minutes=15):
                            continue

                        fixtures.append({
                            'id': f"{league_code}_{day_offset}_{i}_{int(now.timestamp())}",
                            'source': 'Estimated',
                            'league_code': league_code,
                            'league_name': league_info['name'],
                            'country': league_info['country'],
                            'tier': league_info.get('tier', 1),
                            'flag': league_info.get('flag', '⚽'),
                            'league_color': '#666666',
                            'matchday': matchday + (day_offset // 7),
                            'date': full_datetime.strftime('%Y-%m-%d'),
                            'time': match_time,
                            'datetime': full_datetime.isoformat(),
                            'timestamp': int(full_datetime.timestamp()),
                            'home_team': home,
                            'away_team': away,
                            'home_team_logo': '',
                            'away_team_logo': '',
                            'venue': TEAM_LOCATIONS.get(home, {}).get('stadium', ''),
                            'city': TEAM_LOCATIONS.get(home, {}).get('city', ''),
                            'status': 'SCHEDULED',
                            'is_past': False,
                            'odds_home': 2.0,
                            'odds_draw': 3.5,
                            'odds_away': 3.0,
                            'odds_source': 'Estimated'
                        })

                print(f"Estimated: {len([f for f in fixtures if f['league_code'] == league_code])} fixture {league_info['name']}")

        except Exception as e:
            print(f"Errore generazione fixture: {e}")
            import traceback
            traceback.print_exc()

        return fixtures

    def collect_all_fixtures(self) -> List[Dict]:
        """
        Raccoglie tutte le fixture disponibili
        """
        all_fixtures = []

        print("\n" + "="*60)
        print("RACCOLTA FIXTURE FUTURE - SISTEMA PROFESSIONALE")
        print("="*60)

        # 1. Fixture REALI da football-data.co.uk (priorità)
        real_fixtures = self.get_fixtures_from_footballdata()
        all_fixtures.extend(real_fixtures)

        # 2. Bundesliga extra da OpenLigaDB (dettagli aggiuntivi)
        # Skip se già abbiamo fixture dalla fonte principale
        if not any(f['league_code'] == 'D1' for f in all_fixtures):
            bundesliga = self.get_fixtures_openligadb('bl1', 2024)
            all_fixtures.extend(bundesliga)

        # 3. Fixture stimate per date future (se non ci sono fixture reali recenti)
        # Aggiungi solo se abbiamo poche fixture future
        future_count = sum(1 for f in all_fixtures if not f.get('is_past', False))
        if future_count < 20:
            print(f"\n📅 Solo {future_count} fixture future - generando stimate...")
            estimated = self.get_fixtures_from_csv()
            # Prendi solo le fixture future dalle stime
            estimated = [f for f in estimated if not f.get('is_past', False)]
            all_fixtures.extend(estimated)
            print(f"  ✓ Aggiunte {len(estimated)} fixture stimate")

        # Ordina per data
        all_fixtures.sort(key=lambda x: x['timestamp'])

        # Salva
        output_path = os.path.join(DATA_DIR, 'upcoming_fixtures.json')
        with open(output_path, 'w') as f:
            json.dump(all_fixtures, f, indent=2, ensure_ascii=False)

        print(f"\n{'='*60}")
        print(f"TOTALE: {len(all_fixtures)} fixture salvate")
        print("="*60)

        return all_fixtures


def fetch_real_odds():
    """
    Scarica quote reali da football-data.co.uk fixtures.csv
    Returns dict: {(home_team, away_team): {'home': x.xx, 'draw': x.xx, 'away': x.xx}}
    """
    print("\n📊 Scaricando quote reali da football-data.co.uk...")

    # Mapping nomi squadre (football-data -> nostro sistema)
    TEAM_NAME_MAP = {
        # Bundesliga
        'stuttgart': 'stuttgart', 'ein frankfurt': 'frankfurt', 'eintracht frankfurt': 'frankfurt',
        'dortmund': 'dortmund', 'werder bremen': 'bremen', 'hamburg': 'hamburg', 'hamburger sv': 'hamburg',
        'leverkusen': 'leverkusen', 'bayer leverkusen': 'leverkusen', 'mainz': 'mainz', 'heidenheim': 'heidenheim',
        'wolfsburg': 'wolfsburg', 'st pauli': 'st pauli', 'fc koln': 'koln', 'bayern munich': 'bayern munich',
        'hoffenheim': 'hoffenheim', "m'gladbach": 'gladbach', 'monchengladbach': 'gladbach',
        'rb leipzig': 'rb leipzig', 'leipzig': 'rb leipzig', 'freiburg': 'freiburg',
        'augsburg': 'augsburg', 'union berlin': 'union berlin', 'hertha': 'hertha',
        'schalke': 'schalke', 'bochum': 'bochum',
        # Serie A
        'inter': 'inter', 'ac milan': 'milan', 'milan': 'milan', 'juventus': 'juventus',
        'napoli': 'napoli', 'roma': 'roma', 'lazio': 'lazio', 'atalanta': 'atalanta',
        'fiorentina': 'fiorentina', 'bologna': 'bologna', 'torino': 'torino', 'verona': 'verona',
        'udinese': 'udinese', 'sassuolo': 'sassuolo', 'empoli': 'empoli', 'cagliari': 'cagliari',
        'genoa': 'genoa', 'sampdoria': 'sampdoria', 'lecce': 'lecce', 'monza': 'monza',
        'parma': 'parma', 'como': 'como', 'venezia': 'venezia',
        # Premier League
        'man city': 'man city', 'manchester city': 'man city', 'man united': 'man united', 'manchester united': 'man united',
        'liverpool': 'liverpool', 'chelsea': 'chelsea', 'arsenal': 'arsenal', 'tottenham': 'tottenham',
        'west ham': 'west ham', 'newcastle': 'newcastle', 'aston villa': 'aston villa',
        'brighton': 'brighton', 'wolves': 'wolves', 'wolverhampton': 'wolves',
        'everton': 'everton', 'leicester': 'leicester', 'leeds': 'leeds', 'southampton': 'southampton',
        'bournemouth': 'bournemouth', 'fulham': 'fulham', 'crystal palace': 'crystal palace',
        'brentford': 'brentford', 'ipswich': 'ipswich', "nott'm forest": "nott'm forest", 'nottingham forest': "nott'm forest",
        # La Liga
        'barcelona': 'barcelona', 'real madrid': 'real madrid', 'ath madrid': 'ath madrid', 'atletico madrid': 'ath madrid',
        'sevilla': 'sevilla', 'valencia': 'valencia', 'villarreal': 'villarreal', 'real betis': 'betis', 'betis': 'betis',
        'real sociedad': 'sociedad', 'ath bilbao': 'ath bilbao', 'athletic bilbao': 'ath bilbao', 'athletic club': 'ath bilbao',
        'celta': 'celta', 'celta vigo': 'celta', 'getafe': 'getafe', 'alaves': 'alaves',
        'osasuna': 'osasuna', 'mallorca': 'mallorca', 'granada': 'granada', 'cadiz': 'cadiz',
        'girona': 'girona', 'almeria': 'almeria', 'las palmas': 'las palmas', 'rayo vallecano': 'vallecano',
        'espanol': 'espanol', 'espanyol': 'espanol', 'leganes': 'leganes', 'valladolid': 'valladolid',
        # Ligue 1
        'paris sg': 'paris sg', 'paris saint germain': 'paris sg', 'psg': 'paris sg',
        'marseille': 'marseille', 'lyon': 'lyon', 'monaco': 'monaco', 'lille': 'lille',
        'nice': 'nice', 'rennes': 'rennes', 'lens': 'lens', 'nantes': 'nantes',
        'strasbourg': 'strasbourg', 'montpellier': 'montpellier', 'toulouse': 'toulouse',
        'reims': 'reims', 'brest': 'brest', 'lorient': 'lorient', 'le havre': 'le havre',
        'clermont': 'clermont', 'metz': 'metz', 'auxerre': 'auxerre', 'angers': 'angers', 'st etienne': 'st etienne',
        # Scottish
        'celtic': 'celtic', 'rangers': 'rangers', 'hearts': 'hearts', 'aberdeen': 'aberdeen',
        'hibernian': 'hibernian', 'dundee': 'dundee', 'motherwell': 'motherwell', 'st mirren': 'st mirren',
        'st johnstone': 'st johnstone', 'kilmarnock': 'kilmarnock', 'ross county': 'ross county', 'dundee utd': 'dundee utd',
    }

    def normalize_team(name):
        """Normalizza nome squadra"""
        name = name.lower().strip()
        return TEAM_NAME_MAP.get(name, name)

    try:
        url = "https://www.football-data.co.uk/fixtures.csv"
        response = requests.get(url, timeout=30)
        response.raise_for_status()

        # Parse CSV
        from io import StringIO
        df = pd.read_csv(StringIO(response.text))

        odds_map = {}

        for _, row in df.iterrows():
            home = str(row.get('HomeTeam', '')).strip()
            away = str(row.get('AwayTeam', '')).strip()

            if not home or not away:
                continue

            # Normalizza nomi squadre
            home_norm = normalize_team(home)
            away_norm = normalize_team(away)

            # Get Bet365 odds (most popular), fallback to average
            home_odds = row.get('B365H') or row.get('AvgH') or 2.0
            draw_odds = row.get('B365D') or row.get('AvgD') or 3.5
            away_odds = row.get('B365A') or row.get('AvgA') or 3.0

            try:
                odds_map[(home_norm, away_norm)] = {
                    'home': float(home_odds),
                    'draw': float(draw_odds),
                    'away': float(away_odds),
                    'league': row.get('Div', ''),
                    'date': row.get('Date', ''),
                    'time': row.get('Time', ''),
                    'original_home': home,
                    'original_away': away
                }
            except (ValueError, TypeError):
                pass

        print(f"  ✓ {len(odds_map)} partite con quote reali")
        return odds_map

    except Exception as e:
        print(f"  ✗ Errore scaricamento quote: {e}")
        return {}


def generate_predictions_for_fixtures():
    """
    Genera predizioni per tutte le fixture usando l'API (V4 Ensemble)
    """

    # Carica fixture
    fixtures_path = os.path.join(DATA_DIR, 'upcoming_fixtures.json')
    if not os.path.exists(fixtures_path):
        print("Nessuna fixture trovata")
        return []

    with open(fixtures_path) as f:
        fixtures = json.load(f)

    # Scarica quote reali
    real_odds = fetch_real_odds()

    API_URL = 'http://localhost:3098/api/predict'

    RESULT_MAP = {0: 'AWAY', 1: 'DRAW', 2: 'HOME'}
    RESULT_LABELS = {0: 'Away Win', 1: 'Draw', 2: 'Home Win'}

    predictions = []
    odds_found = 0

    print(f"\nGenerando predizioni per {len(fixtures)} fixture usando API (V4 Ensemble)...")

    for fixture in fixtures:
        league_code = fixture['league_code']
        home_team = fixture['home_team']
        away_team = fixture['away_team']

        try:
            # Chiama l'API per la predizione V4
            response = requests.post(API_URL, json={
                'home_team': home_team,
                'away_team': away_team,
                'league': league_code
            }, timeout=10)

            if response.status_code == 200:
                pred_data = response.json()

                prediction = {
                    **fixture,
                    'prediction': pred_data.get('prediction', 'HOME'),
                    'prediction_label': pred_data.get('prediction_label', 'Home Win'),
                    'prediction_code': pred_data.get('prediction_code', 2),
                    'confidence': pred_data.get('confidence', 40),
                    'home_prob': pred_data.get('home_prob', 33),
                    'draw_prob': pred_data.get('draw_prob', 33),
                    'away_prob': pred_data.get('away_prob', 33),
                    'home_form': pred_data.get('home_form', {}),
                    'away_form': pred_data.get('away_form', {}),
                    'generated_at': datetime.now().isoformat()
                }
            else:
                # Fallback se API non risponde
                prediction = {
                    **fixture,
                    'prediction': 'HOME',
                    'prediction_label': 'Home Win',
                    'prediction_code': 2,
                    'confidence': 40,
                    'home_prob': 40,
                    'draw_prob': 30,
                    'away_prob': 30,
                    'home_form': {},
                    'away_form': {},
                    'generated_at': datetime.now().isoformat()
                }

        except Exception as e:
            print(f"  Errore predizione {home_team} vs {away_team}: {e}")
            prediction = {
                **fixture,
                'prediction': 'HOME',
                'prediction_label': 'Home Win',
                'prediction_code': 2,
                'confidence': 40,
                'home_prob': 40,
                'draw_prob': 30,
                'away_prob': 30,
                'home_form': {},
                'away_form': {},
                'generated_at': datetime.now().isoformat()
            }

        # Aggiungi quote reali se disponibili
        # Normalizza i nomi per il matching
        home_norm = home_team.lower().strip()
        away_norm = away_team.lower().strip()
        odds_key = (home_norm, away_norm)

        if odds_key in real_odds:
            odds = real_odds[odds_key]
            prediction['odds_home'] = odds['home']
            prediction['odds_draw'] = odds['draw']
            prediction['odds_away'] = odds['away']
            prediction['odds_source'] = 'Bet365'
            odds_found += 1
        else:
            # Calcola quote implicite dalla probabilità del modello
            # EV sarà mostrato come N/A nel frontend per queste partite
            prediction['odds_home'] = round(100 / max(prediction['home_prob'], 1), 2)
            prediction['odds_draw'] = round(100 / max(prediction['draw_prob'], 1), 2)
            prediction['odds_away'] = round(100 / max(prediction['away_prob'], 1), 2)
            prediction['odds_source'] = 'Implied'

        predictions.append(prediction)

    # Ordina per data
    predictions.sort(key=lambda x: x['timestamp'])

    # Salva
    output_path = os.path.join(DATA_DIR, 'predictions_upcoming.json')
    with open(output_path, 'w') as f:
        json.dump(predictions, f, indent=2, ensure_ascii=False)

    print(f"Salvate {len(predictions)} predizioni in predictions_upcoming.json")
    print(f"  ✓ {odds_found} con quote REALI (Bet365)")
    print(f"  ✓ {len(predictions) - odds_found} con quote implicite")

    return predictions


if __name__ == "__main__":
    # Raccogli fixture
    collector = FixtureCollector()
    fixtures = collector.collect_all_fixtures()

    # Genera predizioni
    predictions = generate_predictions_for_fixtures()

    print(f"\nPrime 5 predizioni:")
    for p in predictions[:5]:
        print(f"  {p['date']} {p['time']} | {p['league_name']}")
        print(f"    {p['home_team']} vs {p['away_team']}")
        print(f"    Pred: {p['prediction']} ({p['confidence']:.0f}%)")
        print()
