#!/usr/bin/env python3
"""
SportsGameOdds API Comprehensive Fetcher
Fills data gaps for half-lines, live odds, player props, and multi-bookmaker comparison
Uses the full-access API key for complete coverage

API: https://sportsgameodds.com
Endpoints used:
  - GET /events - Event data with odds
  - GET /markets - Available markets
  - GET /account/usage - Quota tracking
"""

import os
import sys
import json
import argparse
import requests
from datetime import datetime, timezone
from typing import Dict, List, Optional, Any
import psycopg2
from psycopg2.extras import execute_values
from dotenv import load_dotenv

# Load environment
load_dotenv('/var/www/html/eventheodds/.env')

# API Configuration
API_KEY = os.getenv('SPORTSGAMEODDS_API_KEY', '47d6ce020d896ece307a284e8c78ff7f')
BASE_URL = os.getenv('SPORTSGAMEODDS_BASE_URL', 'https://api.sportsgameodds.com/v2')
HEADER_NAME = os.getenv('SPORTSGAMEODDS_HEADER', 'x-api-key')

# Database connection string
DB_URL = os.getenv('SPORTS_DATABASE_URL', 'postgresql://eventheodds:eventheodds_dev_password@127.0.0.1:5433/eventheodds_sports')

# League mappings
LEAGUE_IDS = {
    'nba': 'NBA',
    'nfl': 'NFL',
    'nhl': 'NHL',
    'mlb': 'MLB',
    'ncaab': 'NCAAB',
    'ncaaf': 'NCAAF',
    'epl': 'EPL',
    'ucl': 'UCL',
    'ufc': 'UFC',
}

# Period mappings for half/quarter data
PERIODS = {
    'game': 'Full Game',
    '1h': '1st Half',
    '2h': '2nd Half',
    '1q': '1st Quarter',
    '2q': '2nd Quarter',
    '3q': '3rd Quarter',
    '4q': '4th Quarter',
    '1p': '1st Period',
    '2p': '2nd Period',
    '3p': '3rd Period',
    'ot': 'Overtime',
}

class SportsGameOddsFetcher:
    """Client for SportsGameOdds API"""

    def __init__(self, api_key: str = API_KEY):
        self.api_key = api_key
        self.session = requests.Session()
        self.session.headers.update({HEADER_NAME: api_key})
        self.credits_used = 0
        self.credits_remaining = 0

    def _request(self, endpoint: str, params: Optional[Dict] = None) -> Dict:
        """Make API request with error handling"""
        url = f"{BASE_URL}/{endpoint}"
        try:
            resp = self.session.get(url, params=params, timeout=30)
            resp.raise_for_status()
            data = resp.json()

            # Track quota if available
            if 'creditsUsed' in data:
                self.credits_used = data.get('creditsUsed', 0)
            if 'creditsRemaining' in data:
                self.credits_remaining = data.get('creditsRemaining', 0)

            return data
        except requests.exceptions.RequestException as e:
            print(f"API Error: {e}")
            return {'success': False, 'data': [], 'error': str(e)}

    def get_events(self, league: str, limit: int = 50,
                   odds_available: bool = True,
                   started: Optional[bool] = None,
                   completed: Optional[bool] = None) -> List[Dict]:
        """Get events with odds for a league"""
        params = {
            'leagueID': LEAGUE_IDS.get(league.lower(), league.upper()),
            'limit': limit,
            'oddsAvailable': str(odds_available).lower(),
        }
        if started is not None:
            params['started'] = str(started).lower()
        if completed is not None:
            params['completed'] = str(completed).lower()

        data = self._request('events', params)
        return data.get('data', [])

    def get_live_events(self, league: str) -> List[Dict]:
        """Get currently live events"""
        return self.get_events(league, started=True, completed=False)

    def get_upcoming_events(self, league: str, limit: int = 20) -> List[Dict]:
        """Get upcoming events"""
        return self.get_events(league, limit=limit, started=False)

    def check_quota(self) -> Dict:
        """Check API quota usage"""
        data = self._request('account/usage')
        return {
            'used': data.get('creditsUsed', 0),
            'remaining': data.get('creditsRemaining', 0),
            'limit': data.get('creditsLimit', 0),
        }

    def parse_american_odds(self, odds_str: Optional[str]) -> Optional[int]:
        """Parse American odds string to integer"""
        if not odds_str:
            return None
        try:
            return int(odds_str.replace('+', ''))
        except (ValueError, TypeError):
            return None


def get_db_connection():
    """Get database connection"""
    # Remove schema parameter which psycopg2 doesn't support
    db_url = DB_URL.split('?')[0] if '?' in DB_URL else DB_URL
    return psycopg2.connect(db_url)


def ensure_tables_exist(conn):
    """Ensure required tables exist"""
    cur = conn.cursor()

    # Add externalEventId column to GameHalfLine if it doesn't exist
    cur.execute('''
        ALTER TABLE "GameHalfLine"
        ADD COLUMN IF NOT EXISTS "externalEventId" VARCHAR(100)
    ''')

    cur.execute('''
        ALTER TABLE "GameHalfLine"
        ADD COLUMN IF NOT EXISTS source VARCHAR(50) DEFAULT 'sportsgameodds'
    ''')

    cur.execute('''
        ALTER TABLE "GameHalfLine"
        ADD COLUMN IF NOT EXISTS "capturedAt" TIMESTAMP DEFAULT NOW()
    ''')

    # Index for external event lookups
    cur.execute('''
        CREATE INDEX IF NOT EXISTS "idx_gamehalfline_external"
        ON "GameHalfLine"(league, "externalEventId", period)
    ''')

    # BookmakerOddsSnapshot for multi-book comparison
    cur.execute('''
        CREATE TABLE IF NOT EXISTS "BookmakerOddsSnapshot" (
            id BIGSERIAL PRIMARY KEY,
            league VARCHAR(20),
            "externalEventId" VARCHAR(100),
            "gameDate" TIMESTAMP,
            "homeTeam" VARCHAR(100),
            "awayTeam" VARCHAR(100),
            bookmaker VARCHAR(50),
            "moneylineHome" INTEGER,
            "moneylineAway" INTEGER,
            "spreadHome" NUMERIC,
            "spreadHomeOdds" INTEGER,
            "spreadAway" NUMERIC,
            "spreadAwayOdds" INTEGER,
            total NUMERIC,
            "totalOverOdds" INTEGER,
            "totalUnderOdds" INTEGER,
            deeplink TEXT,
            "capturedAt" TIMESTAMP DEFAULT NOW(),
            "createdAt" TIMESTAMP DEFAULT NOW()
        )
    ''')

    cur.execute('''
        CREATE UNIQUE INDEX IF NOT EXISTS "BookmakerOddsSnapshot_unique_idx"
        ON "BookmakerOddsSnapshot"(league, "externalEventId", bookmaker, date_trunc('minute', "capturedAt"))
    ''')

    # LiveOddsSnapshot for in-game odds
    cur.execute('''
        CREATE TABLE IF NOT EXISTS "LiveOddsSnapshot" (
            id BIGSERIAL PRIMARY KEY,
            league VARCHAR(20),
            "externalEventId" VARCHAR(100),
            "gameDate" TIMESTAMP,
            "homeTeam" VARCHAR(100),
            "awayTeam" VARCHAR(100),
            "gameStatus" VARCHAR(50),
            "currentPeriod" VARCHAR(20),
            "homeScore" INTEGER,
            "awayScore" INTEGER,
            "moneylineHome" INTEGER,
            "moneylineAway" INTEGER,
            "spreadHome" NUMERIC,
            "spreadHomeOdds" INTEGER,
            total NUMERIC,
            "totalOverOdds" INTEGER,
            "fairMoneylineHome" INTEGER,
            "fairSpread" NUMERIC,
            "fairTotal" NUMERIC,
            bookmaker VARCHAR(50),
            "capturedAt" TIMESTAMP DEFAULT NOW(),
            "createdAt" TIMESTAMP DEFAULT NOW()
        )
    ''')

    cur.execute('''
        CREATE INDEX IF NOT EXISTS "idx_liveodds_lookup"
        ON "LiveOddsSnapshot"(league, "externalEventId", "capturedAt")
    ''')

    conn.commit()
    cur.close()


def fetch_half_lines(fetcher: SportsGameOddsFetcher, league: str, conn) -> int:
    """
    Fetch half-time and quarter lines
    Fills data gap Q4: Half spread efficiency analysis
    """
    print(f"\n{'='*60}")
    print(f"FETCHING HALF/QUARTER LINES - {league.upper()}")
    print(f"{'='*60}")

    events = fetcher.get_upcoming_events(league, limit=30)
    if not events:
        print("No events found")
        return 0

    cur = conn.cursor()
    stored = 0

    for event in events:
        event_id = event.get('eventID', '')
        home_team = event.get('teams', {}).get('home', {}).get('names', {}).get('long', '')
        away_team = event.get('teams', {}).get('away', {}).get('names', {}).get('long', '')
        starts_at = event.get('status', {}).get('startsAt', '')

        if not home_team or not away_team:
            continue

        game_date = datetime.fromisoformat(starts_at.replace('Z', '+00:00')) if starts_at else None

        odds = event.get('odds', {})

        # Extract half/quarter lines from odds
        half_lines = {}  # period -> {market -> {value, odds}}

        for odd_key, odd_data in odds.items():
            # Match period-specific team odds
            # Pattern: points-{side}-{period}-{betType}-{outcome}
            # Examples: points-home-1h-sp-home, points-all-1q-ou-over

            parts = odd_key.split('-')
            if len(parts) < 5:
                continue

            stat = parts[0]
            side = parts[1]  # home, away, all
            period = parts[2]  # game, 1h, 2h, 1q, etc.
            bet_type = parts[3]  # sp, ou, ml
            outcome = parts[4]  # home, away, over, under

            # Only process sub-game periods
            if period == 'game':
                continue
            if period not in ['1h', '2h', '1q', '2q', '3q', '4q', '1p', '2p', '3p']:
                continue

            if period not in half_lines:
                half_lines[period] = {}

            book_odds = fetcher.parse_american_odds(odd_data.get('bookOdds'))
            line_value = odd_data.get('bookOverUnder') or odd_data.get('fairOverUnder')

            if line_value:
                try:
                    line_value = float(line_value)
                except (ValueError, TypeError):
                    line_value = None

            # Store by market type
            if bet_type == 'sp' and side == 'home':
                half_lines[period]['spread'] = {'value': line_value, 'odds': book_odds}
            elif bet_type == 'ou' and side == 'all' and outcome == 'over':
                half_lines[period]['total'] = {'value': line_value, 'odds': book_odds}
            elif bet_type == 'ml' and side == 'home':
                half_lines[period]['moneyline_home'] = {'value': None, 'odds': book_odds}
            elif bet_type == 'ml' and side == 'away':
                half_lines[period]['moneyline_away'] = {'value': None, 'odds': book_odds}

        # Store half lines
        for period, markets in half_lines.items():
            for market, data in markets.items():
                if data.get('value') is None and data.get('odds') is None:
                    continue

                market_name = market.replace('_home', '').replace('_away', '')

                try:
                    cur.execute('''
                        INSERT INTO "GameHalfLine" (
                            league, "externalEventId", "gameDate", "homeTeam", "awayTeam",
                            period, market, "lineValue", "bookOdds", bookmaker, "capturedAt"
                        ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, date_trunc('minute', NOW()))
                        ON CONFLICT DO NOTHING
                    ''', (
                        league.upper(), event_id, game_date, home_team, away_team,
                        period, market_name, data.get('value'), data.get('odds'), 'consensus'
                    ))
                    stored += 1
                except Exception as e:
                    pass  # Continue on errors

        # Show what we found
        if half_lines:
            print(f"\n  {away_team[:25]} @ {home_team[:25]}")
            for period, markets in sorted(half_lines.items()):
                market_strs = []
                if 'spread' in markets:
                    v = markets['spread'].get('value')
                    o = markets['spread'].get('odds')
                    if v: market_strs.append(f"Spread: {v:+.1f}")
                if 'total' in markets:
                    v = markets['total'].get('value')
                    if v: market_strs.append(f"Total: {v:.1f}")
                if 'moneyline_home' in markets:
                    o = markets['moneyline_home'].get('odds')
                    if o: market_strs.append(f"ML: {o:+d}")
                if market_strs:
                    print(f"    {PERIODS.get(period, period):12} {' | '.join(market_strs)}")

    conn.commit()
    cur.close()

    print(f"\n{'='*60}")
    print(f"STORED: {stored} half/quarter line records")
    print(f"{'='*60}")

    return stored


def fetch_live_odds(fetcher: SportsGameOddsFetcher, league: str, conn) -> int:
    """
    Fetch live in-game odds
    Fills data gaps Q8, Q12: Live odds analysis
    """
    print(f"\n{'='*60}")
    print(f"FETCHING LIVE ODDS - {league.upper()}")
    print(f"{'='*60}")

    events = fetcher.get_live_events(league)
    if not events:
        print("No live events")
        return 0

    cur = conn.cursor()
    stored = 0

    for event in events:
        event_id = event.get('eventID', '')
        home_team = event.get('teams', {}).get('home', {}).get('names', {}).get('long', '')
        away_team = event.get('teams', {}).get('away', {}).get('names', {}).get('long', '')
        starts_at = event.get('status', {}).get('startsAt', '')

        status = event.get('status', {})
        game_status = status.get('displayLong', 'Live')
        current_period = status.get('currentPeriodID', '')

        # Get scores
        scores = event.get('scores', {})
        home_score = scores.get('home', {}).get('total')
        away_score = scores.get('away', {}).get('total')

        game_date = datetime.fromisoformat(starts_at.replace('Z', '+00:00')) if starts_at else None

        odds = event.get('odds', {})

        # Extract main game lines
        ml_home = odds.get('points-home-game-ml-home', {})
        ml_away = odds.get('points-away-game-ml-away', {})
        sp_home = odds.get('points-home-game-sp-home', {})
        total_over = odds.get('points-all-game-ou-over', {})

        moneyline_home = fetcher.parse_american_odds(ml_home.get('bookOdds'))
        moneyline_away = fetcher.parse_american_odds(ml_away.get('bookOdds'))

        spread_home = None
        spread_odds = None
        if sp_home.get('bookOverUnder'):
            try:
                spread_home = float(sp_home.get('bookOverUnder'))
                spread_odds = fetcher.parse_american_odds(sp_home.get('bookOdds'))
            except (ValueError, TypeError):
                pass

        total = None
        total_over_odds = None
        if total_over.get('bookOverUnder'):
            try:
                total = float(total_over.get('bookOverUnder'))
                total_over_odds = fetcher.parse_american_odds(total_over.get('bookOdds'))
            except (ValueError, TypeError):
                pass

        # Fair odds
        fair_ml_home = fetcher.parse_american_odds(ml_home.get('fairOdds'))
        fair_spread = None
        fair_total = None
        if sp_home.get('fairOverUnder'):
            try:
                fair_spread = float(sp_home.get('fairOverUnder'))
            except (ValueError, TypeError):
                pass
        if total_over.get('fairOverUnder'):
            try:
                fair_total = float(total_over.get('fairOverUnder'))
            except (ValueError, TypeError):
                pass

        print(f"\n  {away_team[:20]} ({away_score or 0}) @ {home_team[:20]} ({home_score or 0}) - {game_status}")
        print(f"    ML: {moneyline_home or '?'} / {moneyline_away or '?'}")
        print(f"    Spread: {spread_home or '?'} ({spread_odds or '?'})")
        print(f"    Total: {total or '?'} o{total_over_odds or '?'}")

        try:
            cur.execute('''
                INSERT INTO "LiveOddsSnapshot" (
                    league, "externalEventId", "gameDate", "homeTeam", "awayTeam",
                    "gameStatus", "currentPeriod", "homeScore", "awayScore",
                    "moneylineHome", "moneylineAway", "spreadHome", "spreadHomeOdds",
                    total, "totalOverOdds", "fairMoneylineHome", "fairSpread", "fairTotal",
                    bookmaker, "capturedAt"
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, date_trunc('minute', NOW()))
                ON CONFLICT DO NOTHING
            ''', (
                league.upper(), event_id, game_date, home_team, away_team,
                game_status, current_period, home_score, away_score,
                moneyline_home, moneyline_away, spread_home, spread_odds,
                total, total_over_odds, fair_ml_home, fair_spread, fair_total,
                'consensus'
            ))
            stored += 1
        except Exception as e:
            pass  # Ignore duplicate errors

    conn.commit()
    cur.close()

    print(f"\n{'='*60}")
    print(f"CAPTURED: {stored} live odds snapshots")
    print(f"{'='*60}")

    return stored


def fetch_bookmaker_comparison(fetcher: SportsGameOddsFetcher, league: str, conn) -> int:
    """
    Fetch odds from multiple bookmakers for comparison
    Fills data gaps Q16, Q18: Book efficiency and sharp detection
    """
    print(f"\n{'='*60}")
    print(f"FETCHING MULTI-BOOKMAKER ODDS - {league.upper()}")
    print(f"{'='*60}")

    events = fetcher.get_upcoming_events(league, limit=20)
    if not events:
        print("No events found")
        return 0

    cur = conn.cursor()
    stored = 0

    for event in events:
        event_id = event.get('eventID', '')
        home_team = event.get('teams', {}).get('home', {}).get('names', {}).get('long', '')
        away_team = event.get('teams', {}).get('away', {}).get('names', {}).get('long', '')
        starts_at = event.get('status', {}).get('startsAt', '')
        links = event.get('links', {}).get('bookmakers', {})

        game_date = datetime.fromisoformat(starts_at.replace('Z', '+00:00')) if starts_at else None

        odds = event.get('odds', {})

        # Collect all bookmaker data
        bookmaker_data = {}

        # Process each odds market
        for odd_key, odd_data in odds.items():
            by_bookmaker = odd_data.get('byBookmaker', {})
            if not by_bookmaker:
                continue

            for book, book_odd in by_bookmaker.items():
                if book not in bookmaker_data:
                    bookmaker_data[book] = {
                        'deeplink': links.get(book),
                    }

                bo = book_odd

                # Parse based on market type
                if 'game-ml-home' in odd_key:
                    bookmaker_data[book]['moneyline_home'] = fetcher.parse_american_odds(bo.get('odds'))
                elif 'game-ml-away' in odd_key:
                    bookmaker_data[book]['moneyline_away'] = fetcher.parse_american_odds(bo.get('odds'))
                elif 'game-sp-home' in odd_key:
                    try:
                        bookmaker_data[book]['spread_home'] = float(bo.get('overUnder') or 0)
                        bookmaker_data[book]['spread_home_odds'] = fetcher.parse_american_odds(bo.get('odds'))
                    except (ValueError, TypeError):
                        pass
                elif 'game-sp-away' in odd_key:
                    try:
                        bookmaker_data[book]['spread_away'] = float(bo.get('overUnder') or 0)
                        bookmaker_data[book]['spread_away_odds'] = fetcher.parse_american_odds(bo.get('odds'))
                    except (ValueError, TypeError):
                        pass
                elif 'game-ou-over' in odd_key and 'all' in odd_key:
                    try:
                        bookmaker_data[book]['total'] = float(bo.get('overUnder') or 0)
                        bookmaker_data[book]['total_over_odds'] = fetcher.parse_american_odds(bo.get('odds'))
                    except (ValueError, TypeError):
                        pass
                elif 'game-ou-under' in odd_key and 'all' in odd_key:
                    bookmaker_data[book]['total_under_odds'] = fetcher.parse_american_odds(bo.get('odds'))

        # Filter books with actual data
        active_books = {k: v for k, v in bookmaker_data.items()
                       if v.get('moneyline_home') or v.get('spread_home') or v.get('total')}

        if active_books:
            print(f"\n  {away_team[:25]} @ {home_team[:25]} ({len(active_books)} books)")

            # Show sample of books
            for book, data in list(active_books.items())[:5]:
                ml = data.get('moneyline_home', '?')
                sp = data.get('spread_home', '?')
                tot = data.get('total', '?')
                print(f"    {book:15} ML: {ml:>5} | Spread: {sp:>5} | Total: {tot}")
            if len(active_books) > 5:
                print(f"    ... and {len(active_books) - 5} more books")

        # Store each bookmaker's odds
        for book, data in active_books.items():
            try:
                cur.execute('''
                    INSERT INTO "BookmakerOddsSnapshot" (
                        league, "externalEventId", "gameDate", "homeTeam", "awayTeam",
                        bookmaker, "moneylineHome", "moneylineAway",
                        "spreadHome", "spreadHomeOdds", "spreadAway", "spreadAwayOdds",
                        total, "totalOverOdds", "totalUnderOdds", deeplink, "capturedAt"
                    ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, date_trunc('minute', NOW()))
                    ON CONFLICT DO NOTHING
                ''', (
                    league.upper(), event_id, game_date, home_team, away_team,
                    book, data.get('moneyline_home'), data.get('moneyline_away'),
                    data.get('spread_home'), data.get('spread_home_odds'),
                    data.get('spread_away'), data.get('spread_away_odds'),
                    data.get('total'), data.get('total_over_odds'), data.get('total_under_odds'),
                    data.get('deeplink')
                ))
                stored += 1
            except Exception as e:
                pass

    conn.commit()
    cur.close()

    print(f"\n{'='*60}")
    print(f"STORED: {stored} bookmaker odds records")
    print(f"{'='*60}")

    return stored


def fetch_player_props(fetcher: SportsGameOddsFetcher, league: str, conn) -> int:
    """
    Fetch player props with line movement tracking
    Fills data gap Q6: Prop softness timing
    """
    print(f"\n{'='*60}")
    print(f"FETCHING PLAYER PROPS - {league.upper()}")
    print(f"{'='*60}")

    events = fetcher.get_upcoming_events(league, limit=15)
    if not events:
        print("No events found")
        return 0

    cur = conn.cursor()
    stored = 0

    for event in events:
        event_id = event.get('eventID', '')
        home_team = event.get('teams', {}).get('home', {}).get('names', {}).get('long', '')
        away_team = event.get('teams', {}).get('away', {}).get('names', {}).get('long', '')
        starts_at = event.get('status', {}).get('startsAt', '')

        game_date = datetime.fromisoformat(starts_at.replace('Z', '+00:00')) if starts_at else None

        odds = event.get('odds', {})

        # Extract player props
        props = {}  # player_id -> {market -> {line, over_odds, under_odds}}

        for odd_key, odd_data in odds.items():
            # Pattern: {stat}-{PLAYER_ID}-{period}-{betType}-{side}
            # Example: points-LEBRON_JAMES_1_NBA-game-ou-over

            parts = odd_key.split('-')
            if len(parts) < 5:
                continue

            stat = parts[0]

            # Check if it's a player prop (player ID contains underscore and ends with league)
            if not any(parts[1].endswith(f'_{l}') for l in ['NBA', 'NFL', 'NHL', 'MLB']):
                continue

            player_id = parts[1]
            period = parts[2]
            bet_type = parts[3]
            side = parts[4]

            # Only process game-level props for now
            if period != 'game':
                continue
            if bet_type != 'ou':
                continue

            # Extract player name from ID
            player_name = player_id.replace('_1_NBA', '').replace('_1_NFL', '').replace('_1_NHL', '').replace('_1_MLB', '')
            player_name = player_name.replace('_', ' ').title()

            if player_id not in props:
                props[player_id] = {'name': player_name}

            line_value = odd_data.get('bookOverUnder') or odd_data.get('fairOverUnder')
            if line_value:
                try:
                    line_value = float(line_value)
                except (ValueError, TypeError):
                    line_value = None

            book_odds = fetcher.parse_american_odds(odd_data.get('bookOdds'))

            if stat not in props[player_id]:
                props[player_id][stat] = {}

            if side == 'over':
                props[player_id][stat]['line'] = line_value
                props[player_id][stat]['over_odds'] = book_odds
            elif side == 'under':
                props[player_id][stat]['under_odds'] = book_odds

        # Display and store props
        if props:
            print(f"\n  {away_team[:25]} @ {home_team[:25]}")

            for player_id, player_props in list(props.items())[:10]:
                player_name = player_props.get('name', player_id)
                prop_strs = []

                for stat in ['points', 'assists', 'rebounds', 'threePointersMade']:
                    if stat in player_props:
                        line = player_props[stat].get('line')
                        over = player_props[stat].get('over_odds')
                        if line:
                            stat_short = stat[:6].title()
                            over_str = f"o{over}" if over else ""
                            prop_strs.append(f"{stat_short} {line}{over_str}")

                        # Store in PropSnapshot
                        try:
                            cur.execute('''
                                INSERT INTO "PropSnapshot" (
                                    league, "theoddsapiEventId", "gameDate", "homeTeam", "awayTeam",
                                    bookmaker, "marketType", "playerName", "propLine",
                                    "overPrice", "underPrice", "capturedAt"
                                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, date_trunc('minute', NOW()))
                                ON CONFLICT DO NOTHING
                            ''', (
                                league.upper(), event_id, game_date, home_team, away_team,
                                'sportsgameodds', f'player_{stat}', player_name, line,
                                over, player_props[stat].get('under_odds')
                            ))
                            stored += 1
                        except Exception as e:
                            pass

                if prop_strs:
                    print(f"    {player_name[:25]:25} {' | '.join(prop_strs[:4])}")

    conn.commit()
    cur.close()

    print(f"\n{'='*60}")
    print(f"STORED: {stored} player prop records")
    print(f"{'='*60}")

    return stored


def show_quota(fetcher: SportsGameOddsFetcher):
    """Display API quota status"""
    quota = fetcher.check_quota()

    print(f"\n{'='*60}")
    print("SPORTSGAMEODDS API QUOTA")
    print(f"{'='*60}")
    print(f"Credits Used:      {quota.get('used', 0):,}")
    print(f"Credits Remaining: {quota.get('remaining', 0):,}")
    print(f"Credits Limit:     {quota.get('limit', 0):,}")
    print(f"{'='*60}")


def main():
    parser = argparse.ArgumentParser(description='SportsGameOdds Data Fetcher')
    parser.add_argument('command', choices=['half', 'live', 'books', 'props', 'all', 'quota'],
                       help='What to fetch: half (half-lines), live (in-game), books (multi-bookmaker), props (player props), all (everything), quota (check usage)')
    parser.add_argument('--league', '-l', default='nba',
                       help='League to fetch (nba, nfl, nhl, mlb, ncaab, ncaaf)')
    parser.add_argument('--leagues', '-L',
                       help='Comma-separated list of leagues')

    args = parser.parse_args()

    # Initialize
    fetcher = SportsGameOddsFetcher()

    if args.command == 'quota':
        show_quota(fetcher)
        return

    # Get leagues to process
    leagues = [args.league]
    if args.leagues:
        leagues = [l.strip().lower() for l in args.leagues.split(',')]

    # Connect to database
    conn = get_db_connection()
    ensure_tables_exist(conn)

    total_records = 0

    try:
        for league in leagues:
            if args.command == 'half':
                total_records += fetch_half_lines(fetcher, league, conn)
            elif args.command == 'live':
                total_records += fetch_live_odds(fetcher, league, conn)
            elif args.command == 'books':
                total_records += fetch_bookmaker_comparison(fetcher, league, conn)
            elif args.command == 'props':
                total_records += fetch_player_props(fetcher, league, conn)
            elif args.command == 'all':
                total_records += fetch_half_lines(fetcher, league, conn)
                total_records += fetch_bookmaker_comparison(fetcher, league, conn)
                total_records += fetch_player_props(fetcher, league, conn)
                # Live only if games are in progress
                live_records = fetch_live_odds(fetcher, league, conn)
                total_records += live_records

        # Show final quota
        show_quota(fetcher)

        print(f"\n{'='*60}")
        print(f"TOTAL RECORDS STORED: {total_records}")
        print(f"{'='*60}")

    finally:
        conn.close()


if __name__ == '__main__':
    main()
