"""
Fetch Historical Betting Data from BallDontLie API

Uses the BallDontLie API to fetch real historical games and betting odds
for NBA, NFL, NHL, and MLB.

Environment Variables:
  BALLDONTLIE_API_KEY - Your BallDontLie API key (required)

Usage:
  python3 fetch_balldontlie_betting.py [--sport SPORT] [--season SEASON]
  
Examples:
  python3 fetch_balldontlie_betting.py --sport nfl --season 2024
  python3 fetch_balldontlie_betting.py --all-sports --season 2024
"""

import json
import os
import sys
import time
import argparse
from datetime import datetime, timedelta
import urllib.request
import urllib.error

# Configuration
API_BASE = 'https://api.balldontlie.io/v1'
DATA_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'data', 'betting')
API_KEY = os.environ.get('BALLDONTLIE_API_KEY', '')

# Rate limiting
REQUESTS_PER_MINUTE = 60
REQUEST_DELAY = 1.0  # seconds between requests

def make_request(endpoint: str, params: dict = None) -> dict:
    """Make API request with authentication and rate limiting."""
    if not API_KEY:
        raise ValueError("BALLDONTLIE_API_KEY environment variable not set")
    
    url = f"{API_BASE}/{endpoint}"
    if params:
        query = '&'.join(f"{k}={v}" for k, v in params.items() if v is not None)
        if query:
            url += f"?{query}"
    
    headers = {
        'Authorization': API_KEY,
        'Content-Type': 'application/json'
    }
    
    req = urllib.request.Request(url, headers=headers)
    
    try:
        with urllib.request.urlopen(req, timeout=30) as response:
            data = json.loads(response.read().decode('utf-8'))
        time.sleep(REQUEST_DELAY)  # Rate limiting
        return data
    except urllib.error.HTTPError as e:
        print(f"  ❌ HTTP Error {e.code}: {e.reason}")
        if e.code == 401:
            print("     Check your BALLDONTLIE_API_KEY")
        return None
    except Exception as e:
        print(f"  ❌ Error: {e}")
        return None


def fetch_games(sport: str, season: int, page: int = 1) -> list:
    """Fetch games from BallDontLie API."""
    endpoint = "games"
    params = {
        'seasons[]': season,
        'per_page': 100,
        'cursor': page if page > 1 else None
    }
    
    data = make_request(endpoint, params)
    if not data:
        return []
    
    return data.get('data', [])


def fetch_betting_odds(sport: str, season: int, game_ids: list = None) -> dict:
    """Fetch betting odds for games."""
    endpoint = "odds"
    params = {}
    
    if game_ids:
        params['game_id'] = game_ids[0] if game_ids else None
    
    data = make_request(endpoint, params)
    if not data:
        return {}
    
    # Build lookup by game_id
    odds_map = {}
    for odds in data.get('data', []):
        gid = odds.get('game_id')
        if gid:
            odds_map[gid] = odds
    
    return odds_map


def process_games(sport: str, games: list, odds_map: dict) -> list:
    """Convert API response to historical betting format."""
    result = []
    
    for g in games:
        # Skip non-final games
        status = g.get('status', '')
        if status.lower() not in ('final', 'f'):
            continue
        
        game_id = g.get('id')
        
        # Get scores
        home_score = g.get('home_team_score', 0) or 0
        away_score = g.get('visitor_team_score', g.get('away_team_score', 0)) or 0
        
        if home_score == 0 and away_score == 0:
            continue
        
        # Get team names
        home_team = g.get('home_team', {})
        away_team = g.get('visitor_team', g.get('away_team', {}))
        
        if isinstance(home_team, dict):
            home_name = home_team.get('name', home_team.get('abbreviation', 'Unknown'))
        else:
            home_name = str(home_team)
        
        if isinstance(away_team, dict):
            away_name = away_team.get('name', away_team.get('abbreviation', 'Unknown'))
        else:
            away_name = str(away_team)
        
        # Get date
        date_str = g.get('date', '')
        if 'T' in date_str:
            date_str = date_str.split('T')[0]
        
        # Get odds if available
        game_odds = odds_map.get(game_id, {})
        
        spread_home = game_odds.get('spread_home', game_odds.get('home_spread', 0)) or 0
        ml_home = game_odds.get('moneyline_home', game_odds.get('home_ml', -110)) or -110
        ml_away = game_odds.get('moneyline_away', game_odds.get('away_ml', 100)) or 100
        total_line = game_odds.get('total_line', game_odds.get('over_under', 0)) or 0
        
        margin = home_score - away_score
        
        # Determine winner
        if home_score > away_score:
            winner = 'home'
        elif away_score > home_score:
            winner = 'away'
        else:
            winner = 'draw'
        
        # Determine spread covered
        if spread_home < 0:
            spread_covered = 'home' if margin > abs(spread_home) else 'away'
        elif spread_home > 0:
            spread_covered = 'home' if margin > -spread_home else 'away'
        else:
            spread_covered = winner
        
        result.append({
            'id': str(game_id),
            'sport': sport,
            'date': date_str,
            'season': g.get('season', 2024),
            'homeTeam': home_name,
            'awayTeam': away_name,
            'scores': {
                'homeScore': home_score,
                'awayScore': away_score
            },
            'odds': {
                'moneylineHome': ml_home,
                'moneylineAway': ml_away,
                'spreadHome': spread_home,
                'spreadAway': -spread_home,
                'totalLine': total_line,
                'source': 'balldontlie'
            },
            'result': {
                'winner': winner,
                'spreadCovered': spread_covered,
                'margin': margin,
                'totalPoints': home_score + away_score
            }
        })
    
    return result


def fetch_sport_data(sport: str, season: int) -> list:
    """Fetch all games and betting odds for a sport/season."""
    print(f"Fetching {sport.upper()} data for {season} season...")
    
    all_games = []
    page = 1
    max_pages = 20  # Safety limit
    
    while page <= max_pages:
        print(f"  Fetching page {page}...")
        games = fetch_games(sport, season, page)
        
        if not games:
            break
        
        all_games.extend(games)
        
        if len(games) < 100:  # Last page
            break
        
        page += 1
    
    print(f"  Found {len(all_games)} total games")
    
    # Fetch betting odds
    game_ids = [g.get('id') for g in all_games if g.get('id')]
    odds_map = {}
    
    if game_ids:
        print(f"  Fetching betting odds...")
        # Fetch in batches
        for i in range(0, len(game_ids), 50):
            batch = game_ids[i:i+50]
            batch_odds = fetch_betting_odds(sport, season, batch)
            odds_map.update(batch_odds)
        print(f"  Found odds for {len(odds_map)} games")
    
    # Process games
    processed = process_games(sport, all_games, odds_map)
    print(f"  Processed {len(processed)} final games")
    
    return processed


def main():
    parser = argparse.ArgumentParser(description='Fetch BallDontLie betting data')
    parser.add_argument('--sport', type=str, help='Sport (nba, nfl, nhl, mlb)')
    parser.add_argument('--season', type=int, default=2024, help='Season year')
    parser.add_argument('--all-sports', action='store_true', help='Fetch all sports')
    args = parser.parse_args()
    
    if not API_KEY:
        print("❌ Error: BALLDONTLIE_API_KEY environment variable not set")
        print("   Get your API key from https://app.balldontlie.io")
        sys.exit(1)
    
    os.makedirs(DATA_DIR, exist_ok=True)
    
    sports = ['nba', 'nfl', 'nhl', 'mlb'] if args.all_sports else [args.sport]
    
    for sport in sports:
        if not sport:
            continue
        
        try:
            data = fetch_sport_data(sport, args.season)
            
            if data:
                filepath = os.path.join(DATA_DIR, f'{sport}_historical.json')
                with open(filepath, 'w') as f:
                    json.dump(data, f, indent=2)
                print(f"  ✅ Saved {len(data)} games to {filepath}")
            else:
                print(f"  ⚠️ No data fetched for {sport.upper()}")
        
        except Exception as e:
            print(f"  ❌ Error fetching {sport.upper()}: {e}")
    
    print()
    print("Done! Run validate_betting_data.py to verify data quality.")


if __name__ == '__main__':
    main()
