"""Historical Backfill - Downloads all available odds data from BallDontLie API."""

import json
import os
import time
import requests
from datetime import datetime, timedelta
from collections import defaultdict
from pathlib import Path

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 = Path('/var/www/html/eventheodds/data/betting')
DELAY = 0.4

def api_get(url):
    try:
        r = requests.get(url, headers={'Authorization': API_KEY}, timeout=30)
        time.sleep(DELAY)
        if r.status_code == 200:
            return r.json()
        else:
            print(f'  Error {r.status_code}: {url[:80]}')
            return {'data': []}
    except Exception as e:
        print(f'  Request error: {e}')
        return {'data': []}

def load_existing(sport):
    f = DATA_DIR / f'{sport}_historical.json'
    if f.exists():
        with open(f) as fh:
            return json.load(fh)
    return []

def save_data(data, sport):
    DATA_DIR.mkdir(parents=True, exist_ok=True)
    with open(DATA_DIR / f'{sport}_historical.json', 'w') as f:
        json.dump(data, f, indent=2)
    print(f'  Saved {len(data)} records to {sport}_historical.json')

def merge_by_id(existing, new_items):
    ids = {str(g.get('id', g.get('game_id', ''))) for g in existing}
    added = 0
    for item in new_items:
        item_id = str(item.get('id', item.get('game_id', '')))
        if item_id and item_id not in ids:
            existing.append(item)
            ids.add(item_id)
            added += 1
    return added

def fetch_nba_historical():
    print('\n' + '='*60)
    print('NBA HISTORICAL BACKFILL (Oct 2025 - Now)')
    print('='*60)
    
    existing = load_existing('nba')
    print(f'Existing: {len(existing)} games')
    
    # Fetch Oct 2025 to now
    start = datetime(2025, 10, 1)
    end = datetime.now()
    current = start
    
    all_new = []
    while current <= end:
        ds = current.strftime('%Y-%m-%d')
        
        # Get games
        games_data = api_get(f'https://api.balldontlie.io/v1/games?dates[]={ds}')
        games = games_data.get('data', [])
        
        # Get odds  
        odds_data = api_get(f'https://api.balldontlie.io/v2/odds?dates[]={ds}')
        odds = odds_data.get('data', [])
        
        if games or odds:
            # Group odds by game_id
            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
                    
                gid = g.get('id')
                game_odds = odds_map.get(gid, [])
                
                # Pick best vendor
                best = None
                for v in ['draftkings', 'fanduel', 'betmgm', 'caesars']:
                    for o in game_odds:
                        if o.get('vendor', '').lower() == v:
                            best = o
                            break
                    if best:
                        break
                if not best and game_odds:
                    best = game_odds[0]
                
                home_score = g.get('home_team_score', 0) or 0
                away_score = g.get('visitor_team_score', 0) or 0
                margin = home_score - away_score
                
                try:
                    spread = float(best.get('spread_home_value', 0) or 0) if best else 0
                except:
                    spread = 0
                
                winner = 'home' if home_score > away_score else 'away'
                covered = 'home' if (spread < 0 and margin > abs(spread)) else 'away'
                
                ht = g.get('home_team', {})
                at = g.get('visitor_team', {})
                
                all_new.append({
                    'id': str(gid),
                    'sport': 'nba',
                    'date': ds,
                    'season': g.get('season', 2024),
                    'homeTeam': ht.get('name', str(ht)) if isinstance(ht, dict) else str(ht),
                    'awayTeam': at.get('name', str(at)) if isinstance(at, dict) else str(at),
                    'scores': {'homeScore': home_score, 'awayScore': away_score},
                    'odds': {
                        'moneylineHome': best.get('moneyline_home_odds') if best else None,
                        'moneylineAway': best.get('moneyline_away_odds') if best else None,
                        'spreadHome': spread,
                        'spreadAway': -spread,
                        'totalLine': float(best.get('total_value', 0) or 0) if best else 0,
                        'source': 'balldontlie',
                        'vendor': best.get('vendor') if best else None
                    },
                    'result': {'winner': winner, 'spreadCovered': covered, 'margin': margin}
                })
            
            if all_new:
                print(f'  {ds}: +{len([g for g in games if g.get('status','').lower() in ('final','f')])} games')
        
        current += timedelta(days=1)
    
    added = merge_by_id(existing, all_new)
    print(f'Added {added} new NBA games')
    save_data(existing, 'nba')
    return added

def fetch_nfl_historical():
    print('\n' + '='*60)
    print('NFL HISTORICAL BACKFILL (2024-2025 Season)')
    print('='*60)
    
    existing = load_existing('nfl')
    print(f'Existing: {len(existing)} records')
    
    all_new = []
    for season in [2024, 2025]:
        for week in range(1, 19):
            data = api_get(f'https://api.balldontlie.io/nfl/v1/odds?season={season}&week={week}')
            odds = data.get('data', [])
            if odds:
                print(f'  Season {season} Week {week}: {len(odds)} odds')
                for o in odds:
                    all_new.append({
                        'id': str(o.get('id')),
                        'game_id': o.get('game_id'),
                        'sport': 'nfl',
                        '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'
                        }
                    })
    
    added = merge_by_id(existing, all_new)
    print(f'Added {added} new NFL odds')
    save_data(existing, 'nfl')
    return added

def fetch_nhl_historical():
    print('\n' + '='*60)
    print('NHL HISTORICAL BACKFILL (Oct 2025 - Now)')
    print('='*60)
    
    existing = load_existing('nhl')
    print(f'Existing: {len(existing)} records')
    
    all_new = []
    start = datetime(2025, 10, 1)
    end = datetime.now()
    current = start
    
    while current <= end:
        ds = current.strftime('%Y-%m-%d')
        
        data = api_get(f'https://api.balldontlie.io/nhl/v1/odds?dates[]={ds}')
        odds = data.get('data', [])
        
        if odds:
            print(f'  {ds}: {len(odds)} odds entries')
            for o in odds:
                all_new.append({
                    'id': str(o.get('id')),
                    'game_id': o.get('game_id'),
                    'sport': 'nhl',
                    'date': ds,
                    'vendor': o.get('vendor'),
                    'odds': {
                        'spreadHome': float(o.get('spread_home_value', 0) or 0),
                        'moneylineHome': o.get('moneyline_home_odds'),
                        'moneylineAway': o.get('moneyline_away_odds'),
                        'totalLine': float(o.get('total_value', 0) or 0),
                        'source': 'balldontlie'
                    }
                })
        
        current += timedelta(days=1)
    
    added = merge_by_id(existing, all_new)
    print(f'Added {added} new NHL odds')
    save_data(existing, 'nhl')
    return added

def fetch_ncaaf_historical():
    print('\n' + '='*60)
    print('NCAAF HISTORICAL BACKFILL (2024-2025 Season)')
    print('='*60)
    
    existing = load_existing('ncaaf')
    print(f'Existing: {len(existing)} records')
    
    all_new = []
    for season in [2024, 2025]:
        for week in range(1, 16):
            data = api_get(f'https://api.balldontlie.io/ncaaf/v1/odds?season={season}&week={week}')
            odds = data.get('data', [])
            if odds:
                print(f'  Season {season} Week {week}: {len(odds)} odds')
                for o in odds:
                    all_new.append({
                        'id': str(o.get('id')),
                        'game_id': o.get('game_id'),
                        'sport': 'ncaaf',
                        'season': season,
                        'week': week,
                        'vendor': o.get('vendor'),
                        'odds': {
                            'spreadHome': float(o.get('spread_home_value', 0) or 0),
                            'moneylineHome': o.get('moneyline_home_odds'),
                            'moneylineAway': o.get('moneyline_away_odds'),
                            'totalLine': float(o.get('total_value', 0) or 0),
                            'source': 'balldontlie'
                        }
                    })
    
    added = merge_by_id(existing, all_new)
    print(f'Added {added} new NCAAF odds')
    save_data(existing, 'ncaaf')
    return added

def main():
    print('='*60)
    print('BALLDONTLIE HISTORICAL ODDS BACKFILL')
    print('='*60)
    
    results = {}
    
    results['nba'] = fetch_nba_historical()
    results['nfl'] = fetch_nfl_historical()
    results['nhl'] = fetch_nhl_historical()
    results['ncaaf'] = fetch_ncaaf_historical()
    
    print('\n' + '='*60)
    print('BACKFILL COMPLETE')
    print('='*60)
    for sport, count in results.items():
        print(f'  {sport.upper()}: +{count} new records')
    print('='*60)

if __name__ == '__main__':
    main()
