#!/usr/bin/env python3
"""
Capture Live Game State from ESPN

This script fetches REAL live game data from ESPN's public scoreboard API
to track momentum, pace, and game state for in-play betting analysis.

Endpoints used:
- NBA: https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard
- NFL: https://site.api.espn.com/apis/site/v2/sports/football/nfl/scoreboard
- NHL: https://site.api.espn.com/apis/site/v2/sports/hockey/nhl/scoreboard

Run: Every 5 minutes during game hours
Cron: */5 * * * * python3 /var/www/html/eventheodds/scripts/capture_live_game_state.py
"""
import psycopg2
import requests
import json
from datetime import datetime, timezone, timedelta

ESPN_SCOREBOARD_URLS = {
    'nba': 'https://site.api.espn.com/apis/site/v2/sports/basketball/nba/scoreboard',
    'nfl': 'https://site.api.espn.com/apis/site/v2/sports/football/nfl/scoreboard',
    'nhl': 'https://site.api.espn.com/apis/site/v2/sports/hockey/nhl/scoreboard',
    'mlb': 'https://site.api.espn.com/apis/site/v2/sports/baseball/mlb/scoreboard',
    'ncaab': 'https://site.api.espn.com/apis/site/v2/sports/basketball/mens-college-basketball/scoreboard',
}

# Expected pace ranges by league
PACE_RANGES = {
    'nba': {'min': 95, 'max': 115, 'avg': 100},
    'nfl': {'min': 50, 'max': 75, 'avg': 62},
    'nhl': {'min': 50, 'max': 65, 'avg': 55},
    'mlb': {'min': 8, 'max': 12, 'avg': 9},
    'ncaab': {'min': 60, 'max': 80, 'avg': 70},
}


def load_db_url():
    with open('/var/www/html/eventheodds/.env', 'r') as f:
        for line in f:
            if line.startswith('SPORTS_DATABASE_URL='):
                return line.split('=', 1)[1].strip().split('?')[0]
    return ''


def fetch_espn_scoreboard(league):
    """Fetch live scoreboard data from ESPN"""
    url = ESPN_SCOREBOARD_URLS.get(league)
    if not url:
        return None

    try:
        resp = requests.get(url, timeout=15)
        if resp.status_code == 200:
            return resp.json()
    except Exception as e:
        print(f"  Error fetching {league} scoreboard: {e}")

    return None


def parse_clock(clock_str):
    """Parse ESPN clock string to seconds remaining"""
    if not clock_str:
        return None

    try:
        if ':' in clock_str:
            parts = clock_str.split(':')
            if len(parts) == 2:
                minutes, seconds = parts
                return int(minutes) * 60 + float(seconds.split('.')[0])
        return float(clock_str)
    except:
        return None


def calculate_pace(home_score, away_score, period, time_remaining, league):
    """Calculate current pace based on scoring and time elapsed"""
    if home_score is None or away_score is None:
        return None

    total_score = home_score + away_score

    # Calculate elapsed time based on league
    if league == 'nba':
        period_length = 12 * 60  # 12 minutes
        total_time = 48 * 60
    elif league == 'nfl':
        period_length = 15 * 60
        total_time = 60 * 60
    elif league == 'nhl':
        period_length = 20 * 60
        total_time = 60 * 60
    elif league == 'ncaab':
        period_length = 20 * 60
        total_time = 40 * 60
    else:
        return None

    time_remaining_sec = time_remaining or 0
    elapsed_in_period = period_length - time_remaining_sec
    total_elapsed = ((period - 1) * period_length) + elapsed_in_period

    if total_elapsed <= 0:
        return None

    # Project pace to full game
    if league in ['nba', 'ncaab']:
        # Possessions per 48 minutes (NBA style)
        pace = (total_score / total_elapsed) * total_time
    elif league == 'nfl':
        # Points per game
        pace = (total_score / total_elapsed) * total_time
    elif league == 'nhl':
        # Goals per game
        pace = (total_score / total_elapsed) * total_time
    else:
        pace = total_score

    return round(pace, 1)


def calculate_momentum(home_score, away_score, period, league, last_play=None):
    """Calculate momentum score based on recent scoring"""
    if home_score is None or away_score is None:
        return 'NEUTRAL', 0

    diff = home_score - away_score

    # Simple momentum based on current margin and period
    if abs(diff) <= 5 and period >= 3:
        # Close late game
        return 'TIGHT', 0
    elif diff >= 15:
        return 'HOME_DOMINANT', diff
    elif diff <= -15:
        return 'AWAY_DOMINANT', diff
    elif diff >= 8:
        return 'HOME_CONTROL', diff
    elif diff <= -8:
        return 'AWAY_CONTROL', diff
    elif diff > 0:
        return 'HOME_SLIGHT', diff
    elif diff < 0:
        return 'AWAY_SLIGHT', diff
    else:
        return 'NEUTRAL', 0


def capture_live_games():
    """Capture live game state from ESPN for all leagues"""
    db_url = load_db_url()
    if not db_url:
        raise RuntimeError('SPORTS_DATABASE_URL not set')

    conn = psycopg2.connect(db_url)
    cur = conn.cursor()

    now = datetime.now(timezone.utc)
    print("=" * 80)
    print("CAPTURING LIVE GAME STATE FROM ESPN")
    print(f"Time: {now.isoformat()}")
    print("=" * 80)

    total_captured = 0
    total_live = 0

    for league, url in ESPN_SCOREBOARD_URLS.items():
        data = fetch_espn_scoreboard(league)
        if not data:
            print(f"\n{league.upper()}: No data available")
            continue

        events = data.get('events', [])
        live_games = [e for e in events if e.get('status', {}).get('type', {}).get('state') == 'in']

        print(f"\n{league.upper()}: {len(live_games)} live games (of {len(events)} total)")

        for event in live_games:
            total_live += 1

            event_id = event.get('id')
            status = event.get('status', {})
            competition = event.get('competitions', [{}])[0]

            # Extract teams and scores
            competitors = competition.get('competitors', [])
            home_team = None
            away_team = None
            home_score = None
            away_score = None

            for comp in competitors:
                if comp.get('homeAway') == 'home':
                    home_team = comp.get('team', {}).get('abbreviation', comp.get('team', {}).get('name', ''))
                    home_score = int(comp.get('score', 0) or 0)
                else:
                    away_team = comp.get('team', {}).get('abbreviation', comp.get('team', {}).get('name', ''))
                    away_score = int(comp.get('score', 0) or 0)

            # Game time info
            period = status.get('period', 1)
            clock_str = status.get('displayClock', '')
            time_remaining = parse_clock(clock_str)

            # Calculate metrics
            pace = calculate_pace(home_score, away_score, period, time_remaining, league)
            momentum, momentum_score = calculate_momentum(home_score, away_score, period, league)

            # Score differential
            score_diff = (home_score - away_score) if home_score and away_score else 0

            # Get game date
            game_date = None
            date_str = event.get('date')
            if date_str:
                try:
                    game_date = datetime.fromisoformat(date_str.replace('Z', '+00:00')).date()
                except:
                    game_date = now.date()

            # Get situation details (foul trouble, timeouts, etc.)
            situation = competition.get('situation', {})
            timeouts = {}
            for comp in competitors:
                team = comp.get('team', {}).get('abbreviation', '')
                stats = comp.get('statistics', [])
                for stat in stats:
                    if stat.get('name') == 'timeoutsRemaining':
                        timeouts[team] = stat.get('displayValue')

            # Insert into LiveGameState
            try:
                cur.execute('''
                    INSERT INTO "LiveGameState" (
                        "gameExternalId", league, "gameDate", "period", "timeRemaining",
                        "homeScore", "awayScore", "scoreDifferential",
                        "pace", "momentum", "momentumScore",
                        "timeoutsRemaining", "recordedAt"
                    ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW())
                    ON CONFLICT ("gameExternalId", "recordedAt")
                    DO UPDATE SET
                        "period" = EXCLUDED."period",
                        "timeRemaining" = EXCLUDED."timeRemaining",
                        "homeScore" = EXCLUDED."homeScore",
                        "awayScore" = EXCLUDED."awayScore",
                        "scoreDifferential" = EXCLUDED."scoreDifferential",
                        "pace" = EXCLUDED."pace",
                        "momentum" = EXCLUDED."momentum",
                        "momentumScore" = EXCLUDED."momentumScore"
                ''', (
                    f"espn_{event_id}", league, game_date, period, clock_str,
                    home_score, away_score, score_diff,
                    pace, momentum, momentum_score,
                    json.dumps(timeouts) if timeouts else None
                ))
                total_captured += 1

                print(f"  {away_team} @ {home_team}: {away_score}-{home_score} (P{period} {clock_str}) "
                      f"Pace: {pace} Momentum: {momentum}")

            except Exception as e:
                print(f"  Error capturing {event_id}: {e}")

    conn.commit()

    # Summary stats
    cur.execute('''
        SELECT
            league,
            COUNT(*) as total,
            COUNT(*) FILTER (WHERE "recordedAt" > NOW() - INTERVAL '1 hour') as recent
        FROM "LiveGameState"
        GROUP BY league
        ORDER BY league
    ''')

    print("\n" + "=" * 80)
    print("LIVE GAME STATE SUMMARY")
    print("=" * 80)
    print(f"{'League':<10} {'Total Records':<15} {'Last Hour':<12}")
    print("-" * 40)

    for row in cur.fetchall():
        league, total, recent = row
        print(f"{league.upper():<10} {total:<15} {recent:<12}")

    cur.execute('SELECT COUNT(*) FROM "LiveGameState"')
    total_records = cur.fetchone()[0]

    print("\n" + "=" * 80)
    print("RESULTS")
    print("=" * 80)
    print(f"  Live games found: {total_live}")
    print(f"  States captured: {total_captured}")
    print(f"  Total LiveGameState records: {total_records}")
    print(f"  Source: REAL (ESPN Scoreboard API)")
    print("=" * 80)

    cur.close()
    conn.close()

    return {
        'live_games': total_live,
        'captured': total_captured,
        'total_records': total_records
    }


def main():
    try:
        result = capture_live_games()
        if result['live_games'] == 0:
            print("\n  No live games currently - this is normal outside of game hours")
        else:
            print(f"\n  Captured {result['captured']} live game states")
    except Exception as e:
        print(f"ERROR: {e}")
        import traceback
        traceback.print_exc()


if __name__ == '__main__':
    main()
