#!/usr/bin/env python3
"""
BET.CUTTALO.COM - FOOTBALL-DATA.ORG API COLLECTOR
Usa l'API ufficiale di football-data.org per:
- Partite programmate in tempo reale
- Risultati live
- Classifiche aggiornate
- Statistiche dettagliate

API Key: Free tier (10 req/min, top 5 + altre leghe)
"""

import requests
import json
import os
import time
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import logging
from dotenv import load_dotenv

# Load environment
load_dotenv(os.path.join(os.path.dirname(__file__), '..', '.env'))

# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

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


class FootballDataAPI:
    """
    Client per football-data.org API
    Free tier: 10 chiamate/min, molte competizioni disponibili
    """

    BASE_URL = "https://api.football-data.org/v4"

    # Competizioni disponibili (Free tier)
    COMPETITIONS = {
        # Top 5 Leagues
        'PL': {'name': 'Premier League', 'country': 'England', 'flag': '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'code': 'E0'},
        'PD': {'name': 'La Liga', 'country': 'Spain', 'flag': '🇪🇸', 'code': 'SP1'},
        'SA': {'name': 'Serie A', 'country': 'Italy', 'flag': '🇮🇹', 'code': 'I1'},
        'BL1': {'name': 'Bundesliga', 'country': 'Germany', 'flag': '🇩🇪', 'code': 'D1'},
        'FL1': {'name': 'Ligue 1', 'country': 'France', 'flag': '🇫🇷', 'code': 'F1'},

        # European Cups
        'CL': {'name': 'Champions League', 'country': 'Europe', 'flag': '🏆', 'code': 'CL'},
        'EL': {'name': 'Europa League', 'country': 'Europe', 'flag': '🏆', 'code': 'EL'},
        'EC': {'name': 'European Championship', 'country': 'Europe', 'flag': '🇪🇺', 'code': 'EURO'},
        'WC': {'name': 'World Cup', 'country': 'World', 'flag': '🌍', 'code': 'WC'},

        # Other Leagues (Free tier)
        'PPL': {'name': 'Primeira Liga', 'country': 'Portugal', 'flag': '🇵🇹', 'code': 'P1'},
        'DED': {'name': 'Eredivisie', 'country': 'Netherlands', 'flag': '🇳🇱', 'code': 'N1'},
        'BSA': {'name': 'Serie A', 'country': 'Brazil', 'flag': '🇧🇷', 'code': 'BRA'},
        'ELC': {'name': 'Championship', 'country': 'England', 'flag': '🏴󠁧󠁢󠁥󠁮󠁧󠁿', 'code': 'E1'},
    }

    def __init__(self, api_key: str = None):
        self.api_key = api_key or os.getenv('FOOTBALL_DATA_API_KEY')
        if not self.api_key:
            raise ValueError("FOOTBALL_DATA_API_KEY non configurata!")

        self.session = requests.Session()
        self.session.headers.update({
            'X-Auth-Token': self.api_key
        })

        self.request_count = 0
        self.last_request = None

    def _rate_limit(self):
        """Rispetta rate limit: 10 req/min"""
        if self.last_request:
            elapsed = (datetime.now() - self.last_request).total_seconds()
            if elapsed < 6:  # 10 req/min = 1 req ogni 6 sec
                time.sleep(6 - elapsed)

        self.last_request = datetime.now()
        self.request_count += 1

    def _get(self, endpoint: str, params: Dict = None) -> Optional[Dict]:
        """GET request con rate limiting"""
        self._rate_limit()

        url = f"{self.BASE_URL}{endpoint}"
        try:
            response = self.session.get(url, params=params, timeout=30)

            if response.status_code == 429:
                logger.warning("Rate limit raggiunto, attendo 60 secondi...")
                time.sleep(60)
                return self._get(endpoint, params)

            response.raise_for_status()
            return response.json()

        except requests.exceptions.RequestException as e:
            logger.error(f"Errore API: {e}")
            return None

    def get_competitions(self) -> List[Dict]:
        """Lista tutte le competizioni disponibili"""
        data = self._get("/competitions")
        if data:
            return data.get('competitions', [])
        return []

    def get_matches(self, competition: str = None, date_from: str = None,
                   date_to: str = None, status: str = None) -> List[Dict]:
        """
        Ottieni partite

        Args:
            competition: Codice competizione (es. 'PL', 'CL')
            date_from: Data inizio (YYYY-MM-DD)
            date_to: Data fine (YYYY-MM-DD)
            status: 'SCHEDULED', 'LIVE', 'FINISHED', etc.
        """
        if competition:
            endpoint = f"/competitions/{competition}/matches"
        else:
            endpoint = "/matches"

        params = {}
        if date_from:
            params['dateFrom'] = date_from
        if date_to:
            params['dateTo'] = date_to
        if status:
            params['status'] = status

        data = self._get(endpoint, params)
        if data:
            return data.get('matches', [])
        return []

    def get_upcoming_matches(self, days: int = 14) -> Dict[str, List[Dict]]:
        """
        Ottieni tutte le partite programmate per i prossimi X giorni

        Returns:
            Dict con competizione -> lista partite
        """
        today = datetime.now().strftime('%Y-%m-%d')
        future = (datetime.now() + timedelta(days=days)).strftime('%Y-%m-%d')

        all_matches = {}

        for comp_code, comp_info in self.COMPETITIONS.items():
            logger.info(f"Fetching {comp_info['name']}...")

            matches = self.get_matches(
                competition=comp_code,
                date_from=today,
                date_to=future,
                status='SCHEDULED'
            )

            if matches:
                # Trasforma nel nostro formato
                formatted = []
                for m in matches:
                    fixture = self._format_match(m, comp_code, comp_info)
                    if fixture:
                        formatted.append(fixture)

                if formatted:
                    all_matches[comp_info['code']] = formatted
                    logger.info(f"  -> {len(formatted)} partite trovate")
            else:
                logger.info(f"  -> Nessuna partita")

        return all_matches

    def get_live_matches(self) -> List[Dict]:
        """Ottieni partite in corso"""
        data = self._get("/matches", {'status': 'LIVE,IN_PLAY'})
        if data:
            return data.get('matches', [])
        return []

    def get_finished_matches(self, competition: str, days_back: int = 7) -> List[Dict]:
        """Ottieni risultati partite finite"""
        date_from = (datetime.now() - timedelta(days=days_back)).strftime('%Y-%m-%d')
        date_to = datetime.now().strftime('%Y-%m-%d')

        return self.get_matches(
            competition=competition,
            date_from=date_from,
            date_to=date_to,
            status='FINISHED'
        )

    def get_standings(self, competition: str) -> Dict:
        """Ottieni classifica"""
        data = self._get(f"/competitions/{competition}/standings")
        if data:
            return data
        return {}

    def _format_match(self, match: Dict, comp_code: str, comp_info: Dict) -> Optional[Dict]:
        """Formatta una partita nel nostro formato"""
        try:
            utc_date = match.get('utcDate', '')
            if utc_date:
                dt = datetime.fromisoformat(utc_date.replace('Z', '+00:00'))
                date_str = dt.strftime('%Y-%m-%d')
                time_str = dt.strftime('%H:%M')
            else:
                date_str = ''
                time_str = ''

            home_team = match.get('homeTeam', {})
            away_team = match.get('awayTeam', {})

            return {
                'id': f"{comp_info['code']}_{match.get('id')}",
                'api_id': match.get('id'),
                'date': date_str,
                'time': time_str,
                'datetime': utc_date,
                'home_team': home_team.get('shortName') or home_team.get('name', 'TBD'),
                'away_team': away_team.get('shortName') or away_team.get('name', 'TBD'),
                'home_team_id': home_team.get('id'),
                'away_team_id': away_team.get('id'),
                'league': comp_info['code'],
                'league_code': comp_code,
                'league_name': comp_info['name'],
                'country': comp_info['country'],
                'flag': comp_info['flag'],
                'matchday': match.get('matchday'),
                'stage': match.get('stage'),
                'group': match.get('group'),
                'status': match.get('status'),
                'venue': match.get('venue'),
            }
        except Exception as e:
            logger.error(f"Errore formattazione match: {e}")
            return None

    def collect_all_fixtures(self) -> Dict:
        """Raccoglie tutte le fixtures da tutte le competizioni"""
        logger.info("=" * 60)
        logger.info("RACCOLTA FIXTURES DA FOOTBALL-DATA.ORG")
        logger.info("=" * 60)

        all_fixtures = self.get_upcoming_matches(days=30)

        # Salva
        output = {
            'generated_at': datetime.now().isoformat(),
            'source': 'football-data.org',
            'fixtures_by_league': all_fixtures,
            'total_fixtures': sum(len(f) for f in all_fixtures.values()),
            'competitions_count': len(all_fixtures)
        }

        output_file = os.path.join(DATA_DIR, 'api_fixtures.json')
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(output, f, ensure_ascii=False, indent=2)

        logger.info(f"\nTotale: {output['total_fixtures']} fixtures da {output['competitions_count']} competizioni")
        logger.info(f"Salvato in: {output_file}")

        return output

    def collect_results(self, days_back: int = 7) -> Dict:
        """Raccoglie risultati recenti per verifica predizioni"""
        logger.info("=" * 60)
        logger.info(f"RACCOLTA RISULTATI (ultimi {days_back} giorni)")
        logger.info("=" * 60)

        all_results = {}

        for comp_code, comp_info in self.COMPETITIONS.items():
            logger.info(f"Fetching risultati {comp_info['name']}...")

            matches = self.get_finished_matches(comp_code, days_back)

            if matches:
                formatted = []
                for m in matches:
                    result = {
                        'id': m.get('id'),
                        'date': m.get('utcDate', '')[:10],
                        'home_team': m.get('homeTeam', {}).get('shortName', ''),
                        'away_team': m.get('awayTeam', {}).get('shortName', ''),
                        'home_goals': m.get('score', {}).get('fullTime', {}).get('home'),
                        'away_goals': m.get('score', {}).get('fullTime', {}).get('away'),
                        'league': comp_info['code'],
                        'status': m.get('status'),
                    }

                    # Calcola risultato
                    hg = result['home_goals']
                    ag = result['away_goals']
                    if hg is not None and ag is not None:
                        if hg > ag:
                            result['result'] = 'H'
                        elif hg < ag:
                            result['result'] = 'A'
                        else:
                            result['result'] = 'D'

                    formatted.append(result)

                all_results[comp_info['code']] = formatted
                logger.info(f"  -> {len(formatted)} risultati")

        # Salva
        output = {
            'generated_at': datetime.now().isoformat(),
            'results_by_league': all_results,
            'total_results': sum(len(r) for r in all_results.values())
        }

        output_file = os.path.join(DATA_DIR, 'api_results.json')
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(output, f, ensure_ascii=False, indent=2)

        logger.info(f"\nTotale: {output['total_results']} risultati")
        return output

    def collect_standings(self) -> Dict:
        """Raccoglie classifiche di tutte le leghe"""
        logger.info("=" * 60)
        logger.info("RACCOLTA CLASSIFICHE")
        logger.info("=" * 60)

        all_standings = {}

        for comp_code, comp_info in self.COMPETITIONS.items():
            # Skip cups (non hanno classifica standard)
            if comp_code in ['CL', 'EL', 'EC', 'WC']:
                continue

            logger.info(f"Fetching classifica {comp_info['name']}...")

            standings = self.get_standings(comp_code)

            if standings and 'standings' in standings:
                formatted = []
                for table in standings.get('standings', []):
                    if table.get('type') == 'TOTAL':
                        for entry in table.get('table', []):
                            team_data = {
                                'position': entry.get('position'),
                                'team': entry.get('team', {}).get('shortName', ''),
                                'team_id': entry.get('team', {}).get('id'),
                                'played': entry.get('playedGames'),
                                'won': entry.get('won'),
                                'drawn': entry.get('draw'),
                                'lost': entry.get('lost'),
                                'goals_for': entry.get('goalsFor'),
                                'goals_against': entry.get('goalsAgainst'),
                                'goal_diff': entry.get('goalDifference'),
                                'points': entry.get('points'),
                            }
                            formatted.append(team_data)

                all_standings[comp_info['code']] = formatted
                logger.info(f"  -> {len(formatted)} squadre")

        # Salva
        output = {
            'generated_at': datetime.now().isoformat(),
            'standings_by_league': all_standings
        }

        output_file = os.path.join(DATA_DIR, 'api_standings.json')
        with open(output_file, 'w', encoding='utf-8') as f:
            json.dump(output, f, ensure_ascii=False, indent=2)

        return output


def main():
    """Esegue raccolta completa"""
    try:
        api = FootballDataAPI()

        # Raccogli tutto
        api.collect_all_fixtures()
        api.collect_results(days_back=7)
        api.collect_standings()

        logger.info("\n" + "=" * 60)
        logger.info("RACCOLTA COMPLETATA!")
        logger.info("=" * 60)

    except ValueError as e:
        logger.error(f"Errore configurazione: {e}")
        logger.error("Assicurati che FOOTBALL_DATA_API_KEY sia configurata in .env")


if __name__ == '__main__':
    main()
