#!/usr/bin/env python3
"""
TheSportsDB Data Fetcher
Fetches historical game data from TheSportsDB Premium API

Premium API Key: 428892
Docs: https://www.thesportsdb.com/api.php
"""

import os
import json
import requests
from datetime import datetime, timedelta
from typing import Dict, List, Any, Optional
import hashlib
import time


class TheSportsDBFetcher:
    """
    Fetches sports data from TheSportsDB API.
    Includes caching to avoid redundant API calls.
    """
    
    API_KEY = "428892"
    BASE_URL_V1 = f"https://www.thesportsdb.com/api/v1/json/{API_KEY}"
    BASE_URL_V2 = f"https://www.thesportsdb.com/api/v2/json"
    
    # Cache duration in seconds (30 days for historical data)
    CACHE_DURATION = 30 * 24 * 60 * 60
    
    # Priority leagues for backtesting
    PRIORITY_LEAGUES = {
        # Soccer
        'epl': 4328,        # English Premier League
        'laliga': 4335,     # Spanish La Liga
        'bundesliga': 4331, # German Bundesliga
        'seriea': 4332,     # Italian Serie A
        'ligue1': 4334,     # French Ligue 1
        'mls': 4346,        # American MLS
        'ucl': 4480,        # UEFA Champions League
        
        # American Sports
        'nfl': 4391,        # NFL
        'nba': 4387,        # NBA
        'nhl': 4380,        # NHL
        'mlb': 4424,        # MLB
        
        # College
        'ncaaf': 4479,      # NCAA Football
        'ncaab': 4607,      # NCAA Basketball
        
        # Combat Sports
        'ufc': 4443,        # UFC
        'boxing': 4445,     # Boxing
    }
    
    def __init__(self, cache_dir: str = './data/cache/thesportsdb'):
        """
        Initialize the fetcher.
        
        Args:
            cache_dir: Directory to store cached responses
        """
        self.cache_dir = cache_dir
        os.makedirs(cache_dir, exist_ok=True)
    
    def _get_cache_key(self, endpoint: str, params: Dict = None) -> str:
        """Generate a unique cache key for the request"""
        param_str = json.dumps(params or {}, sort_keys=True)
        key_str = f"thesportsdb:{endpoint}:{param_str}"
        return hashlib.md5(key_str.encode()).hexdigest()
    
    def _get_from_cache(self, cache_key: str) -> Optional[Any]:
        """Get cached response if valid"""
        cache_file = os.path.join(self.cache_dir, f"{cache_key}.json")
        
        if os.path.exists(cache_file):
            try:
                with open(cache_file, 'r') as f:
                    cached = json.load(f)
                
                cached_at = cached.get('cached_at', 0)
                if time.time() - cached_at < self.CACHE_DURATION:
                    return cached.get('data')
            except (json.JSONDecodeError, IOError):
                pass
        
        return None
    
    def _save_to_cache(self, cache_key: str, data: Any) -> None:
        """Save response to cache"""
        cache_file = os.path.join(self.cache_dir, f"{cache_key}.json")
        
        try:
            with open(cache_file, 'w') as f:
                json.dump({
                    'cached_at': time.time(),
                    'data': data
                }, f)
        except IOError:
            pass
    
    def _fetch_api(self, endpoint: str, params: Dict = None, use_cache: bool = True) -> Any:
        """
        Fetch data from TheSportsDB API.
        
        Args:
            endpoint: API endpoint (e.g., 'all_leagues.php')
            params: Query parameters
            use_cache: Whether to use cache
            
        Returns:
            API response data
        """
        params = params or {}
        
        # Check cache first
        if use_cache:
            cache_key = self._get_cache_key(endpoint, params)
            cached = self._get_from_cache(cache_key)
            if cached is not None:
                return cached
        
        # Build URL
        url = f"{self.BASE_URL_V1}/{endpoint}"
        
        try:
            response = requests.get(url, params=params, timeout=30)
            response.raise_for_status()
            data = response.json()
            
            # Cache the response
            if use_cache:
                self._save_to_cache(cache_key, data)
            
            return data
        except requests.RequestException as e:
            print(f"[TheSportsDB] API request failed: {e}")
            return None
    
    def get_all_leagues(self) -> List[Dict]:
        """Get all available leagues"""
        data = self._fetch_api('all_leagues.php')
        return data.get('leagues', []) if data else []
    
    def get_past_events(self, league_id: int, limit: int = 50) -> List[Dict]:
        """
        Get past events for a league.
        
        Args:
            league_id: TheSportsDB league ID
            limit: Number of events to fetch (max varies by league)
            
        Returns:
            List of past event dictionaries
        """
        data = self._fetch_api('eventspastleague.php', {'id': league_id})
        events = data.get('events', []) if data else []
        return events[:limit] if events else []
    
    def get_next_events(self, league_id: int, limit: int = 25) -> List[Dict]:
        """Get upcoming events for a league"""
        data = self._fetch_api('eventsnextleague.php', {'id': league_id})
        events = data.get('events', []) if data else []
        return events[:limit] if events else []
    
    def search_team(self, team_name: str) -> Optional[Dict]:
        """Search for a team by name"""
        data = self._fetch_api('searchteams.php', {'t': team_name})
        teams = data.get('teams', []) if data else []
        return teams[0] if teams else None
    
    def get_events_by_season(self, league_id: int, season: str) -> List[Dict]:
        """
        Get all events for a league in a specific season.
        
        Args:
            league_id: TheSportsDB league ID
            season: Season string (e.g., '2024-2025' or '2024')
            
        Returns:
            List of events
        """
        data = self._fetch_api('eventsseason.php', {'id': league_id, 's': season})
        return data.get('events', []) if data else []
    
    def normalize_event(self, event: Dict) -> Dict:
        """
        Normalize event data to a common format for backtesting.
        
        Args:
            event: Raw event from API
            
        Returns:
            Normalized event dictionary
        """
        home_score = event.get('intHomeScore')
        away_score = event.get('intAwayScore')
        
        # Determine result
        result = 'pending'
        if home_score is not None and away_score is not None:
            try:
                h = int(home_score)
                a = int(away_score)
                if h > a:
                    result = 'home_win'
                elif a > h:
                    result = 'away_win'
                else:
                    result = 'draw'
            except (ValueError, TypeError):
                pass
        
        return {
            'event_id': event.get('idEvent'),
            'date': event.get('dateEvent'),
            'time': event.get('strTime'),
            'league': event.get('strLeague'),
            'league_id': event.get('idLeague'),
            'season': event.get('strSeason'),
            'home_team': event.get('strHomeTeam'),
            'away_team': event.get('strAwayTeam'),
            'home_score': home_score,
            'away_score': away_score,
            'result': result,
            'venue': event.get('strVenue'),
            'status': event.get('strStatus'),
            'sport': event.get('strSport'),
        }
    
    def fetch_priority_leagues(self, seasons: List[str] = None) -> Dict[str, List[Dict]]:
        """
        Fetch events for all priority leagues.
        
        Args:
            seasons: List of seasons to fetch (e.g., ['2024-2025', '2023-2024'])
            
        Returns:
            Dictionary mapping league key to list of normalized events
        """
        if seasons is None:
            seasons = ['2024-2025', '2023-2024']
        
        all_events = {}
        
        for key, league_id in self.PRIORITY_LEAGUES.items():
            print(f"[TheSportsDB] Fetching {key} (ID: {league_id})...")
            league_events = []
            
            for season in seasons:
                events = self.get_events_by_season(league_id, season)
                if events:
                    normalized = [self.normalize_event(e) for e in events]
                    league_events.extend(normalized)
                    print(f"  - {season}: {len(events)} events")
            
            all_events[key] = league_events
        
        return all_events


# Singleton instance for easy access
_fetcher_instance = None

def get_fetcher() -> TheSportsDBFetcher:
    """Get or create the singleton fetcher instance"""
    global _fetcher_instance
    if _fetcher_instance is None:
        _fetcher_instance = TheSportsDBFetcher()
    return _fetcher_instance


if __name__ == '__main__':
    # Test the fetcher
    print("=" * 60)
    print("TheSportsDB Fetcher Test")
    print("=" * 60)
    
    fetcher = get_fetcher()
    
    # Test: Get leagues
    leagues = fetcher.get_all_leagues()
    print(f"\n✓ Found {len(leagues)} leagues")
    
    # Test: Get past events for EPL
    epl_events = fetcher.get_past_events(4328, limit=5)
    print(f"\n✓ EPL past events: {len(epl_events)}")
    for e in epl_events[:3]:
        print(f"  - {e.get('strEvent')} ({e.get('dateEvent')})")
    
    # Test: Search team
    team = fetcher.search_team('Arsenal')
    if team:
        print(f"\n✓ Found team: {team.get('strTeam')} ({team.get('strLeague')})")
    
    print("\n" + "=" * 60)
    print("✅ TheSportsDB Fetcher tests completed!")
