import xbmc
import requests
from datetime import datetime, timezone
from tools import debug_log


# Global cache for constructor standings (F1)
_constructor_standings = []

RACING_LEAGUE_MAP = {
    'f1': 'f1',
    'irl': 'irl',
    'nascar': 'nascar-premier',
}


def get_racing_scores(sport):
    """Get racing scores/results from ESPN API"""
    try:
        league = RACING_LEAGUE_MAP.get(sport.lower())
        if not league:
            debug_log(f"Racing: Unknown sport {sport}", xbmc.LOGERROR)
            return []
        
        url = f"https://site.api.espn.com/apis/site/v2/sports/racing/{league}/scoreboard"
        debug_log(f"Racing: Fetching scores from {url}", xbmc.LOGINFO)
        
        response = requests.get(
            url,
            headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'},
            timeout=10
        )
        response.raise_for_status()
        data = response.json()
        
        events = data.get('events', [])
        races = []
        
        for event in events:
            competitions = event.get('competitions', [])
            if not competitions:
                continue
            
            # For F1, we want the main Race session (type.id == "3")
            # For NASCAR, there's only one competition per event
            main_competition = None
            
            if sport.lower() == 'f1':
                # Find the main race session
                for comp in competitions:
                    comp_type = comp.get('type', {})
                    if comp_type.get('id') == '3' or comp_type.get('abbreviation') == 'Race':
                        main_competition = comp
                        break
                # If no race found, use qualifying
                if not main_competition:
                    for comp in competitions:
                        comp_type = comp.get('type', {})
                        if comp_type.get('id') == '2' or comp_type.get('abbreviation') == 'Qual':
                            main_competition = comp
                            break
            else:
                # NASCAR and IndyCar have single competition
                main_competition = competitions[0] if competitions else None
            
            if not main_competition:
                continue
            
            competitors = main_competition.get('competitors', [])
            status_obj = main_competition.get('status', {})
            status_type = status_obj.get('type', {})
            
            # Get top finishers (up to 10)
            finishers = []
            for comp in sorted(competitors, key=lambda x: x.get('order', 999)):
                athlete = comp.get('athlete', {})
                driver_name = athlete.get('displayName', '')
                if not driver_name:
                    continue
                
                flag_url = athlete.get('flag', {}).get('href', '')
                country = athlete.get('flag', {}).get('alt', '')
                
                finisher = {
                    'name': driver_name,
                    'country': country,
                    'flag': flag_url,
                    'position': comp.get('order', ''),
                    'winner': comp.get('winner', False),
                }
                finishers.append(finisher)
                
                if len(finishers) >= 10:
                    break
            
            # Build race info
            circuit = event.get('circuit', {})
            circuit_name = circuit.get('fullName', '')
            location = ''
            if circuit.get('address'):
                city = circuit['address'].get('city', '')
                state = circuit['address'].get('state', '')
                country = circuit['address'].get('country', '')
                parts = [p for p in [city, state, country] if p]
                location = ', '.join(parts)
            
            # Get circuit details (if available)
            circuit_length = ''
            total_laps = ''
            # ESPN API doesn't always provide these, but we can try
            if 'laps' in str(event).lower():
                # Try to extract lap info from event data
                pass
            
            broadcasts = main_competition.get('broadcasts', [])
            network = broadcasts[0].get('names', ['TBD'])[0] if broadcasts else 'TBD'
            
            # Determine status
            status_state = status_type.get('state', '')
            status_desc = status_type.get('description', 'Scheduled')
            period = status_obj.get('period', '')
            
            if status_state == 'post' or status_type.get('completed'):
                prefix = "[FINAL]"
            elif status_state == 'in':
                prefix = "[[COLORlime]LIVE[/COLOR]]"
                # Add lap info for live races (ESPN only provides current lap, not total)
                if period:
                    status_desc = f"Lap {period} - {status_desc}"
            else:
                prefix = "[SCHEDULED]"
            
            race_info = {
                'event_name': event.get('shortName', event.get('name', '')),
                'circuit': circuit_name,
                'location': location,
                'date': event.get('date', ''),
                'status': status_desc,
                'prefix': prefix,
                'network': network,
                'finishers': finishers,
                'winner': next((f for f in finishers if f.get('winner')), None),
                'lap': period if status_state == 'in' else '',
            }
            
            races.append(race_info)
        
        debug_log(f"Racing: Found {len(races)} races", xbmc.LOGINFO)
        return races
        
    except Exception as e:
        debug_log(f"Racing: Error fetching scores: {str(e)}", xbmc.LOGERROR)
        return []


def get_racing_standings(sport):
    """Get racing championship standings using ESPN site API"""
    try:
        league = RACING_LEAGUE_MAP.get(sport.lower())
        if not league:
            return []
        
        current_year = datetime.now().year
        
        # Use the site API which includes athlete data directly
        url = f"https://site.api.espn.com/apis/v2/sports/racing/{league}/standings?season={current_year}"
        debug_log(f"Racing: Fetching standings from {url}", xbmc.LOGINFO)
        
        response = requests.get(
            url,
            headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'},
            timeout=10
        )
        
        if response.status_code != 200:
            debug_log(f"Racing: Standings not available (HTTP {response.status_code})", xbmc.LOGWARNING)
            return []
        
        data = response.json()
        
        # Parse driver standings from site API format
        drivers = []
        constructors = []
        children = data.get('children', [])
        
        for child in children:
            child_name = child.get('name', '').lower()
            entries = child.get('standings', {}).get('entries', [])
            
            # Check for driver standings
            if 'driver' in child_name or ('standings' in child_name and 'constructor' not in child_name):
                debug_log(f"Racing: Found {len(entries)} driver entries in '{child.get('name')}'", xbmc.LOGINFO)
                for entry in entries:
                    driver = _parse_site_api_entry(entry, sport)
                    if driver:
                        drivers.append(driver)
            
            # Check for constructor standings (F1 only)
            elif 'constructor' in child_name and sport.lower() == 'f1':
                debug_log(f"Racing: Found {len(entries)} constructor entries", xbmc.LOGINFO)
                for entry in entries:
                    constructor = _parse_constructor_entry(entry)
                    if constructor:
                        constructors.append(constructor)
        
        debug_log(f"Racing: Successfully parsed {len(drivers)} drivers and {len(constructors)} constructors", xbmc.LOGINFO)
        
        # Store constructors in a global variable for later access
        if constructors:
            global _constructor_standings
            _constructor_standings = constructors
        
        return drivers
        
    except Exception as e:
        debug_log(f"Racing: Error fetching standings: {str(e)}", xbmc.LOGERROR)
        import traceback
        debug_log(f"Racing: Traceback: {traceback.format_exc()}", xbmc.LOGERROR)
        return []


def _parse_site_api_entry(entry, sport):
    """Parse a driver entry from ESPN site API standings"""
    try:
        athlete = entry.get('athlete', {})
        name = athlete.get('displayName', '') or athlete.get('name', '')
        
        if not name:
            return None
        
        flag = athlete.get('flag', {}).get('href', '')
        country = athlete.get('flag', {}).get('alt', '')
        
        # Extract stats
        stats = {}
        for stat in entry.get('stats', []):
            stat_name = stat.get('name', '').lower()
            value = stat.get('displayValue', '')
            
            if stat_name == 'rank':
                stats['rank'] = value
            elif 'championshippts' in stat_name or stat_name == 'points':
                stats['points'] = value
            elif stat_name == 'wins':
                stats['wins'] = value
            elif 'podium' in stat_name:
                stats['podiums'] = value
            elif stat_name == 'poles':
                stats['poles'] = value
            elif stat_name == 'top5':
                stats['top5'] = value
            elif stat_name == 'top10':
                stats['top10'] = value
        
        return {
            'name': name,
            'logo': '',
            'flag': flag,
            'country': country,
            'points': stats.get('points', '0'),
            'wins': stats.get('wins', ''),
            'podiums': stats.get('podiums', ''),
            'poles': stats.get('poles', ''),
            'top5': stats.get('top5', ''),
            'top10': stats.get('top10', ''),
            'rank': stats.get('rank', ''),
        }
    except Exception as e:
        debug_log(f"Racing: Error parsing site API entry: {str(e)}", xbmc.LOGWARNING)
        return None


def _parse_constructor_entry(entry):
    """Parse a constructor (team) entry from F1 standings"""
    try:
        team = entry.get('team', {})
        name = team.get('displayName', '') or team.get('name', '')
        
        if not name:
            return None
        
        logo = ''
        logos = team.get('logos', [])
        if logos:
            logo = logos[0].get('href', '')
        
        # Extract points
        points = '0'
        for stat in entry.get('stats', []):
            if 'championshippts' in stat.get('name', '').lower() or stat.get('name', '').lower() == 'points':
                points = stat.get('displayValue', '0')
                break
        
        return {
            'name': name,
            'logo': logo,
            'points': points,
        }
    except Exception as e:
        debug_log(f"Racing: Error parsing constructor entry: {str(e)}", xbmc.LOGWARNING)
        return None


def get_constructor_standings():
    """Get cached constructor standings (F1 only)"""
    return _constructor_standings


def _parse_driver_record(record, sport):
    """Parse a driver record from standings - legacy function kept for compatibility"""
    try:
        # First, extract stats from the record
        stats = {}
        for stat in record.get('stats', []):
            stat_name = stat.get('name', '').lower()
            value = stat.get('displayValue', '')
            
            if 'championshippts' in stat_name or stat_name == 'points':
                stats['points'] = value
            elif stat_name == 'wins':
                stats['wins'] = value
            elif 'podium' in stat_name:
                stats['podiums'] = value
            elif stat_name == 'poles':
                stats['poles'] = value
            elif stat_name == 'top5':
                stats['top5'] = value
            elif stat_name == 'top10':
                stats['top10'] = value
            elif stat_name == 'rank':
                stats['rank'] = value
        
        # The record itself doesn't have athlete info, we need to follow $ref
        ref_url = record.get('$ref', '')
        
        if ref_url:
            # Convert internal URL to public API
            ref_url = ref_url.replace('http://sports.core.api.espn.pvt', 'https://sports.core.api.espn.com')
            
            try:
                response = requests.get(
                    ref_url,
                    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'},
                    timeout=10
                )
                
                if response.status_code == 200:
                    athlete_data = response.json()
                    
                    # Try to find athlete info
                    athlete = athlete_data.get('athlete', {})
                    name = athlete.get('displayName', '') or athlete.get('fullName', '')
                    
                    if not name:
                        # Sometimes it's under 'team' for racing
                        team = athlete_data.get('team', {})
                        name = team.get('displayName', '') or team.get('name', '')
                    
                    if not name:
                        # Last resort: use the record displayName
                        name = record.get('displayName', 'Unknown Driver')
                    
                    logo = ''
                    logos = athlete.get('logos', []) or athlete_data.get('logos', [])
                    if logos:
                        logo = logos[0].get('href', '')
                    
                    flag = athlete.get('flag', {}).get('href', '')
                    country = athlete.get('flag', {}).get('alt', '')
                    
                    return {
                        'name': name,
                        'logo': logo,
                        'flag': flag,
                        'country': country,
                        'points': stats.get('points', '0'),
                        'wins': stats.get('wins', '0'),
                        'podiums': stats.get('podiums', ''),
                        'poles': stats.get('poles', ''),
                        'top5': stats.get('top5', ''),
                        'top10': stats.get('top10', ''),
                        'rank': stats.get('rank', ''),
                    }
            except Exception as e:
                debug_log(f"Racing: Error fetching athlete detail: {str(e)}", xbmc.LOGWARNING)
        
        # Fallback: create minimal driver entry without name
        return {
            'name': record.get('displayName', 'Unknown Driver'),
            'logo': '',
            'flag': '',
            'country': '',
            'points': stats.get('points', '0'),
            'wins': stats.get('wins', '0'),
            'podiums': stats.get('podiums', ''),
            'poles': stats.get('poles', ''),
            'top5': stats.get('top5', ''),
            'top10': stats.get('top10', ''),
            'rank': stats.get('rank', ''),
        }
        
    except Exception as e:
        debug_log(f"Racing: Error parsing driver record: {str(e)}", xbmc.LOGWARNING)
        return None


def format_racing_channels(standings, sport):
    """Format racing standings as channels"""
    channels = []
    
    default_logo = f"special://home/addons/plugin.video.jet_guide/resources/skins/default/720p/media/sports/racing.png"
    
    for idx, driver in enumerate(standings, 1):
        stats_parts = []
        # Only add stats that have actual values (not empty or '0')
        points = driver.get('points', '0')
        if points and points != '0':
            stats_parts.append(f"Pts: {points}")
        
        wins = driver.get('wins', '')
        if wins and wins != '0':
            stats_parts.append(f"W: {wins}")
        
        podiums = driver.get('podiums', '')
        if podiums and podiums != '0':
            stats_parts.append(f"Pod: {podiums}")
        
        poles = driver.get('poles', '')
        if poles and poles != '0':
            stats_parts.append(f"Pole: {poles}")
        
        top5 = driver.get('top5', '')
        if top5 and top5 != '0':
            stats_parts.append(f"T5: {top5}")
        
        top10 = driver.get('top10', '')
        if top10 and top10 != '0':
            stats_parts.append(f"T10: {top10}")
        
        record = " | ".join(stats_parts) if stats_parts else f"Pts: {points}"
        
        channel = {
            'name': driver['name'],
            'tvg_id': f"racing_{sport}_{idx}",
            'logo': driver.get('logo') or driver.get('flag') or default_logo,
            'group': sport.upper(),
            'record': record,
            'label': str(idx),
            'label2': driver['name'],
            'points': driver.get('points', ''),
            'wins': driver.get('wins', ''),
            'podiums': driver.get('podiums', ''),
            'poles': driver.get('poles', ''),
            'top5': driver.get('top5', ''),
            'top10': driver.get('top10', ''),
            'country': driver.get('country', ''),
        }
        channels.append(channel)
    
    return channels


def get_racing_calendar(sport):
    """Get full season calendar with all upcoming races"""
    try:
        league = RACING_LEAGUE_MAP.get(sport.lower())
        if not league:
            return []
        
        current_year = datetime.now().year
        
        # Fetch scoreboard which includes calendar data
        url = f"https://site.api.espn.com/apis/site/v2/sports/racing/{league}/scoreboard"
        debug_log(f"Racing: Fetching calendar from {url}", xbmc.LOGINFO)
        
        response = requests.get(
            url,
            headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'},
            timeout=10
        )
        
        if response.status_code != 200:
            return []
        
        data = response.json()
        
        # Extract calendar from leagues array
        leagues = data.get('leagues', [])
        if not leagues:
            return []
        
        calendar = leagues[0].get('calendar', [])
        
        races = []
        for event_ref in calendar:
            label = event_ref.get('label', '')
            start_date = event_ref.get('startDate', '')
            end_date = event_ref.get('endDate', '')
            
            if not label or not start_date:
                continue
            
            # Parse date
            try:
                date_obj = datetime.fromisoformat(start_date.replace('Z', '+00:00'))
                date_str = date_obj.strftime('%b %d, %Y')
                time_str = date_obj.strftime('%I:%M %p').lstrip('0')
            except:
                date_str = start_date[:10]
                time_str = ''
            
            races.append({
                'name': label,
                'date': date_str,
                'time': time_str,
                'start_date': start_date,
                'end_date': end_date,
            })
        
        debug_log(f"Racing: Found {len(races)} calendar events", xbmc.LOGINFO)
        return races
        
    except Exception as e:
        debug_log(f"Racing: Error fetching calendar: {str(e)}", xbmc.LOGERROR)
        return []


def format_racing_programs(races, channels, sport):
    """Format racing events as programs"""
    from datetime import timedelta
    
    programs = []
    
    # Create time slots for races
    now = datetime.now().astimezone()
    time_slots = [
        (now.replace(hour=9, minute=0, second=0, microsecond=0),
         now.replace(hour=12, minute=0, second=0, microsecond=0)),
        (now.replace(hour=12, minute=0, second=0, microsecond=0),
         now.replace(hour=15, minute=0, second=0, microsecond=0)),
        (now.replace(hour=15, minute=0, second=0, microsecond=0),
         now.replace(hour=18, minute=0, second=0, microsecond=0)),
        (now.replace(hour=18, minute=0, second=0, microsecond=0),
         now.replace(hour=21, minute=0, second=0, microsecond=0)),
        (now.replace(hour=21, minute=0, second=0, microsecond=0),
         now.replace(hour=23, minute=59, second=59, microsecond=999999))
    ]
    
    for race in races:
        # Assign to evening slot by default
        slot_start, slot_end = time_slots[3]
        
        # Build title
        winner = race.get('winner')
        winner_text = f" - Winner: {winner['name']}" if winner else ""
        
        title = f"{race['prefix']} {race['event_name']}{winner_text}"
        
        # Build description
        desc_lines = [
            f"Circuit: {race.get('circuit', 'TBD')}",
            f"Location: {race.get('location', 'TBD')}",
        ]
        
        # Add lap progress for live races
        lap = race.get('lap', '')
        if lap:
            desc_lines.append(f"Current Lap: {lap}")
        
        desc_lines.extend([
            f"Status: {race.get('status', 'TBD')}",
            f"Network: {race.get('network', 'TBD')}",
        ])
        
        # Add top finishers
        finishers = race.get('finishers', [])
        if finishers:
            desc_lines.append("\nTop Finishers:")
            for i, f in enumerate(finishers[:5], 1):
                flag = f"[IMG]{f['flag']}[/IMG] " if f.get('flag') else ""
                desc_lines.append(f"  {i}. {flag}{f['name']} ({f.get('country', '')})")
        
        program = {
            'start': slot_start,
            'stop': slot_end,
            'title': title,
            'desc': "\n".join(desc_lines),
            'category': sport.upper(),
            'time': race.get('status', 'TBD'),
            'status': race.get('status', 'TBD'),
            'channel': channels[0]['tvg_id'] if channels else f"racing_{sport}_1",
        }
        programs.append(program)
    
    return programs
