#!/usr/bin/env python3
"""
The Odds API Extended Markets Fetcher

Handles sport-level market fetches that don't fit the per-event prop model:
- Period markets (quarters, halves, periods)
- Team totals and alternate team totals
- Soccer specials (BTTS, draw no bet, double chance, 3-way)
- Alternate totals

Usage:
    python theoddsapi_extended_markets.py --periods          # Period markets (Q1-Q4, H1-H2, P1-P3)
    python theoddsapi_extended_markets.py --team-totals      # Team totals & alt team totals
    python theoddsapi_extended_markets.py --soccer           # Soccer specials (BTTS, DNB, DC, 3-way)
    python theoddsapi_extended_markets.py --alt-totals       # Alternate totals
    python theoddsapi_extended_markets.py --all              # All of the above
    python theoddsapi_extended_markets.py --dry-run --all    # Preview without writing
"""
import argparse
import requests
import psycopg2
import json
import os
import sys
import time
from datetime import datetime, timezone, timedelta
from typing import Optional, Dict, List, Tuple

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from team_names import normalize_to_full

# Add lib directory to path
sys.path.insert(0, os.path.dirname(__file__))
try:
    from lib.unified_odds_ingestion import (
        log_ingestion_start, log_ingestion_complete,
        upsert_bookmaker_odds, get_or_create_sports_game,
    )
    UNIFIED_AVAILABLE = True
except ImportError:
    UNIFIED_AVAILABLE = False
    print("Warning: unified_odds_ingestion not available")

BASE_URL = 'https://api.the-odds-api.com/v4'

# Sport keys for The Odds API
SPORT_KEYS = {
    'nba': 'basketball_nba',
    'nfl': 'americanfootball_nfl',
    'nhl': 'icehockey_nhl',
    'mlb': 'baseball_mlb',
    'ncaab': 'basketball_ncaab',
    'ncaaf': 'americanfootball_ncaaf',
    'epl': 'soccer_epl',
    'bundesliga': 'soccer_germany_bundesliga',
    'seriea': 'soccer_italy_serie_a',
    'laliga': 'soccer_spain_la_liga',
    'ligue1': 'soccer_france_ligue_one',
    'ucl': 'soccer_uefa_champs_league',
    'mls': 'soccer_usa_mls',
}

# Period market definitions per sport
PERIOD_MARKETS = {
    'nba': {
        'quarters': ['h2h_q1', 'spreads_q1', 'totals_q1', 'h2h_q2', 'spreads_q2', 'totals_q2',
                     'h2h_q3', 'spreads_q3', 'totals_q3', 'h2h_q4', 'spreads_q4', 'totals_q4'],
        'halves': ['h2h_h1', 'spreads_h1', 'totals_h1', 'h2h_h2', 'spreads_h2', 'totals_h2'],
    },
    'nfl': {
        'quarters': ['h2h_q1', 'spreads_q1', 'totals_q1'],
        'halves': ['h2h_h1', 'spreads_h1', 'totals_h1', 'h2h_h2', 'spreads_h2', 'totals_h2'],
    },
    'nhl': {
        'periods': ['h2h_p1', 'spreads_p1', 'totals_p1', 'h2h_p2', 'spreads_p2', 'totals_p2',
                    'h2h_p3', 'spreads_p3', 'totals_p3'],
    },
    'mlb': {
        'innings': ['h2h_1st_1_innings', 'spreads_1st_1_innings', 'totals_1st_1_innings',
                    'h2h_1st_3_innings', 'spreads_1st_3_innings', 'totals_1st_3_innings',
                    'h2h_1st_5_innings', 'spreads_1st_5_innings', 'totals_1st_5_innings',
                    'h2h_1st_7_innings', 'spreads_1st_7_innings', 'totals_1st_7_innings'],
    },
}

# Soccer special markets
SOCCER_MARKETS = ['btts', 'draw_no_bet', 'double_chance', 'h2h_3_way']

# Sports that support team totals
TEAM_TOTAL_SPORTS = ['nba', 'nfl', 'nhl', 'mlb']

# Sports that support alternate totals
ALT_TOTAL_SPORTS = ['nba', 'nfl', 'nhl', 'mlb', 'ncaab', 'ncaaf']

# Soccer leagues
SOCCER_LEAGUES = ['epl', 'bundesliga', 'seriea', 'laliga', 'ligue1', 'ucl', 'mls']


def load_config() -> Tuple[str, str]:
    """Load database URL and API key from .env"""
    env_path = '/var/www/html/eventheodds/.env'
    db_url = None
    api_key = None

    try:
        with open(env_path, 'r') as f:
            for line in f:
                if line.startswith('SPORTS_DATABASE_URL='):
                    db_url = line.split('=', 1)[1].strip().strip('"').split('?')[0]
                elif line.startswith('THE_ODDS_API_KEY='):
                    api_key = line.split('=', 1)[1].strip().strip('"')
    except FileNotFoundError:
        pass

    db_url = db_url or os.environ.get('SPORTS_DATABASE_URL', '').split('?')[0]
    api_key = api_key or os.environ.get('THE_ODDS_API_KEY')

    return db_url, api_key


class ExtendedMarketsFetcher:
    def __init__(self, api_key: str, db_url: str, dry_run: bool = False):
        self.api_key = api_key
        self.db_url = db_url
        self.dry_run = dry_run
        self.session = requests.Session()
        self.quota_used = 0
        self.quota_remaining = None

    def _request(self, endpoint: str, params: dict = None) -> Optional[dict]:
        """Make API request and track quota"""
        if params is None:
            params = {}
        params['apiKey'] = self.api_key

        url = f"{BASE_URL}{endpoint}"

        try:
            resp = self.session.get(url, params=params, timeout=30)
            self.quota_used = int(resp.headers.get('x-requests-used', 0))
            self.quota_remaining = int(resp.headers.get('x-requests-remaining', 0))

            if resp.status_code == 401:
                print(f"ERROR: Invalid API key")
                return None
            if resp.status_code == 422:
                return None  # No data available
            if resp.status_code == 429:
                print(f"ERROR: Quota exceeded")
                return None
            if resp.status_code != 200:
                print(f"ERROR: API returned {resp.status_code} for {endpoint}")
                return None

            return resp.json()

        except Exception as e:
            print(f"ERROR: Request failed: {e}")
            return None

    def get_odds_with_markets(self, sport_key: str, markets: List[str],
                               regions: str = 'us') -> List[dict]:
        """Get odds for specific markets"""
        params = {
            'regions': regions,
            'markets': ','.join(markets),
            'oddsFormat': 'american'
        }
        result = self._request(f'/sports/{sport_key}/odds', params)
        return result or []

    def get_event_odds(self, sport_key: str, event_id: str,
                       markets: List[str], regions: str = 'us') -> Optional[dict]:
        """Get event-level odds for specific markets"""
        params = {
            'regions': regions,
            'markets': ','.join(markets),
            'oddsFormat': 'american'
        }
        return self._request(f'/sports/{sport_key}/events/{event_id}/odds', params)


def ensure_tables(conn):
    """Ensure required tables exist.

    Existing tables (PeriodOdds, GameOddsAltLine, GameOdds) already have schemas.
    Only create PropSnapshot if it doesn't exist yet.
    """
    cur = conn.cursor()

    # PropSnapshot — may not exist yet
    cur.execute('''
        CREATE TABLE IF NOT EXISTS "PropSnapshot" (
            id SERIAL PRIMARY KEY,
            league VARCHAR(20),
            "theoddsapiEventId" VARCHAR(100),
            "gameDate" TIMESTAMP,
            "homeTeam" VARCHAR(100),
            "awayTeam" VARCHAR(100),
            bookmaker VARCHAR(50),
            "marketType" VARCHAR(50),
            "playerName" VARCHAR(100),
            "propLine" DOUBLE PRECISION,
            "overPrice" INTEGER,
            "underPrice" INTEGER,
            "capturedAt" TIMESTAMP DEFAULT NOW(),
            source VARCHAR(50) DEFAULT 'theoddsapi',
            "createdAt" TIMESTAMP DEFAULT NOW()
        )
    ''')
    cur.execute('''
        CREATE INDEX IF NOT EXISTS idx_prop_snapshot_event
        ON "PropSnapshot"(league, "theoddsapiEventId", "playerName", "capturedAt")
    ''')

    # Add bookmaker column to PeriodOdds if missing (existing table may not have it)
    cur.execute("""
        SELECT column_name FROM information_schema.columns
        WHERE table_name = 'PeriodOdds' AND column_name = 'bookmaker'
    """)
    if not cur.fetchone():
        try:
            cur.execute('ALTER TABLE "PeriodOdds" ADD COLUMN bookmaker TEXT')
        except:
            conn.rollback()

    # Add source column to PeriodOdds if missing
    cur.execute("""
        SELECT column_name FROM information_schema.columns
        WHERE table_name = 'PeriodOdds' AND column_name = 'source'
    """)
    if not cur.fetchone():
        try:
            cur.execute("ALTER TABLE \"PeriodOdds\" ADD COLUMN source TEXT DEFAULT 'theoddsapi'")
        except:
            conn.rollback()

    conn.commit()
    cur.close()


def parse_period_market_key(market_key: str) -> Tuple[str, str]:
    """Parse a period market key like 'h2h_q1' into (market_type, period).

    Returns: (market_type, period) e.g. ('h2h', 'q1')
    """
    # Handle patterns like h2h_q1, spreads_h1, totals_p2, h2h_1st_5_innings
    if '_1st_' in market_key:
        # MLB innings: h2h_1st_5_innings -> (h2h, 1st_5_innings)
        parts = market_key.split('_', 1)
        return parts[0], parts[1]

    parts = market_key.rsplit('_', 1)
    if len(parts) == 2:
        return parts[0], parts[1]
    return market_key, 'full'


def fetch_period_markets(fetcher: ExtendedMarketsFetcher, conn, leagues: List[str],
                         dry_run: bool = False):
    """Fetch period markets (quarters, halves, periods) for specified leagues"""
    cur = conn.cursor()
    total = 0

    print(f"\n{'='*60}")
    print("FETCHING PERIOD MARKETS")
    print(f"Time: {datetime.now(timezone.utc).isoformat()}")
    print(f"{'='*60}")

    for league in leagues:
        sport_key = SPORT_KEYS.get(league)
        period_config = PERIOD_MARKETS.get(league)
        if not sport_key or not period_config:
            continue

        # Flatten all period market keys for this sport
        all_markets = []
        for group_markets in period_config.values():
            all_markets.extend(group_markets)

        if not all_markets:
            continue

        # Fetch in batches of 8 markets (API limit)
        for batch_start in range(0, len(all_markets), 8):
            batch = all_markets[batch_start:batch_start + 8]
            print(f"  {league.upper()}: Fetching {','.join(batch[:3])}... ({len(batch)} markets)")

            events = fetcher.get_odds_with_markets(sport_key, batch)
            if not events:
                continue

            for event in events:
                event_id = event.get('id')
                home = normalize_to_full(event.get('home_team', ''), league)
                away = normalize_to_full(event.get('away_team', ''), league)
                commence = event.get('commence_time')

                commence_dt = None
                if commence:
                    try:
                        commence_dt = datetime.fromisoformat(commence.replace('Z', '+00:00'))
                    except:
                        pass

                for book in event.get('bookmakers', []):
                    book_name = book.get('key', 'unknown')

                    for market in book.get('markets', []):
                        market_key = market.get('key', '')
                        market_type, period = parse_period_market_key(market_key)
                        outcomes = market.get('outcomes', [])

                        home_odds = away_odds = draw_odds = None
                        line_value = None

                        for o in outcomes:
                            name = o.get('name', '')
                            if name == home or name == 'Over':
                                home_odds = o.get('price')
                                if o.get('point') is not None:
                                    line_value = o.get('point')
                            elif name == away or name == 'Under':
                                away_odds = o.get('price')
                            elif name == 'Draw':
                                draw_odds = o.get('price')

                        if home_odds is None and away_odds is None:
                            continue

                        if dry_run:
                            print(f"    [DRY] {home} vs {away} | {period} {market_type} | "
                                  f"{book_name}: {home_odds}/{away_odds} line={line_value}")
                            total += 1
                            continue

                        # PeriodOdds schema: spread/total/moneyline columns per period
                        # Map market_type to the right columns
                        sp_home = sp_away = tot_val = ml_home = ml_away = None
                        if market_type in ('spreads', 'spread'):
                            sp_home = line_value
                            sp_away = -line_value if line_value is not None else None
                        elif market_type in ('totals', 'total'):
                            tot_val = line_value
                        elif market_type in ('h2h', 'moneyline'):
                            ml_home = home_odds
                            ml_away = away_odds

                        cur.execute('''
                            INSERT INTO "PeriodOdds" (
                                league, "gameId", "gameDate", "homeTeam", "awayTeam",
                                period, "spreadHome", "spreadAway", total,
                                "moneylineHome", "moneylineAway",
                                "snapshotType", "snapshotAt", bookmaker, source
                            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'live', NOW(), %s, 'theoddsapi')
                            ON CONFLICT ("league", "gameId", "period", "snapshotType")
                            DO UPDATE SET
                                "spreadHome" = COALESCE(EXCLUDED."spreadHome", "PeriodOdds"."spreadHome"),
                                "spreadAway" = COALESCE(EXCLUDED."spreadAway", "PeriodOdds"."spreadAway"),
                                total = COALESCE(EXCLUDED.total, "PeriodOdds".total),
                                "moneylineHome" = COALESCE(EXCLUDED."moneylineHome", "PeriodOdds"."moneylineHome"),
                                "moneylineAway" = COALESCE(EXCLUDED."moneylineAway", "PeriodOdds"."moneylineAway"),
                                "snapshotAt" = NOW()
                        ''', (
                            league, event_id, commence_dt, home, away,
                            period, sp_home, sp_away, tot_val,
                            ml_home, ml_away, book_name
                        ))
                        total += 1

            time.sleep(1)  # Rate limiting

    if not dry_run:
        conn.commit()
    cur.close()

    print(f"\n  Period markets captured: {total}")
    print(f"  Quota remaining: {fetcher.quota_remaining}")
    return total


def fetch_team_totals(fetcher: ExtendedMarketsFetcher, conn, leagues: List[str],
                      dry_run: bool = False):
    """Fetch team totals and alternate team totals"""
    cur = conn.cursor()
    total = 0

    print(f"\n{'='*60}")
    print("FETCHING TEAM TOTALS")
    print(f"Time: {datetime.now(timezone.utc).isoformat()}")
    print(f"{'='*60}")

    for league in leagues:
        if league not in TEAM_TOTAL_SPORTS:
            continue
        sport_key = SPORT_KEYS.get(league)
        if not sport_key:
            continue

        markets = ['team_totals', 'alternate_team_totals']
        print(f"  {league.upper()}: Fetching team totals")

        events = fetcher.get_odds_with_markets(sport_key, markets)
        if not events:
            continue

        for event in events:
            event_id = event.get('id')
            home = normalize_to_full(event.get('home_team', ''), league)
            away = normalize_to_full(event.get('away_team', ''), league)
            commence = event.get('commence_time')

            commence_dt = None
            if commence:
                try:
                    commence_dt = datetime.fromisoformat(commence.replace('Z', '+00:00'))
                except:
                    pass

            for book in event.get('bookmakers', []):
                book_name = book.get('key', 'unknown')

                for market in book.get('markets', []):
                    market_key = market.get('key', '')
                    is_alt = 'alternate' in market_key

                    for o in market.get('outcomes', []):
                        team_name = o.get('description', o.get('name', ''))
                        outcome_type = o.get('name', '').lower()  # over/under
                        line_value = o.get('point')
                        price = o.get('price')

                        if line_value is None or price is None:
                            continue

                        # Determine if home or away team total
                        normalized_team = normalize_to_full(team_name, league)
                        if normalized_team == home:
                            side = 'home'
                        elif normalized_team == away:
                            side = 'away'
                        else:
                            side = 'home' if team_name == event.get('home_team') else 'away'

                        market_label = f"team_total_{side}"
                        if is_alt:
                            market_label = f"alt_team_total_{side}"

                        over_odds = price if outcome_type == 'over' else None
                        under_odds = price if outcome_type == 'under' else None

                        if dry_run:
                            print(f"    [DRY] {home} vs {away} | {market_label} {line_value} | "
                                  f"{book_name}: o={over_odds} u={under_odds}")
                            total += 1
                            continue

                        # Store in GameOdds for regular, GameOddsAltLine for alt
                        if is_alt:
                            # GameOddsAltLine schema: gameId, market, team, opponent, lineValue, oddsAmerican
                            cur.execute('''
                                INSERT INTO "GameOddsAltLine" (
                                    league, "gameId", "gameDate", "homeTeam", "awayTeam",
                                    team, opponent, market, bookmaker, "lineValue",
                                    "oddsAmerican", "fetchedAt", source
                                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), 'theoddsapi')
                                ON CONFLICT ("league", "gameId", "bookmaker", "market", "team", "lineValue")
                                DO UPDATE SET "oddsAmerican" = EXCLUDED."oddsAmerican", "fetchedAt" = NOW()
                            ''', (
                                league, event_id, commence_dt, home, away,
                                normalized_team, away if normalized_team == home else home,
                                market_label, book_name, line_value,
                                over_odds or under_odds
                            ))
                        else:
                            # GameOdds schema: gameId, market, lineValue, overOdds, underOdds
                            cur.execute('''
                                INSERT INTO "GameOdds" (
                                    league, "gameId", "gameDate", "homeTeam", "awayTeam",
                                    market, bookmaker, "lineValue",
                                    "overOdds", "underOdds", "fetchedAt", source
                                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), 'theoddsapi')
                                ON CONFLICT ("league", "gameId", "bookmaker", "market")
                                DO UPDATE SET "lineValue" = EXCLUDED."lineValue",
                                    "overOdds" = EXCLUDED."overOdds",
                                    "underOdds" = EXCLUDED."underOdds",
                                    "fetchedAt" = NOW()
                            ''', (
                                league, event_id, commence_dt, home, away,
                                market_label, book_name, line_value,
                                over_odds, under_odds
                            ))
                        total += 1

        time.sleep(1)

    if not dry_run:
        conn.commit()
    cur.close()

    print(f"\n  Team totals captured: {total}")
    print(f"  Quota remaining: {fetcher.quota_remaining}")
    return total


def fetch_soccer_specials(fetcher: ExtendedMarketsFetcher, conn, leagues: List[str] = None,
                          dry_run: bool = False):
    """Fetch soccer special markets (BTTS, draw no bet, double chance, 3-way)"""
    if leagues is None:
        leagues = SOCCER_LEAGUES

    cur = conn.cursor()
    total = 0

    print(f"\n{'='*60}")
    print("FETCHING SOCCER SPECIALS")
    print(f"Time: {datetime.now(timezone.utc).isoformat()}")
    print(f"{'='*60}")

    for league in leagues:
        if league not in SOCCER_LEAGUES:
            continue
        sport_key = SPORT_KEYS.get(league)
        if not sport_key:
            continue

        print(f"  {league.upper()}: Fetching {','.join(SOCCER_MARKETS)}")

        events = fetcher.get_odds_with_markets(sport_key, SOCCER_MARKETS)
        if not events:
            print(f"  {league.upper()}: No events")
            continue

        print(f"  {league.upper()}: {len(events)} events")

        for event in events:
            event_id = event.get('id')
            home = normalize_to_full(event.get('home_team', ''), league)
            away = normalize_to_full(event.get('away_team', ''), league)
            commence = event.get('commence_time')

            commence_dt = None
            if commence:
                try:
                    commence_dt = datetime.fromisoformat(commence.replace('Z', '+00:00'))
                except:
                    pass

            for book in event.get('bookmakers', []):
                book_name = book.get('key', 'unknown')

                for market in book.get('markets', []):
                    market_key = market.get('key', '')
                    outcomes = market.get('outcomes', [])

                    home_odds = away_odds = draw_odds = None
                    line_value = None

                    for o in outcomes:
                        name = o.get('name', '')
                        price = o.get('price')

                        if market_key == 'btts':
                            if name == 'Yes':
                                home_odds = price
                            elif name == 'No':
                                away_odds = price
                        elif market_key in ('h2h_3_way', 'double_chance'):
                            if name == home or name == event.get('home_team'):
                                home_odds = price
                            elif name == away or name == event.get('away_team'):
                                away_odds = price
                            elif name == 'Draw':
                                draw_odds = price
                            # Double chance outcomes
                            elif 'Home' in name or '1' == name:
                                home_odds = price
                            elif 'Away' in name or '2' == name:
                                away_odds = price
                            elif 'Draw' in name or 'X' == name:
                                draw_odds = price
                        elif market_key == 'draw_no_bet':
                            if name == home or name == event.get('home_team'):
                                home_odds = price
                            elif name == away or name == event.get('away_team'):
                                away_odds = price

                    if home_odds is None and away_odds is None and draw_odds is None:
                        continue

                    if dry_run:
                        print(f"    [DRY] {home} vs {away} | {market_key} | "
                              f"{book_name}: h={home_odds} a={away_odds} d={draw_odds}")
                        total += 1
                        continue

                    # GameOdds schema: gameId, market, homeOdds, awayOdds
                    cur.execute('''
                        INSERT INTO "GameOdds" (
                            league, "gameId", "gameDate", "homeTeam", "awayTeam",
                            market, bookmaker, "lineValue",
                            "homeOdds", "awayOdds", "fetchedAt", source
                        ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), 'theoddsapi')
                        ON CONFLICT ("league", "gameId", "bookmaker", "market")
                        DO UPDATE SET "homeOdds" = EXCLUDED."homeOdds",
                            "awayOdds" = EXCLUDED."awayOdds",
                            "fetchedAt" = NOW()
                    ''', (
                        league, event_id, commence_dt, home, away,
                        market_key, book_name, line_value,
                        home_odds, away_odds
                    ))
                    total += 1

        time.sleep(1)

    if not dry_run:
        conn.commit()
    cur.close()

    print(f"\n  Soccer specials captured: {total}")
    print(f"  Quota remaining: {fetcher.quota_remaining}")
    return total


def fetch_alt_totals(fetcher: ExtendedMarketsFetcher, conn, leagues: List[str],
                     dry_run: bool = False):
    """Fetch alternate totals"""
    cur = conn.cursor()
    total = 0

    print(f"\n{'='*60}")
    print("FETCHING ALTERNATE TOTALS")
    print(f"Time: {datetime.now(timezone.utc).isoformat()}")
    print(f"{'='*60}")

    for league in leagues:
        if league not in ALT_TOTAL_SPORTS:
            continue
        sport_key = SPORT_KEYS.get(league)
        if not sport_key:
            continue

        markets = ['alternate_totals', 'alternate_spreads']
        print(f"  {league.upper()}: Fetching alternate lines")

        events = fetcher.get_odds_with_markets(sport_key, markets)
        if not events:
            continue

        for event in events:
            event_id = event.get('id')
            home = normalize_to_full(event.get('home_team', ''), league)
            away = normalize_to_full(event.get('away_team', ''), league)
            commence = event.get('commence_time')

            commence_dt = None
            if commence:
                try:
                    commence_dt = datetime.fromisoformat(commence.replace('Z', '+00:00'))
                except:
                    pass

            for book in event.get('bookmakers', []):
                book_name = book.get('key', 'unknown')

                for market in book.get('markets', []):
                    market_key = market.get('key', '')

                    for o in market.get('outcomes', []):
                        name = o.get('name', '')
                        line_value = o.get('point')
                        price = o.get('price')

                        if line_value is None or price is None:
                            continue

                        if 'totals' in market_key:
                            over_odds = price if name == 'Over' else None
                            under_odds = price if name == 'Under' else None
                            alt_market = 'alt_total'
                        else:
                            over_odds = price if name == home or name == event.get('home_team') else None
                            under_odds = price if name == away or name == event.get('away_team') else None
                            alt_market = 'alt_spread'

                        if dry_run:
                            print(f"    [DRY] {home} vs {away} | {alt_market} {line_value} | "
                                  f"{book_name}: {price}")
                            total += 1
                            continue

                        # GameOddsAltLine schema: gameId, market, team, lineValue, oddsAmerican
                        team_name_for_alt = name if name in (home, away, event.get('home_team'), event.get('away_team')) else ('Over' if name == 'Over' else 'Under')
                        opp_name = away if team_name_for_alt in (home, event.get('home_team')) else home

                        cur.execute('''
                            INSERT INTO "GameOddsAltLine" (
                                league, "gameId", "gameDate", "homeTeam", "awayTeam",
                                team, opponent, market, bookmaker, "lineValue",
                                "oddsAmerican", "fetchedAt", source
                            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, NOW(), 'theoddsapi')
                            ON CONFLICT ("league", "gameId", "bookmaker", "market", "team", "lineValue")
                            DO UPDATE SET "oddsAmerican" = EXCLUDED."oddsAmerican", "fetchedAt" = NOW()
                        ''', (
                            league, event_id, commence_dt, home, away,
                            team_name_for_alt, opp_name,
                            alt_market, book_name, line_value,
                            price
                        ))
                        total += 1

        time.sleep(1)

    if not dry_run:
        conn.commit()
    cur.close()

    print(f"\n  Alt lines captured: {total}")
    print(f"  Quota remaining: {fetcher.quota_remaining}")
    return total


def main():
    parser = argparse.ArgumentParser(description='The Odds API Extended Markets Fetcher')
    parser.add_argument('--periods', action='store_true', help='Fetch period markets')
    parser.add_argument('--team-totals', action='store_true', help='Fetch team totals')
    parser.add_argument('--soccer', action='store_true', help='Fetch soccer specials')
    parser.add_argument('--alt-totals', action='store_true', help='Fetch alt totals & spreads')
    parser.add_argument('--all', action='store_true', help='Fetch all extended markets')
    parser.add_argument('--leagues', type=str, default='nba,nfl,nhl,mlb',
                        help='Comma-separated leagues (default: nba,nfl,nhl,mlb)')
    parser.add_argument('--dry-run', action='store_true', help='Preview without writing')

    args = parser.parse_args()

    if not any([args.periods, args.team_totals, args.soccer, args.alt_totals, args.all]):
        parser.print_help()
        return 1

    if args.all:
        args.periods = args.team_totals = args.soccer = args.alt_totals = True

    db_url, api_key = load_config()

    if not api_key:
        print("ERROR: THE_ODDS_API_KEY not configured")
        return 1
    if not db_url:
        print("ERROR: SPORTS_DATABASE_URL not configured")
        return 1

    fetcher = ExtendedMarketsFetcher(api_key, db_url, dry_run=args.dry_run)
    leagues = [l.strip() for l in args.leagues.split(',')]

    conn = psycopg2.connect(db_url)
    ensure_tables(conn)

    # Log ingestion start
    ingestion_id = None
    if UNIFIED_AVAILABLE and not args.dry_run:
        try:
            ingestion_id = log_ingestion_start(conn, 'theoddsapi-extended', 'multi', 'scheduled')
        except Exception as e:
            print(f"Warning: Could not log ingestion start: {e}")

    total = 0
    errors = 0

    try:
        if args.periods:
            try:
                total += fetch_period_markets(fetcher, conn, leagues, args.dry_run)
            except Exception as e:
                print(f"ERROR in period markets: {e}")
                errors += 1

        if args.team_totals:
            try:
                total += fetch_team_totals(fetcher, conn, leagues, args.dry_run)
            except Exception as e:
                print(f"ERROR in team totals: {e}")
                errors += 1

        if args.soccer:
            try:
                total += fetch_soccer_specials(fetcher, conn, leagues, args.dry_run)
            except Exception as e:
                print(f"ERROR in soccer specials: {e}")
                errors += 1

        if args.alt_totals:
            try:
                total += fetch_alt_totals(fetcher, conn, leagues, args.dry_run)
            except Exception as e:
                print(f"ERROR in alt totals: {e}")
                errors += 1

    finally:
        # Log ingestion complete
        if UNIFIED_AVAILABLE and ingestion_id and not args.dry_run:
            try:
                log_ingestion_complete(
                    conn, ingestion_id,
                    odds_created=total,
                    errors_count=errors,
                    status='completed' if errors == 0 else 'completed_with_errors'
                )
            except Exception as e:
                print(f"Warning: Could not log ingestion complete: {e}")

    print(f"\n{'='*60}")
    print(f"EXTENDED MARKETS COMPLETE")
    print(f"  Total records: {total}")
    print(f"  Errors: {errors}")
    print(f"  Quota used: {fetcher.quota_used}")
    print(f"  Quota remaining: {fetcher.quota_remaining}")
    if args.dry_run:
        print(f"  MODE: DRY RUN (no data written)")
    print(f"{'='*60}")

    conn.close()
    return 0


if __name__ == '__main__':
    exit(main())
