"""
Fetch Real Historical Odds from BallDontLie API

Downloads NBA and NFL betting odds and saves to historical JSON files.
"""

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

# Configuration
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.5  # Rate limiting

def fetch_nba_odds(date_str: str) -> list:
    """Fetch NBA odds for a specific date."""
    url = f'https://api.balldontlie.io/v2/odds?dates[]={date_str}'
    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.get('data', [])
    except Exception as e:
        print(f'  Error fetching NBA odds for {date_str}: {e}')
        return []

def fetch_nba_games(date_str: str) -> list:
    """Fetch NBA games for a specific date."""
    url = f'https://api.balldontlie.io/v1/games?dates[]={date_str}'
    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.get('data', [])
    except Exception as e:
        print(f'  Error fetching NBA games for {date_str}: {e}')
        return []

def fetch_nfl_odds(season: int, week: int) -> list:
    """Fetch NFL odds for a specific season/week."""
    url = f'https://api.balldontlie.io/nfl/v1/odds?season={season}&week={week}'
    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.get('data', [])
    except Exception as e:
        print(f'  Error fetching NFL odds for {season} week {week}: {e}')
        return []

def merge_game_with_odds(game: dict, odds_list: list, sport: str) -> dict:
    """Merge game data with best odds (use DraftKings/FanDuel as default)."""
    
    # Pick best odds source in priority order
    priority = ['draftkings', 'fanduel', 'betmgm', 'caesars', 'bet365']
    best_odds = None
    
    for vendor in priority:
        for odds in odds_list:
            if odds.get('vendor', '').lower() == vendor:
                best_odds = odds
                break
        if best_odds:
            break
    
    if not best_odds and odds_list:
        best_odds = odds_list[0]
    
    if not best_odds:
        return None
    
    # Get scores
    home_score = game.get('home_team_score', 0) or 0
    away_score = game.get('visitor_team_score', 0) or 0
    margin = home_score - away_score
    
    # Get spread value
    spread_str = best_odds.get('spread_home_value', '0')
    try:
        spread = float(spread_str) if spread_str else 0
    except:
        spread = 0
    
    # Determine winner and cover
    if home_score > away_score:
        winner = 'home'
    elif away_score > home_score:
        winner = 'away'
    else:
        winner = 'draw'
    
    if spread < 0:
        spread_covered = 'home' if margin > abs(spread) else 'away'
    else:
        spread_covered = 'home' if margin > -spread else 'away'
    
    # Get team names
    home_team = game.get('home_team', {})
    away_team = game.get('visitor_team', {})
    
    if isinstance(home_team, dict):
        home_name = home_team.get('name', home_team.get('full_name', 'Unknown'))
    else:
        home_name = str(home_team)
    
    if isinstance(away_team, dict):
        away_name = away_team.get('name', away_team.get('full_name', 'Unknown'))
    else:
        away_name = str(away_team)
    
    return {
        'id': str(game.get('id')),
        'sport': sport,
        'date': game.get('date', '')[:10] if game.get('date') else '',
        'season': game.get('season', 2024),
        'homeTeam': home_name,
        'awayTeam': away_name,
        'scores': {'homeScore': home_score, 'awayScore': away_score},
        'odds': {
            'moneylineHome': best_odds.get('moneyline_home_odds', -110),
            'moneylineAway': best_odds.get('moneyline_away_odds', 100),
            'spreadHome': spread,
            'spreadAway': -spread,
            'spreadHomeOdds': best_odds.get('spread_home_odds', -110),
            'spreadAwayOdds': best_odds.get('spread_away_odds', -110),
            'totalLine': float(best_odds.get('total_value', 0) or 0),
            'source': 'balldontlie',
            'vendor': best_odds.get('vendor', 'unknown')
        },
        'result': {
            'winner': winner,
            'spreadCovered': spread_covered,
            'margin': margin,
            'totalPoints': home_score + away_score
        }
    }

def fetch_nba_season(start_date: str, end_date: str) -> list:
    """Fetch NBA games and odds for a date range."""
    print(f'Fetching NBA data from {start_date} to {end_date}...')
    
    results = []
    current = datetime.strptime(start_date, '%Y-%m-%d')
    end = datetime.strptime(end_date, '%Y-%m-%d')
    
    while current <= end:
        date_str = current.strftime('%Y-%m-%d')
        print(f'  Processing {date_str}...', end=' ', flush=True)
        
        # Fetch games and odds
        games = fetch_nba_games(date_str)
        odds = fetch_nba_odds(date_str)
        
        # Group odds by game_id
        odds_by_game = defaultdict(list)
        for o in odds:
            odds_by_game[o.get('game_id')].append(o)
        
        # Match and merge
        count = 0
        for game in games:
            if game.get('status', '').lower() not in ('final', 'f'):
                continue
            
            game_id = game.get('id')
            game_odds = odds_by_game.get(game_id, [])
            
            if game_odds:
                merged = merge_game_with_odds(game, game_odds, 'nba')
                if merged:
                    results.append(merged)
                    count += 1
        
        print(f'{count} games with odds')
        current += timedelta(days=1)
    
    return results

def main():
    print('='*60)
    print('BallDontLie Real Odds Downloader')
    print('='*60)
    print()
    
    os.makedirs(DATA_DIR, exist_ok=True)
    
    # Fetch NBA - last 2 months of season
    nba_data = fetch_nba_season('2025-11-01', '2025-12-31')
    
    if nba_data:
        # Check stats
        covered = sum(1 for g in nba_data if g['odds']['spreadHome'] < 0 and g['result']['margin'] > abs(g['odds']['spreadHome']))
        not_covered = sum(1 for g in nba_data if g['odds']['spreadHome'] < 0 and g['result']['margin'] <= abs(g['odds']['spreadHome']))
        total_fav = covered + not_covered
        
        print()
        print(f'NBA: {len(nba_data)} games with real odds')
        if total_fav > 0:
            print(f'  Cover rate: {covered}/{total_fav} = {covered/total_fav*100:.1f}%')
        
        # Save
        filepath = os.path.join(DATA_DIR, 'nba_historical.json')
        with open(filepath, 'w') as f:
            json.dump(nba_data, f, indent=2)
        print(f'  Saved to {filepath}')
    
    print()
    print('Done!')

if __name__ == '__main__':
    main()
