#!/usr/bin/env python3
"""
Track NBA Lineup Changes
Monitors lineup changes and calculates timing relative to tip-off.
Unlocks: Q1 (late lineup changes vs spread performance)

Run: Every 30 minutes during game hours
"""
import psycopg2
import requests
import os
import json
from datetime import datetime, timezone, timedelta

HEADERS = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'}
ESPN_BASE = 'https://site.api.espn.com/apis/site/v2/sports/basketball/nba'

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


def fetch_current_lineups():
    """Fetch current NBA lineups from ESPN"""
    url = f'{ESPN_BASE}/scoreboard'
    lineups = []

    try:
        resp = requests.get(url, headers=HEADERS, timeout=15)
        if resp.status_code != 200:
            return lineups

        data = resp.json()

        for event in data.get('events', []):
            event_id = event.get('id')
            game_date = event.get('date')
            competition = event.get('competitions', [{}])[0]

            for competitor in competition.get('competitors', []):
                team_abbr = competitor.get('team', {}).get('abbreviation')
                is_home = competitor.get('homeAway') == 'home'

                # Get lineup/roster info
                lineup_url = f'{ESPN_BASE}/summary?event={event_id}'
                try:
                    lineup_resp = requests.get(lineup_url, headers=HEADERS, timeout=15)
                    if lineup_resp.status_code == 200:
                        lineup_data = lineup_resp.json()

                        # Extract starters from boxscore
                        boxscore = lineup_data.get('boxscore', {})
                        for team in boxscore.get('players', []):
                            if team.get('team', {}).get('abbreviation') == team_abbr:
                                starters = []
                                for player in team.get('statistics', [{}])[0].get('athletes', []):
                                    if player.get('starter'):
                                        starters.append({
                                            'id': player.get('athlete', {}).get('id'),
                                            'name': player.get('athlete', {}).get('displayName'),
                                            'position': player.get('athlete', {}).get('position', {}).get('abbreviation')
                                        })

                                if starters:
                                    lineups.append({
                                        'event_id': event_id,
                                        'game_date': game_date,
                                        'team': team_abbr,
                                        'is_home': is_home,
                                        'starters': starters
                                    })
                except Exception as e:
                    continue

    except Exception as e:
        print(f"Error fetching lineups: {e}")

    return lineups


def detect_changes(cur, lineup_data):
    """Compare current lineup with previous and detect changes"""
    event_id = lineup_data['event_id']
    team = lineup_data['team']

    # Get previous lineup
    cur.execute('''
        SELECT id, starters, "createdAt"
        FROM "NBALineup"
        WHERE "espnEventId" = %s AND team = %s
        ORDER BY "createdAt" DESC
        LIMIT 1
    ''', (event_id, team))

    previous = cur.fetchone()

    if not previous:
        return None, 'new'

    prev_id, prev_starters, prev_time = previous
    current_starters = lineup_data['starters']

    # Compare starters
    if not prev_starters:
        return prev_id, 'new'

    prev_ids = set(s.get('id') for s in prev_starters if s.get('id'))
    curr_ids = set(s.get('id') for s in current_starters if s.get('id'))

    if prev_ids == curr_ids:
        return prev_id, 'no_change'

    # Determine change type
    scratched = prev_ids - curr_ids
    added = curr_ids - prev_ids

    if scratched and added:
        return prev_id, 'substitution'
    elif scratched:
        return prev_id, 'scratch'
    elif added:
        return prev_id, 'addition'
    else:
        return prev_id, 'reorder'


def main():
    print("=" * 60)
    print("TRACK LINEUP CHANGES")
    print(f"Time: {datetime.now(timezone.utc).isoformat()}")
    print("=" * 60)

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

    now = datetime.now(timezone.utc)

    # Fetch current lineups
    print("\nFetching current lineups...")
    lineups = fetch_current_lineups()
    print(f"Found {len(lineups)} team lineups")

    new_lineups = 0
    changes_detected = 0
    late_changes = 0

    for lineup in lineups:
        game_date_str = lineup.get('game_date')
        if game_date_str:
            try:
                game_date = datetime.fromisoformat(game_date_str.replace('Z', '+00:00'))
                minutes_to_tip = int((game_date - now).total_seconds() / 60)
            except:
                minutes_to_tip = None
        else:
            minutes_to_tip = None

        prev_id, change_type = detect_changes(cur, lineup)

        is_late = minutes_to_tip is not None and minutes_to_tip <= 60

        if change_type == 'new':
            # Insert new lineup
            cur.execute('''
                INSERT INTO "NBALineup"
                ("espnEventId", "gameId", "gameDate", team, "isHome", starters,
                 "minutesToTip", "isLateChange", "createdAt")
                VALUES (%s, NULL, %s, %s, %s, %s, %s, %s, NOW())
            ''', (
                lineup['event_id'],
                lineup['game_date'],
                lineup['team'],
                lineup['is_home'],
                json.dumps(lineup['starters']),
                minutes_to_tip,
                False
            ))
            new_lineups += 1

        elif change_type not in ('no_change',):
            # Update with change info
            cur.execute('''
                UPDATE "NBALineup"
                SET "previousLineup" = starters,
                    starters = %s,
                    "changedAt" = NOW(),
                    "changeType" = %s,
                    "minutesToTip" = %s,
                    "isLateChange" = %s,
                    "updatedAt" = NOW()
                WHERE id = %s
            ''', (
                json.dumps(lineup['starters']),
                change_type,
                minutes_to_tip,
                is_late,
                prev_id
            ))
            changes_detected += 1
            if is_late:
                late_changes += 1
                print(f"  LATE CHANGE: {lineup['team']} - {change_type} ({minutes_to_tip} min to tip)")

    conn.commit()

    # Summary
    print(f"\nNew lineups: {new_lineups}")
    print(f"Changes detected: {changes_detected}")
    print(f"Late changes (≤60 min): {late_changes}")

    # Report late changes history
    cur.execute('''
        SELECT team, "changeType", "minutesToTip", "changedAt"
        FROM "NBALineup"
        WHERE "isLateChange" = true
        ORDER BY "changedAt" DESC
        LIMIT 10
    ''')
    late = cur.fetchall()
    if late:
        print("\nRecent late changes:")
        for row in late:
            print(f"  {row[0]}: {row[1]} ({row[2]} min before tip) at {row[3]}")

    cur.close()
    conn.close()

    print("\n" + "=" * 60)
    print("Lineup tracking complete")
    print("=" * 60)


if __name__ == '__main__':
    main()
