#!/usr/bin/env python3
"""Fetch odds from The Odds API for sports not covered by BallDontLie.
   Merges data into the existing historical files, enriching matching games.
"""
import json
import os
import sys
from datetime import datetime
from pathlib import Path
import urllib.request
import urllib.error
import re

# Get API KEY from environment (required - no hardcoded fallbacks)
API_KEY = os.environ.get("ODDS_API_KEY")
if not API_KEY:
    print("ERROR: ODDS_API_KEY environment variable is not set", file=sys.stderr)
    sys.exit(1)
BASE_URL = "https://api.the-odds-api.com/v4"
DATA_DIR = Path("/var/www/html/eventheodds/data/betting")

SPORT_MAP = {
    "mlb": "baseball_mlb",
    "epl": "soccer_epl",
    "bundesliga": "soccer_germany_bundesliga",
    "seriea": "soccer_italy_serie_a",
    "ligue1": "soccer_france_ligue_one",
    "laliga": "soccer_spain_la_liga",
    "ucl": "soccer_uefa_champs_league",
    "nba": "basketball_nba",
    "nfl": "americanfootball_nfl",
    "nhl": "icehockey_nhl",
    "ncaab": "basketball_ncaab",
    "wnba": "basketball_wnba",
    "ncaaf": "americanfootball_ncaaf"
}

def normalize_team(name):
    """Normalize team name for matching."""
    if not name: return ""
    # Lowercase
    n = name.lower()
    # Remove city names roughly (last word is usually the identifier)
    # Exceptions
    if "trail blazers" in n: return "blazers"
    if "maple leafs" in n: return "leafs"
    if "blue jays" in n: return "jays"
    if "red sox" in n: return "sox"
    if "white sox" in n: return "sox"
    
    words = n.split()
    return words[-1] if words else n

def fetch_sport_odds(sport_key, our_sport):
    """Fetch odds for a specific sport key and merge."""
    data_file = DATA_DIR / (our_sport + "_historical.json")
    existing_games = []
    
    # Create directory if it does not exist
    DATA_DIR.mkdir(parents=True, exist_ok=True)
    
    if data_file.exists():
        try:
            with open(data_file) as f:
                existing_games = json.load(f)
        except json.JSONDecodeError:
            print(f"Warning: Could not decode {data_file}, starting fresh.")
            existing_games = []
    
    # Build lookup map for existing games
    # Key: (date, home_team_normalized)
    game_map = {}
    for i, game in enumerate(existing_games):
        d = game.get("date", "")[:10]
        h = normalize_team(game.get("homeTeam") or game.get("home_team"))
        if d and h:
            game_map[(d, h)] = i

    # Fetch standardized odds (h2h, spreads, totals)
    url = f"{BASE_URL}/sports/{sport_key}/odds?apiKey={API_KEY}&regions=us&markets=h2h,spreads,totals&oddsFormat=american"
    
    print(f"Fetching {our_sport.upper()} odds from The Odds API...")
    try:
        with urllib.request.urlopen(url, timeout=30) as resp:
            odds_data = json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        print(f"HTTP Error fetching {sport_key}: {e.code} - {e.reason}")
        return 0
    except Exception as e:
        print(f"Error fetching {sport_key}: {str(e)}")
        return 0
    
    if not odds_data:
        print(f"No active games found for {our_sport}")
        return 0
    
    print(f"Found {len(odds_data)} games from Odds API for {our_sport}")
    
    updated_count = 0
    new_count = 0
    
    for game in odds_data:
        game_date = game["commence_time"][:10]
        home_team = game["home_team"]
        home_norm = normalize_team(home_team)
        
        # Try to find match
        match_idx = game_map.get((game_date, home_norm))
        
        target_game = None
        if match_idx is not None:
            target_game = existing_games[match_idx]
        else:
            # Optional: Add new game logic if we decided to append new games (without scores).
            # For now, skipping unwatched games to avoid polluting with scoreless entries
            # print(f"No match for {game_date} {home_team} vs {game['away_team']}")
            continue

        # Extract odds
        sportsbooks = {}
        spread = None
        total = None
        home_ml = None
        away_ml = None
        
        for bookmaker in game.get("bookmakers", []):
            book_name = bookmaker["key"]
            book_odds = {}
            
            for market in bookmaker.get("markets", []):
                if market["key"] == "h2h":
                    for outcome in market["outcomes"]:
                        if outcome["name"] == game["home_team"]:
                            book_odds["home_ml"] = outcome["price"]
                            if home_ml is None: home_ml = outcome["price"]
                        else:
                            book_odds["away_ml"] = outcome["price"]
                            if away_ml is None: away_ml = outcome["price"]
                elif market["key"] == "spreads":
                    for outcome in market["outcomes"]:
                        if outcome["name"] == game["home_team"]:
                            book_odds["spread"] = outcome.get("point")
                            if spread is None: spread = outcome.get("point")
                elif market["key"] == "totals":
                    for outcome in market["outcomes"]:
                        if outcome["name"] == "Over":
                            book_odds["total"] = outcome.get("point")
                            if total is None: total = outcome.get("point")
            
            if book_odds:
                sportsbooks[book_name] = book_odds
        
        if not sportsbooks:
            continue
            
        # Update existing game if it doesn't have real odds or if we want to augment
        # Check current status
        current_source = target_game.get("odds", {}).get("source")
        has_real = target_game.get("hasRealOdds", False)
        
        # We update if: No real odds, or source is not 'live'/'balldontlie'
        # Or if we want to fill in missing fields?
        # Let's be aggressive: If source is 'none' or missing, definitely update.
        if not has_real or current_source in ["none", "unknown", None]:
            target_game["odds"] = {
                "moneylineHome": home_ml,
                "moneylineAway": away_ml,
                "spreadHome": spread,
                "spreadAway": -spread if spread else None,
                "totalLine": total,
                "source": "the-odds-api",
                "sportsbooks": sportsbooks
            }
            target_game["hasRealOdds"] = True
            updated_count += 1
    
    if updated_count > 0:
        with open(data_file, "w") as f:
            json.dump(existing_games, f, indent=2)
        print(f"{our_sport.upper()}: Updated {updated_count} games with new odds.")
    else:
        print(f"{our_sport.upper()}: No existing games required updates.")
        
    return updated_count

def fetch_all_mapped_sports():
    """Fetch odds for all sports defined in SPORT_MAP."""
    total_new = 0
    for our_sport, api_sport in SPORT_MAP.items():
        total_new += fetch_sport_odds(api_sport, our_sport)
    return total_new

if __name__ == "__main__":
    # Allow passing a specific sport or all
    sport_arg = sys.argv[1] if len(sys.argv) > 1 else "all"
    
    if sport_arg == "all":
        fetch_all_mapped_sports()
    elif sport_arg in SPORT_MAP:
        fetch_sport_odds(SPORT_MAP[sport_arg], sport_arg)
    else:
        print(f"Unknown sport: {sport_arg}")
        print(f"Available sports: {', '.join(SPORT_MAP.keys())}")
