"""
Fetch All Real Historical Odds from BallDontLie API
Supports: NBA, NFL, NHL, NCAAF
"""

import json
import os
import time
import urllib.request
import urllib.error
from datetime import datetime, timedelta
from collections import defaultdict

API_KEY = os.environ.get("BALLDONTLIE_API_KEY")
if not API_KEY:
    raise RuntimeError("BALLDONTLIE_API_KEY is not set. Put it in the environment (recommended: .env / systemd EnvironmentFile).")
DATA_DIR = '/var/www/html/eventheodds/data/betting'
REQUEST_DELAY = 0.3

def api_request(url: str) -> dict:
    headers = {'Authorization': API_KEY}
    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)
        return data
    except Exception as e:
        print(f'  Error: {e}')
        return {'data': []}

def merge_odds(game: dict, odds_list: list, sport: str) -> dict:
    priority = ['draftkings', 'fanduel', 'betmgm', 'caesars', 'bet365']
    best = next((o for v in priority for o in odds_list if o.get('vendor','').lower()==v), odds_list[0] if odds_list else None)
    if not best:
        return None
    
    home_score = game.get('home_team_score') or game.get('home_score') or 0
    away_score = game.get('visitor_team_score') or game.get('away_score') or 0
    margin = home_score - away_score
    
    try:
        spread = float(best.get('spread_home_value', 0) or 0)
    except:
        spread = 0
    
    winner = 'home' if home_score > away_score else ('away' if away_score > home_score else 'draw')
    spread_covered = 'home' if (spread < 0 and margin > abs(spread)) or (spread >= 0 and margin > -spread) else 'away'
    
    home_team = game.get('home_team', {})
    away_team = game.get('visitor_team') or game.get('away_team', {})
    home_name = home_team.get('name', home_team.get('full_name', str(home_team))) if isinstance(home_team, dict) else str(home_team)
    away_name = away_team.get('name', away_team.get('full_name', str(away_team))) if isinstance(away_team, dict) else str(away_team)
    
    return {
        'id': str(game.get('id')),
        'sport': sport,
        'date': str(game.get('date', ''))[:10],
        'season': game.get('season', 2024),
        'homeTeam': home_name,
        'awayTeam': away_name,
        'scores': {'homeScore': home_score, 'awayScore': away_score},
        'odds': {
            'moneylineHome': best.get('moneyline_home_odds', -110),
            'moneylineAway': best.get('moneyline_away_odds', 100),
            'spreadHome': spread, 'spreadAway': -spread,
            'totalLine': float(best.get('total_value', 0) or 0),
            'source': 'balldontlie', 'vendor': best.get('vendor', 'unknown')
        },
        'result': {'winner': winner, 'spreadCovered': spread_covered, 'margin': margin, 'totalPoints': home_score + away_score}
    }

def fetch_nba(start: str, end: str) -> list:
    print(f'\n=== NBA: {start} to {end} ===')
    results = []
    current = datetime.strptime(start, '%Y-%m-%d')
    end_dt = datetime.strptime(end, '%Y-%m-%d')
    
    while current <= end_dt:
        ds = current.strftime('%Y-%m-%d')
        games = api_request(f'https://api.balldontlie.io/v1/games?dates[]={ds}').get('data', [])
        odds = api_request(f'https://api.balldontlie.io/v2/odds?dates[]={ds}').get('data', [])
        
        odds_map = defaultdict(list)
        for o in odds:
            odds_map[o.get('game_id')].append(o)
        
        for g in games:
            if g.get('status', '').lower() not in ('final', 'f'):
                continue
            game_odds = odds_map.get(g.get('id'), [])
            if game_odds:
                m = merge_odds(g, game_odds, 'nba')
                if m:
                    results.append(m)
        
        print(f'  {ds}: {len([g for g in games if g.get('status','').lower() in ('final','f')])} games, {len([r for r in results if r['date']==ds])} with odds')
        current += timedelta(days=1)
    
    return results

def fetch_nhl(start: str, end: str) -> list:
    print(f'\n=== NHL: {start} to {end} ===')
    results = []
    current = datetime.strptime(start, '%Y-%m-%d')
    end_dt = datetime.strptime(end, '%Y-%m-%d')
    
    while current <= end_dt:
        ds = current.strftime('%Y-%m-%d')
        games = api_request(f'https://api.balldontlie.io/nhl/v1/games?dates[]={ds}').get('data', [])
        odds = api_request(f'https://api.balldontlie.io/nhl/v1/odds?dates[]={ds}').get('data', [])
        
        odds_map = defaultdict(list)
        for o in odds:
            odds_map[o.get('game_id')].append(o)
        
        for g in games:
            status = g.get('status', '').lower()
            if status not in ('final', 'f', 'finished'):
                continue
            game_odds = odds_map.get(g.get('id'), [])
            if game_odds:
                m = merge_odds(g, game_odds, 'nhl')
                if m:
                    results.append(m)
        
        if games:
            print(f'  {ds}: {len(games)} games, {len([r for r in results if r['date']==ds])} with odds')
        current += timedelta(days=1)
    
    return results

def fetch_nfl(season: int) -> list:
    print(f'\n=== NFL Season {season} ===')
    results = []
    
    for week in range(1, 19):
        odds = api_request(f'https://api.balldontlie.io/nfl/v1/odds?season={season}&week={week}').get('data', [])
        if odds:
            print(f'  Week {week}: {len(odds)} odds entries')
            # NFL odds don't have game data attached, store raw odds
            for o in odds:
                results.append({
                    'id': str(o.get('id')),
                    'sport': 'nfl',
                    'game_id': o.get('game_id'),
                    'season': season,
                    'week': week,
                    'vendor': o.get('vendor'),
                    'odds': {
                        'spreadHome': float(o.get('spread_home_value', 0) or 0),
                        'spreadHomeOdds': o.get('spread_home_odds'),
                        'spreadAway': float(o.get('spread_away_value', 0) or 0),
                        'spreadAwayOdds': o.get('spread_away_odds'),
                        'moneylineHome': o.get('moneyline_home_odds'),
                        'moneylineAway': o.get('moneyline_away_odds'),
                        'totalLine': float(o.get('total_value', 0) or 0),
                        'source': 'balldontlie'
                    }
                })
    
    return results

def fetch_ncaaf(season: int) -> list:
    print(f'\n=== NCAAF Season {season} ===')
    results = []
    
    for week in range(1, 16):
        odds = api_request(f'https://api.balldontlie.io/ncaaf/v1/odds?season={season}&week={week}').get('data', [])
        if odds:
            print(f'  Week {week}: {len(odds)} odds entries')
            for o in odds:
                results.append({
                    'id': str(o.get('id')),
                    'sport': 'ncaaf',
                    'game_id': o.get('game_id'),
                    'season': season,
                    'week': week,
                    'vendor': o.get('vendor'),
                    'odds': {
                        'spreadHome': float(o.get('spread_home_value', 0) or 0),
                        'spreadHomeOdds': o.get('spread_home_odds'),
                        'moneylineHome': o.get('moneyline_home_odds'),
                        'moneylineAway': o.get('moneyline_away_odds'),
                        'totalLine': float(o.get('total_value', 0) or 0),
                        'source': 'balldontlie'
                    }
                })
    
    return results

def save_data(data: list, sport: str):
    if not data:
        print(f'  No {sport} data to save')
        return
    
    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)} {sport} records to {filepath}')

def main():
    print('='*60)
    print('BallDontLie All Sports Odds Downloader')
    print('='*60)
    
    os.makedirs(DATA_DIR, exist_ok=True)
    
    # NBA - 2 months
    nba = fetch_nba('2025-11-01', '2025-12-31')
    save_data(nba, 'nba')
    
    # NHL - 2 months  
    nhl = fetch_nhl('2025-10-01', '2025-12-31')
    save_data(nhl, 'nhl')
    
    # NFL - 2025 season
    nfl = fetch_nfl(2025)
    save_data(nfl, 'nfl')
    
    # NCAAF - 2025 season
    ncaaf = fetch_ncaaf(2025)
    save_data(ncaaf, 'ncaaf')
    
    print('\n' + '='*60)
    print('All downloads complete!')
    print('='*60)

if __name__ == '__main__':
    main()
