import xbmc
import xbmcgui
import xbmcaddon
import xbmcvfs
import xbmcgui
import os
import re
from datetime import datetime, timedelta, timezone
import time
# from epggrid import EPGGrid
import requests
from tools import show_tools, debug_log
from themes import apply_theme_to_window

ADDON = xbmcaddon.Addon()
TEMP_PATH = xbmcvfs.translatePath('special://temp')

# Default sport thumbnails mapping (used when ESPN doesn't provide team logos)
# Maps sport names to local thumbnail files
SPORT_THUMBNAILS = {
    'nfl': 'nfl.png',
    'nba': 'nba.png',
    'nhl': 'nhl.png',
    'wnba': 'wnba.png',
    'mlb': 'baseball.png',
    'cfl': 'cfb.png',
    'ncaab': 'basketball.png',
    'mls': 'soccer.png',
    'premierleague': 'soccer.png',
    'laliga': 'soccer.png',
    'bundesliga': 'soccer.png',
    'seriea': 'soccer.png',
    'ligue1': 'soccer.png',
    'championsleague': 'soccer.png',
}

class TimeListControl(xbmcgui.ControlList):
    def __init__(self, *args, **kwargs):
        self.grid = kwargs.pop('grid', None)
        super().__init__(*args, **kwargs)
        TimeoutError
    def onAction(self, action):
        if action.getId() == 7:  # ACTION_SELECT_ITEM
            if self.grid:
                self.grid.handleGameSelection()
        super().onAction(action)

class SportsGrid(xbmcgui.WindowXML):
    @classmethod
    def is_dialog_locked(cls):
        """Check if a dialog is currently locked"""
        return cls._dialog_lock
    
    @classmethod
    def acquire_dialog_lock(cls, owner):
        """Acquire dialog lock to prevent concurrent dialogs"""
        if cls._dialog_lock:
            return False
        cls._dialog_lock = True
        cls._dialog_locked_by = owner
        return True
    
    @classmethod
    def release_dialog_lock(cls, owner):
        """Release dialog lock"""
        if cls._dialog_locked_by == owner:
            cls._dialog_lock = False
            cls._dialog_locked_by = None
    
    # Sport-specific team name mappings
    # Class-level dialog lock to prevent concurrent busydialog crashes
    _dialog_lock = False
    _dialog_locked_by = None
    TEAM_MAPPINGS = {
        'mlb': {
            'chi': 'chicago',
            'la': 'los angeles',
            'ny': 'new york',
            'chi cubs': 'chicago cubs',
            'chi white sox': 'chicago white sox',
            'la angels': 'los angeles angels',
            'la dodgers': 'los angeles dodgers',
            'ny yankees': 'new york yankees',
            'ny mets': 'new york mets',
            'athletics': 'oakland athletics',
            'a\'s': 'oakland athletics',
            'jays': 'toronto blue jays',
            'rays': 'tampa bay rays',
            'nats': 'washington nationals',
            'detroit': 'detroit tigers',
            'cincinnati': 'cincinnati reds',
            'toronto': 'toronto blue jays',
            'philadelphia': 'philadelphia phillies',
            'miami': 'miami marlins',
            'washington': 'washington nationals',
            'colorado': 'colorado rockies',
            'atlanta': 'atlanta braves',
            'boston': 'boston red sox',
            'baltimore': 'baltimore orioles',
            'tampa bay': 'tampa bay rays',
            'minnesota': 'minnesota twins',
            'houston': 'houston astros',
            'st. louis': 'st. louis cardinals',
            'milwaukee': 'milwaukee brewers',
            'kansas city': 'kansas city royals',
            'pittsburgh': 'pittsburgh pirates',
            'texas': 'texas rangers',
            'san diego': 'san diego padres',
            'arizona': 'arizona diamondbacks',
            'cleveland': 'cleveland guardians',
            'seattle': 'seattle mariners',
            'san francisco': 'san francisco giants'
        },
        'nba': {
            'cleveland': 'cleveland cavaliers',
            'boston': 'boston celtics',
            'new york': 'new york knicks',
            'indiana': 'indiana pacers',
            'milwaukee': 'milwaukee bucks',
            'detroit': 'detroit pistons',
            'orlando': 'orlando magic',
            'atlanta': 'atlanta hawks',
            'chicago': 'chicago bulls',
            'miami': 'miami heat',
            'toronto': 'toronto raptors',
            'brooklyn': 'brooklyn nets',
            'philadelphia': 'philadelphia 76ers',
            'charlotte': 'charlotte hornets',
            'washington': 'washington wizards',
            'oklahoma city': 'oklahoma city thunder',
            'houston': 'houston rockets',
            'la lakers': 'los angeles lakers',
            'la clippers': 'los angeles clippers',
            'denver': 'denver nuggets',
            'minnesota': 'minnesota timberwolves',
            'golden state': 'golden state warriors',
            'memphis': 'memphis grizzlies',
            'sacramento': 'sacramento kings',
            'dallas': 'dallas mavericks',
            'phoenix': 'phoenix suns',
            'portland': 'portland trail blazers',
            'san antonio': 'san antonio spurs',
            'new orleans': 'new orleans pelicans',
            'utah': 'utah jazz'
        },
        'wnba': {
            'atlanta': 'atlanta dream',
            'chicago': 'chicago sky',
            'connecticut': 'connecticut sun',
            'dallas': 'dallas wings',
            'indiana': 'indiana fever',
            'las vegas': 'las vegas aces',
            'minnesota': 'minnesota lynx',
            'new york': 'new york liberty',
            'phoenix': 'phoenix mercury',
            'seattle': 'seattle storm',
            'washington': 'washington mystics',
            'fever': 'indiana fever',
            'sky': 'chicago sky',
            'sun': 'connecticut sun',
            'wings': 'dallas wings',
            'aces': 'las vegas aces',
            'lynx': 'minnesota lynx',
            'liberty': 'new york liberty',
            'mercury': 'phoenix mercury',
            'storm': 'seattle storm',
            'mystics': 'washington mystics',
            'dream': 'atlanta dream'
        },
        'nhl': {
            'boston': 'boston bruins',
            'buffalo': 'buffalo sabres',
            'detroit': 'detroit red wings',
            'florida': 'florida panthers',
            'montreal': 'montreal canadiens',
            'ottawa': 'ottawa senators',
            'tampa bay': 'tampa bay lightning',
            'toronto': 'toronto maple leafs',
            'carolina': 'carolina hurricanes',
            'columbus': 'columbus blue jackets',
            'new jersey': 'new jersey devils',
            'ny islanders': 'new york islanders',
            'ny rangers': 'new york rangers',
            'philadelphia': 'philadelphia flyers',
            'pittsburgh': 'pittsburgh penguins',
            'washington': 'washington capitals',
            'arizona': 'arizona coyotes',
            'chicago': 'chicago blackhawks',
            'colorado': 'colorado avalanche',
            'dallas': 'dallas stars',
            'minnesota': 'minnesota wild',
            'nashville': 'nashville predators',
            'st. louis': 'st. louis blues',
            'winnipeg': 'winnipeg jets',
            'anaheim': 'anaheim ducks',
            'calgary': 'calgary flames',
            'edmonton': 'edmonton oilers',
            'los angeles': 'los angeles kings',
            'san jose': 'san jose sharks',
            'seattle': 'seattle kraken',
            'vancouver': 'vancouver canucks',
            'vegas': 'vegas golden knights'
        },
        'nfl': {
            'buffalo': 'buffalo bills',
            'miami': 'miami dolphins',
            'new england': 'new england patriots',
            'ny jets': 'new york jets',
            'baltimore': 'baltimore ravens',
            'cincinnati': 'cincinnati bengals',
            'cleveland': 'cleveland browns',
            'pittsburgh': 'pittsburgh steelers',
            'houston': 'houston texans',
            'indianapolis': 'indianapolis colts',
            'jacksonville': 'jacksonville jaguars',
            'tennessee': 'tennessee titans',
            'denver': 'denver broncos',
            'kansas city': 'kansas city chiefs',
            'la chargers': 'los angeles chargers',
            'las vegas': 'las vegas raiders',
            'dallas': 'dallas cowboys',
            'ny giants': 'new york giants',
            'philadelphia': 'philadelphia eagles',
            'washington': 'washington commanders',
            'chicago': 'chicago bears',
            'detroit': 'detroit lions',
            'green bay': 'green bay packers',
            'minnesota': 'minnesota vikings',
            'atlanta': 'atlanta falcons',
            'carolina': 'carolina panthers',
            'new orleans': 'new orleans saints',
            'tampa bay': 'tampa bay buccaneers',
            'arizona': 'arizona cardinals',
            'la rams': 'los angeles rams',
            'san francisco': 'san francisco 49ers',
            'seattle': 'seattle seahawks'
        },
        'mls': {
            'atlanta': 'atlanta united',
            'austin': 'austin fc',
            'charlotte': 'charlotte fc',
            'chicago': 'chicago fire',
            'colorado': 'colorado rapids',
            'columbus': 'columbus crew',
            'd.c.': 'dc united',
            'dc': 'dc united',
            'dallas': 'fc dallas',
            'houston': 'houston dynamo',
            'los angeles': 'los angeles fc',
            'la': 'los angeles fc',
            'la galaxy': 'la galaxy',
            'miami': 'inter miami',
            'minnesota': 'minnesota united',
            'montreal': 'cf montreal',
            'nashville': 'nashville sc',
            'new england': 'new england revolution',
            'new york': 'new york city fc',
            'nyc': 'new york city fc',
            'ny red bulls': 'new york red bulls',
            'orlando': 'orlando city',
            'philadelphia': 'philadelphia union',
            'portland': 'portland timbers',
            'real salt lake': 'real salt lake',
            'san jose': 'san jose earthquakes',
            'seattle': 'seattle sounders',
            'sporting kc': 'sporting kansas city',
            'st. louis': 'st. louis city',
            'toronto': 'toronto fc',
            'vancouver': 'vancouver whitecaps'
        },
        'premierleague': {
            'arsenal': 'arsenal',
            'aston villa': 'aston villa',
            'bournemouth': 'bournemouth',
            'brentford': 'brentford',
            'brighton': 'brighton & hove albion',
            'chelsea': 'chelsea',
            'crystal palace': 'crystal palace',
            'everton': 'everton',
            'fulham': 'fulham',
            'liverpool': 'liverpool',
            'manchester city': 'manchester city',
            'man city': 'manchester city',
            'manchester united': 'manchester united',
            'man united': 'manchester united',
            'newcastle': 'newcastle united',
            'nottingham': 'nottingham forest',
            'southampton': 'southampton',
            'tottenham': 'tottenham hotspur',
            'west ham': 'west ham united',
            'wolves': 'wolverhampton wanderers'
        },
        'laliga': {
            'alaves': 'alaves',
            'almería': 'almeria',
            'athletic bilbao': 'athletic bilbao',
            'athletic': 'athletic bilbao',
            'atletico madrid': 'atletico madrid',
            'atletico': 'atletico madrid',
            'barcelona': 'fc barcelona',
            'barca': 'fc barcelona',
            'celta vigo': 'celta vigo',
            'celta': 'celta vigo',
            'espanyol': 'espanyol',
            'girona': 'girona',
            'granada': 'granada',
            'las palmas': 'las palmas',
            'levante': 'levante',
            'mallorca': 'mallorca',
            'osasuna': 'osasuna',
            'rayo vallecano': 'rayo vallecano',
            'real betis': 'real betis',
            'real madrid': 'real madrid',
            'real sociedad': 'real sociedad',
            'sevilla': 'sevilla',
            'valencia': 'valencia',
            'villarreal': 'villarreal'
        },
        'bundesliga': {
            'augsburg': 'augsburg',
            'bayern munich': 'bayern munich',
            'bayern': 'bayern munich',
            'bochum': 'bochum',
            'darmstadt': 'darmstadt',
            'dortmund': 'borussia dortmund',
            'eintracht frankfurt': 'eintracht frankfurt',
            'freiburg': 'freiburg',
            'hertha': 'hertha bsc',
            'hoffenheim': 'hoffenheim',
            'koln': 'koln',
            'leverkusen': 'bayer leverkusen',
            'mainz': 'mainz',
            'monchengladbach': 'borussia monchengladbach',
            'rb leipzig': 'rb leipzig',
            'stuttgart': 'vfb stuttgart',
            'union berlin': 'union berlin',
            'werder bremen': 'werder bremen',
            'wolfsburg': 'wolfsburg'
        },
        'seriea': {
            'atalanta': 'atalanta',
            'bologna': 'bologna',
            'cagliari': 'cagliari',
            'empoli': 'empoli',
            'fiorentina': 'fiorentina',
            'frosinone': 'frosinone',
            'genoa': 'genoa',
            'inter milan': 'inter milan',
            'inter': 'inter milan',
            'juventus': 'juventus',
            'lazio': 'lazio',
            'lecce': 'lecce',
            'milan': 'ac milan',
            'ac milan': 'ac milan',
            'monza': 'monza',
            'napoli': 'napoli',
            'roma': 'roma',
            'salernitana': 'salernitana',
            'sassuolo': 'sassuolo',
            'torino': 'torino',
            'udinese': 'udinese',
            'venezia': 'venezia',
            'verona': 'verona'
        },
        'ligue1': {
            'brest': 'brest',
            'clermont': 'clermont',
            'le havre': 'le havre',
            'lens': 'lens',
            'lille': 'lille',
            'lyon': 'lyon',
            'marseille': 'marseille',
            'monaco': 'monaco',
            'montpellier': 'montpellier',
            'nantes': 'nantes',
            'nice': 'nice',
            'paris': 'paris saint-germain',
            'psg': 'paris saint-germain',
            'reims': 'reims',
            'rennes': 'rennes',
            'strasbourg': 'strasbourg',
            'toulouse': 'toulouse'
        },
        'championsleague': {
            'arsenal': 'arsenal',
            'atletico madrid': 'atletico madrid',
            'barcelona': 'fc barcelona',
            'bayern': 'bayern munich',
            'bayern munich': 'bayern munich',
            'benfica': 'benfica',
            'borussia dortmund': 'borussia dortmund',
            'chelsea': 'chelsea',
            'dortmund': 'borussia dortmund',
            'fc barcelona': 'fc barcelona',
            'inter milan': 'inter milan',
            'juventus': 'juventus',
            'liverpool': 'liverpool',
            'manchester city': 'manchester city',
            'manchester united': 'manchester united',
            'marseille': 'marseille',
            'milan': 'ac milan',
            'ac milan': 'ac milan',
            'monaco': 'monaco',
            'napoli': 'napoli',
            'paris saint-germain': 'paris saint-germain',
            'psg': 'paris saint-germain',
            'real madrid': 'real madrid',
            'roma': 'roma',
            'sevilla': 'sevilla',
            'tottenham': 'tottenham hotspur',
            'valencia': 'valencia'
        }
    }

    @classmethod
    def normalize_team_name(cls, name, sport):
        """Normalize team name for comparison"""
        if not name:
            return ''
        # Clean up the input name
        name = name.lower().strip()
        original = name
        # Remove playoff seeds and qualifiers (e.g., "(4)", "-z", "-y", "-x")
        name = re.sub(r'\(\d+\)|-[xyz]', '', name).strip()
        # Special case for MLB A's/Athletics
        if sport == 'mlb' and name in ['a\'s', 'athletics', 'oakland a\'s', 'oakland athletics']:
            return 'oakland athletics'
        # Remove division prefix
        if name.startswith(('e-', 'c-', 'w-')):
            name = name[2:].strip()
        # Try direct mapping first
        sport_mappings = cls.TEAM_MAPPINGS.get(sport, {})
        mapped = sport_mappings.get(name)
        if mapped:
            return mapped
        # Split into parts and handle duplicates
        parts = name.split()
        if len(parts) >= 2:
            # Try city mapping
            city = ' '.join(parts[:-1])  # Everything except last word
            nickname = parts[-1]
            # Check if nickname repeats city
            if nickname in city:
                name = city  # Use city as base if nickname is redundant
            else:
                name = ' '.join(parts)
            # Check city mapping again
            mapped_city = sport_mappings.get(city)
            if mapped_city:
                result = mapped_city
                return result
            # Try full team name
            mapped = sport_mappings.get(name)
            if mapped:
                return mapped
        return name

    def set_time_slots(self):
        """Set up sports-appropriate time slots for the grid."""
        now = datetime.now().astimezone(self.local_tz)
        # Create predefined time slots for games
        self.time_slots = [
            # Morning games
            (now.replace(hour=9, minute=0, second=0, microsecond=0),
             now.replace(hour=12, minute=0, second=0, microsecond=0)),
            # Early afternoon games
            (now.replace(hour=12, minute=0, second=0, microsecond=0),
             now.replace(hour=15, minute=0, second=0, microsecond=0)),
            # Late afternoon games
            (now.replace(hour=15, minute=0, second=0, microsecond=0),
             now.replace(hour=18, minute=0, second=0, microsecond=0)),
            # Evening games
            (now.replace(hour=18, minute=0, second=0, microsecond=0),
             now.replace(hour=21, minute=0, second=0, microsecond=0)),
            # Night games
            (now.replace(hour=21, minute=0, second=0, microsecond=0),
             now.replace(hour=23, minute=59, second=59, microsecond=999999))
        ]

    def __init__(self, xml_file: str, addon_path: str, sport: str):
        # Call parent constructor first to ensure window is properly initialized
        super().__init__(xml_file, addon_path)
        # Initialize controls
        self.time_panel = None
        self.channel_panel = None
        self.sport = sport.lower()
        self.local_tz = datetime.now().astimezone().tzinfo
        self.is_android = 'ANDROID_DATA' in os.environ or 'ANDROID_ROOT' in os.environ
        self.android_optimize_mode = False
        self.android_input_debounce_ms = 120
        self.last_interaction_time = time.time()
        # Initialize basic attributes needed by EPGGrid
        self.all_channels = []
        self.channels = []
        self.programs = []
        self.is_sports_view = True
        self.program_cache = {}
        self.visible_rows = 13
        self.current_page = 0
        self.time_scroll_pos = 0
        self.time_slots = []
        self.selected_program = None
        # Set up initial time slots
        self.set_time_slots()

        if self.is_android:
            try:
                self.android_optimize_mode = ADDON.getSettingBool('android_optimize_mode')
            except Exception:
                self.android_optimize_mode = ADDON.getSetting('android_optimize_mode') == 'true'
            try:
                self.android_input_debounce_ms = max(50, int(ADDON.getSetting('android_input_debounce_ms') or '120'))
            except Exception:
                self.android_input_debounce_ms = 120

        # Get sports data
        
        try:
            # Load data
            scores = self.get_scores()
            debug_log(f"SportsGrid: Found {len(scores)} games for {self.sport}", xbmc.LOGINFO)
            standings_data = self.get_standings()
            debug_log(f"SportsGrid: Found {len(standings_data)} standings entries for {self.sport}", xbmc.LOGINFO)
            # Format data
            self.all_channels = self.format_channels(standings_data)
            debug_log(f"SportsGrid: Created {len(self.all_channels)} channels", xbmc.LOGINFO)
            self.channels = self.all_channels[:]
            self.programs = self.format_programs(scores)
            debug_log(f"SportsGrid: Created {len(self.programs)} programs", xbmc.LOGINFO)
            
        except Exception as e:
            debug_log(f"SportsGrid: Exception in load: {str(e)}", xbmc.LOGERROR)
            xbmcgui.Dialog().ok("Error", "Failed to load sports data. Please try again.")
            self.channels = []
            self.programs = []
            self.close()
            return
        
        if not self.channels:
            xbmcgui.Dialog().ok("Error", "No sports data available. Please try again.")
            self.close()
            return

    def onInit(self):
        """Override onInit to handle sports-specific initialization"""
        # Apply theme colors to window first
        try:
            apply_theme_to_window(self)
        except Exception as e:
            debug_log(f"SportsGrid: Error applying theme: {str(e)}", xbmc.LOGERROR)
        
        try:
            debug_log("SportsGrid: onInit starting", xbmc.LOGINFO)
            # Initialize panels before parent onInit
            self.channel_panel = None
            self.time_panel = None
            # Call parent onInit
            super().onInit()
            debug_log("SportsGrid: super().onInit() done", xbmc.LOGINFO)
            # Set window title
            self.setProperty('SportTitle', self.sport.upper())
            # Verify we have channels (standings)
            if not self.channels:
                xbmcgui.Dialog().ok("Error", "No sports data available. Please try again.")
                self.close()
                return
            # Initialize and populate panels
            self.channel_panel = self.getControl(100)
            self.time_panel = self.getControl(101)
            debug_log(f"SportsGrid: Got controls: channel={self.channel_panel}, time={self.time_panel}", xbmc.LOGINFO)
            # Configure panels
            self.channel_panel.setEnabled(True)
            self.time_panel.setEnabled(True)
            # Populate data
            self.populate_channel_panel()
            self.populate_time_panel()
            debug_log("SportsGrid: Populated panels", xbmc.LOGINFO)
            # Initial focus and selection - start with teams panel
            # Fix: Check if control exists and is focusable before setting focus
            if self.channel_panel.size() > 0:
                self.channel_panel.selectItem(0)
                # Only try to focus if the control is valid and visible
                try:
                    if self.channel_panel:
                        self.setFocusId(100)
                except Exception as e:
                    debug_log(f"SportsGrid: Could not set focus to control 100: {str(e)}", xbmc.LOGWARNING)
                    # Android/skin fallback: try time panel if teams panel cannot receive focus
                    try:
                        if self.time_panel and self.time_panel.size() > 0:
                            self.time_panel.selectItem(0)
                            self.setFocusId(101)
                    except Exception:
                        pass
            # Make sure both panels are visible and enabled
            self.channel_panel.setVisible(True)
            self.time_panel.setVisible(True)
            
            # Update initial info display
            self.update_selected_info()
            
            # Hide loading overlay (now safely handles missing control 999)
            self.hide_loading()
            debug_log("SportsGrid: onInit complete", xbmc.LOGINFO)
                
        except Exception as e:
            debug_log(f"SportsGrid: onInit error: {str(e)}", xbmc.LOGERROR)
            xbmcgui.Dialog().ok("Error", "Failed to initialize display. Please try again.")
            self.close()
            return

    def get_standings(self):
        try:
            sport_map = {
                'mlb': 'sports/baseball/mlb',
                'nba': 'sports/basketball/nba',
                'ncaab': 'sports/basketball/mens-college-basketball',
                'nhl': 'sports/hockey/nhl',
                'wnba': 'sports/basketball/wnba',
                'nfl': 'sports/football/nfl',
                'mls': 'sports/soccer/usa.1',
                'premierleague': 'sports/soccer/eng.1',
                'laliga': 'sports/soccer/esp.1',
                'bundesliga': 'sports/soccer/ger.1',
                'seriea': 'sports/soccer/ita.1',
                'ligue1': 'sports/soccer/fra.1',
                'championsleague': 'sports/soccer/uefa.champions'
            }
            espn_sport = sport_map.get(self.sport, f'sports/{self.sport}')
            current_year = datetime.now().year
            soccer_leagues = ['mls', 'premierleague', 'laliga', 'bundesliga', 'seriea', 'ligue1', 'championsleague']
            if self.sport in soccer_leagues:
                years_to_try = [2025, 2024, 2026, current_year - 1]
            else:
                years_to_try = [current_year, current_year - 1]
            data = None
            for year in years_to_try:
                try:
                    url = f"https://site.api.espn.com/apis/v2/{espn_sport}/standings?season={year}"
                    debug_log(f"SportsGrid: 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:
                        data = response.json()
                        break
                except Exception as e:
                    debug_log(f"SportsGrid: Error fetching standings for {year}: {e}", xbmc.LOGWARNING)
                    continue
            if not data:
                debug_log("SportsGrid: No standings data available", xbmc.LOGWARNING)
                return []
            
            # Extract league logo from the response
            self.league_logo = ''
            debug_log(f"SportsGrid: API response keys: {data.keys()}", xbmc.LOGINFO)
            leagues = data.get('leagues', [])
            debug_log(f"SportsGrid: Found {len(leagues)} leagues in response", xbmc.LOGINFO)
            if leagues:
                first_league = leagues[0]
                debug_log(f"SportsGrid: First league: {first_league.get('name')}", xbmc.LOGINFO)
                league_logos = first_league.get('logos', [])
                debug_log(f"SportsGrid: League has {len(league_logos)} logos", xbmc.LOGINFO)
                if league_logos:
                    self.league_logo = league_logos[0].get('href', '')
                    debug_log(f"SportsGrid: Found league logo: {self.league_logo}", xbmc.LOGINFO)
            else:
                debug_log("SportsGrid: No leagues found in response", xbmc.LOGWARNING)
            
            standings = []
            children = data.get('children', [])
            for league in children:
                league_name = league.get('name', '')
                if league_name:
                    standings.append({'team_name': league_name})
                league_standings = league.get('standings', {})
                entries = league_standings.get('entries', [])
                for entry in entries:
                    team = entry.get('team', {})
                    team_name = team.get('displayName', '')
                    if not team_name:
                        continue
                    if any(word in team_name.lower() for word in ['division', 'conference', 'league', 'wild card']):
                        standings.append({'team_name': team_name})
                        continue
                    logos = team.get('logos', [])
                    logo_url = ''
                    if logos:
                        logo_url = logos[0].get('href', '')
                    normalized_name = self.normalize_team_name(team_name, self.sport)
                    record = {'team_name': normalized_name, 'logo_url': logo_url}
                    stats = entry.get('stats', [])
                    for stat in stats:
                        stat_name = stat.get('name', '')
                        display_value = stat.get('displayValue', '')
                        if stat_name == 'wins':
                            record['wins'] = display_value
                        elif stat_name == 'losses':
                            record['losses'] = display_value
                        elif stat_name == 'winPercent':
                            record['pct'] = display_value
                        elif stat_name == 'gamesBehind':
                            record['gb'] = display_value
                        elif stat_name == 'homeWinPercent' or stat_name == 'homeRecord':
                            record['home'] = display_value
                        elif stat_name == 'roadWinPercent' or stat_name == 'awayRecord':
                            record['away'] = display_value
                        elif stat_name == 'last10':
                            record['last10'] = display_value
                        elif stat_name == 'streak':
                            record['streak'] = display_value
                    standings.append(record)
            return standings
        except Exception as e:
            debug_log(f"SportsGrid: Error in get_standings: {str(e)}", xbmc.LOGERROR)
            return []

    def populate_channel_panel(self):
        """Populate or repopulate the channel panel"""
        debug_log("SportsGrid DEBUG: Entered populate_channel_panel", xbmc.LOGINFO)
        self.channel_panel.reset()
        for idx, channel in enumerate(self.channels):
            team_name = channel.get('name', '')
            record = channel.get('record', '')
            item = xbmcgui.ListItem(label=team_name.upper())
            item.setProperty('record', record)
            logo_url = channel.get('logo', '')
            debug_log(f"SportsGrid: Team {team_name}, logo: {logo_url[:50] if logo_url else 'None'}...", xbmc.LOGINFO)
            if logo_url:
                item.setArt({'thumb': logo_url, 'icon': logo_url})
                item.setProperty('logo', logo_url)
            
            for stat in ['wins', 'losses', 'pct', 'gb', 'home', 'away', 'l10', 'strk']:
                value = channel.get(stat, '')
                if value:
                    item.setProperty(stat, str(value))
            
            self.channel_panel.addItem(item)
            
    def populate_time_panel(self):
        """Populate or repopulate the time panel"""
        self.time_panel.reset()
        sorted_programs = sorted(
            self.programs,
            key=lambda x: (
                x.get('time', datetime.max) if isinstance(x.get('time'), datetime) else datetime.max,
                'A' if 'final' in str(x.get('status', '')).lower() else
                'B' if any(hint in str(x.get('status', '')).lower() for hint in ['live', 'quarter', 'period', 'inning']) else 'C'
            )
        )
        for idx, program in enumerate(sorted_programs, 1):
            title = program.get('title', '')
            desc = program.get('desc', '')
            status = program.get('status', '')
            if isinstance(program.get('time'), datetime):
                time_str = program['time'].strftime('%I:%M %p').lstrip('0')
            else:
                time_str = 'TBD'
            item = xbmcgui.ListItem(label=title.upper())
            item.setProperty('time', time_str)
            item.setProperty('game', title)
            item.setProperty('status', status)
            item.setProperty('description', desc)
            self.time_panel.addItem(item)

    def get_scores(self):
        try:
            sport_map = {
                'mlb': 'sports/baseball/mlb',
                'nba': 'sports/basketball/nba',
                'ncaab': 'sports/basketball/mens-college-basketball',
                'nhl': 'sports/hockey/nhl',
                'wnba': 'sports/basketball/wnba',
                'nfl': 'sports/football/nfl',
                'mls': 'sports/soccer/usa.1',
                'premierleague': 'sports/soccer/eng.1',
                'laliga': 'sports/soccer/esp.1',
                'bundesliga': 'sports/soccer/ger.1',
                'seriea': 'sports/soccer/ita.1',
                'ligue1': 'sports/soccer/fra.1',
                'championsleague': 'sports/soccer/uefa.champions'
            }
            espn_sport = sport_map.get(self.sport, f'sports/{self.sport}')
            url = f"https://site.api.espn.com/apis/site/v2/{espn_sport}/scoreboard"
            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()
            games = []
            events = data.get('events', [])
            for event in events:
                competition = event.get('competitions', [{}])[0]
                competitors = competition.get('competitors', [])
                if len(competitors) < 2:
                    continue
                team1 = competitors[0].get('team', {})
                team2 = competitors[1].get('team', {})
                team1_name = team1.get('displayName', '')
                team2_name = team2.get('displayName', '')
                
                # Skip All-Star type games
                if team1_name.startswith('Team ') or team2_name.startswith('Team '):
                    continue
                
                if not team1_name or not team2_name:
                    continue
                team1_norm = self.normalize_team_name(team1_name, self.sport)
                team2_norm = self.normalize_team_name(team2_name, self.sport)
                score1 = str(competitors[0].get('score', ''))
                score2 = str(competitors[1].get('score', ''))
                status_obj = competition.get('status', {})
                status_type = status_obj.get('type', {})
                status = status_type.get('description', 'TBD')
                period = status_obj.get('period', '')
                clock = status_obj.get('displayClock', '')
                if period and clock:
                    status = f"{status} - {period}Q {clock}"
                elif period:
                    status = f"{status} - {period}"
                networks = competition.get('broadcasts', [])
                network = networks[0].get('names', ['TBD'])[0] if networks else 'TBD'
                games.append({
                    'team1': team1_norm,
                    'team2': team2_norm,
                    'score1': score1,
                    'score2': score2,
                    'status': status,
                    'network': network,
                    'time': None
                })
            return games
        except Exception as e:
            debug_log(f"SportsGrid: Error in get_scores: {str(e)}", xbmc.LOGERROR)
            return []

    def format_channels(self, standings):
        """Format standings data as channels for the grid"""
        channels = []
        channel_number = 1
        
        # Get default logo - prefer league logo from API, then fall back to local thumbnail
        default_logo = getattr(self, 'league_logo', '')
        debug_log(f"SportsGrid: league_logo attribute: {default_logo}", xbmc.LOGINFO)
        
        # If no league logo from API, try local thumbnail
        if not default_logo:
            default_thumb = SPORT_THUMBNAILS.get(self.sport, '')
            if default_thumb:
                default_logo = f"special://home/addons/plugin.video.jet_guide/resources/skins/default/720p/media/sports/{default_thumb}"
        
        debug_log(f"SportsGrid: Using default logo: {default_logo}", xbmc.LOGINFO)
        
        # Sort standings by division/conference blocks, then by wins (descending), then losses (ascending)
        def sort_key(entry):
            try:
                wins = float(entry.get('wins', 0))
                losses = float(entry.get('losses', 0))
                # Use negative wins for descending order
                return (-wins, losses)
            except Exception:
                return (0, 0)
        
        # Group by division/conference headers, keep their order, but sort teams within each group
        sorted_standings = []
        group = []
        for entry in standings:
            if 'team_name' in entry and len(entry) == 1:
                # Sort previous group if exists
                if group:
                    group.sort(key=sort_key)
                    sorted_standings.extend(group)
                    group = []
                sorted_standings.append(entry)
            else:
                group.append(entry)
        if group:
            group.sort(key=sort_key)
            sorted_standings.extend(group)
        
        for entry in sorted_standings:
            if 'team_name' in entry and len(entry) == 1:
                continue
            stats = []
            if entry.get('wins') and entry.get('losses'):
                stats.append(f"{entry['wins']} - {entry['losses']}")
            if entry.get('pct'):
                stats.append(f"{entry['pct']}")
            if entry.get('gb'):
                stats.append(f"{entry['gb']}")
            if entry.get('home'):
                stats.append(f"{entry['home']}")
            if entry.get('away') or entry.get('road'):
                stats.append(f"{entry.get('away', entry.get('road', ''))}")
            if entry.get('last10') or entry.get('last5'):
                stats.append(f"{entry.get('last10', entry.get('last5', ''))}")
            if entry.get('streak'):
                stats.append(f"{entry['streak']}")
            record = " | ".join(stats)
            
            # Use ESPN logo if available, otherwise use default sport thumbnail
            logo = entry.get('logo_url', '')
            if not logo and default_logo:
                logo = default_logo
            
            channel = {
                'name': entry['team_name'],
                'tvg_id': f"sports_{self.sport}_{channel_number}",
                'logo': logo,
                'group': self.sport.upper(),
                'record': record,
                'label': str(channel_number),
                'label2': entry['team_name']
            }
            channels.append(channel)
            channel_number += 1
        return channels

    def format_programs(self, games):
        """Format game data as programs for the grid"""
        programs = []
        processed_games = set()
        if not self.time_slots:
            self.set_time_slots()
        now = datetime.now().astimezone(self.local_tz)
        
        for game in games:
            game_id = f"{game['team1']}-{game['team2']}"
            if game_id in processed_games:
                continue
            processed_games.add(game_id)
            status_text = game['status'] if game['status'] else "TBD"
            
            # Simplified - just use default time slot and focus on status
            slot_start, slot_end = self.time_slots[3]  # Default to evening slot
            time_text = status_text  # Use status as time display
            
            team1_norm = game['team1']
            team2_norm = game['team2']
            
            team1_channel = next((c['tvg_id'] for c in self.channels
                                if c['name'] == team1_norm), None)
            team2_channel = next((c['tvg_id'] for c in self.channels
                                if c['name'] == team2_norm), None)
            
            # Add program even if only one channel is found
            if team1_channel or team2_channel:
                score_text = f" ({game['score1']}-{game['score2']})" if game['score1'] and game['score2'] else ""
                if 'final' in status_text.lower():
                    prefix = "[FINAL]"
                elif 'postponed' in status_text.lower() or 'ppd' in status_text.lower():
                    prefix = "[POSTPONED]"
                elif any(hint in status_text.lower() for hint in ['inning', 'quarter', 'period', 'live', 'bot', 'top']):
                    prefix = f"[[COLORlime]Live[/COLOR] - {status_text}]"
                elif 'scheduled' in status_text.lower():
                    prefix = "[SCHEDULED]"
                else:
                    prefix = f"[{status_text}]" if status_text != "Scheduled" else "[TBD]"
                game_text = f"{team1_norm.upper()} vs {team2_norm.upper()}{score_text}"
                game_title = f"{prefix} | {game_text}"
                desc_lines = [
                    f"Status: {status_text}",
                    f"Time: {time_text}",
                    f"Teams: {team1_norm.upper()} vs {team2_norm.upper()}{score_text}",
                    f"Network: {game['network'] or 'TBD'}"
                ]
                program_data = {
                    'start': slot_start,
                    'stop': slot_end,
                    'title': game_title,
                    'desc': "\n".join(desc_lines),
                    'category': self.sport.upper(),
                    'time': time_text,
                    'status': status_text
                }
                program_data['channel'] = team1_channel or team2_channel
                program_data['away_channel'] = team2_channel if team1_channel else None
                programs.append(program_data)
        return programs
        
    def update_selected_info(self):
        """Update info panel based on current selection"""
        try:
            focused_id = self.getFocusId()
            debug_log(f"SportsGrid: update_selected_info called, focused_id={focused_id}", xbmc.LOGINFO)
            
            # Default to channel panel if no focus
            if focused_id == 0:
                focused_id = 100
            
            if focused_id == 100 and self.channel_panel:  # Team stats panel
                # Show team statistics
                selected_pos = self.channel_panel.getSelectedPosition()
                debug_log(f"SportsGrid: Channel panel pos={selected_pos}, size={self.channel_panel.size()}", xbmc.LOGINFO)
                if 0 <= selected_pos < self.channel_panel.size():
                    selected_item = self.channel_panel.getSelectedItem()
                    team_name = selected_item.getLabel()
                    team_record = selected_item.getProperty('record')
                    debug_log(f"SportsGrid: Selected team: {team_name}, record: {team_record}", xbmc.LOGINFO)
                    
                    # Build team stats info
                    stats_info = []
                    if team_record:
                        stats_info.append(f"Record: {team_record}")
                    
                    # Add any additional team stats from properties
                    for prop in ['wins', 'losses', 'pct', 'gb', 'home', 'away', 'l10']:
                        value = selected_item.getProperty(prop)
                        if value:
                            stats_info.append(f"{prop.upper()}: {value}")
                    
                    self.setProperty('GameTitle', f"[B]{team_name.upper()} Statistics[/B]")
                    self.setProperty('GameInfo', '\n'.join(stats_info) if stats_info else 'No statistics available')
                    debug_log(f"SportsGrid: Set GameInfo: {stats_info}", xbmc.LOGINFO)
                    
            elif focused_id == 101 and self.time_panel:  # Games panel
                # Show game information
                selected_pos = self.time_panel.getSelectedPosition()
                debug_log(f"SportsGrid: Time panel pos={selected_pos}, size={self.time_panel.size()}", xbmc.LOGINFO)
                if 0 <= selected_pos < self.time_panel.size():
                    selected_item = self.time_panel.getSelectedItem()
                    game_info_text = selected_item.getProperty('game')
                    
                    if game_info_text:
                        self.setProperty('GameTitle', '[B]Game Information[/B]')
                        self.setProperty('GameInfo', game_info_text)
                    else:
                        self.setProperty('GameTitle', '[B]No Game Selected[/B]')
                        self.setProperty('GameInfo', 'Select a game to view details')
            else:
                # Clear info if no valid selection
                self.setProperty('GameTitle', '')
                self.setProperty('GameInfo', '')
                
        except Exception as e:
            debug_log(f"SportsGrid: update_selected_info error: {str(e)}", xbmc.LOGERROR)
            # Clear properties on error
            self.setProperty('GameTitle', '')
            self.setProperty('GameInfo', '')

    def update_program_info(self, selected_item, channel=None):
        """Update the info panel with sports-specific information"""
        try:
            # Clear properties if no item
            self.setProperty('GameTitle', '')
            self.setProperty('GameInfo', '')
            if not selected_item:
                return
            # Get game title from item or dict
            game = (selected_item.getProperty('game') if isinstance(selected_item, xbmcgui.ListItem)
                   else selected_item.get('title', ''))
            if not game:
                return
            # Build info display
            game_info = []
            self.setProperty('GameTitle', f"[B]{game}[/B]")
            # Add channel/team info if available
            if channel and isinstance(channel, dict):
                record = channel.get('record', '')
                team_name = channel.get('name', '')
                if record and team_name:
                    game_info.append(f"[COLOR yellow]{team_name.upper()}:[/COLOR] {record}")
            # Add program details
            for program in self.programs:
                if program.get('title') == game and program.get('desc'):
                    for line in program['desc'].split('\n'):
                        game_info.append(line)
            self.setProperty('GameInfo', '\n'.join(game_info))
            
        except Exception as e:
            # debug_log(f"SportsGrid: Error updating program info: {str(e)}", xbmc.LOGERROR)
            # Clear properties on error
            self.setProperty('GameTitle', '')
            self.setProperty('GameInfo', '')
    
    def show_loading(self):
        """Show the loading overlay"""
        try:
            # Fix: Check if control 999 exists before trying to use it
            loading_control = self.getControl(999)
            if loading_control:
                loading_control.setVisible(True)
        except:
            # Control 999 doesn't exist in skin - silently ignore
            pass
    
    def hide_loading(self):
        """Hide the loading overlay"""
        try:
            # Fix: Check if control 999 exists before trying to use it
            loading_control = self.getControl(999)
            if loading_control:
                loading_control.setVisible(False)
        except:
            # Control 999 doesn't exist in skin - silently ignore
            pass
    
    def update_loading_progress(self, progress_text="", percent=0):
        """Update loading progress text and bar"""
        try:
            # Update loading text
            if progress_text:
                text_control = self.getControl(998)
                text_control.setLabel(progress_text)
            
            # Update progress bar width (360px max width)
            if 0 <= percent <= 100:
                progress_width = int((percent / 100) * 360)
                progress_control = self.getControl(997)
                progress_control.setWidth(progress_width)
        except Exception as e:
            pass

    def handleGameSelection(self):
            """Handle game selection and stream dialog. Only trigger playback after explicit user selection."""
            # Fix: Use dialog lock to prevent concurrent busydialog crash
            if not self.acquire_dialog_lock('handleGameSelection'):
                debug_log("SportsGrid: Dialog already in use, skipping", xbmc.LOGWARNING)
                return
            
            try:
                item = self.time_panel.getSelectedItem()
                if not item:
                    self.release_dialog_lock('handleGameSelection')
                    return

                game_title = item.getProperty('game')
                if not game_title:
                    self.release_dialog_lock('handleGameSelection')
                    return
                parts = game_title.split('|')
                if len(parts) < 2:
                    self.release_dialog_lock('handleGameSelection')
                    return
                teams_part = parts[1].strip()
                teams = teams_part.split('vs')
                if len(teams) != 2:
                    self.release_dialog_lock('handleGameSelection')
                    return

                team1_full = teams[0].strip()
                team2_full = teams[1].strip()
                # Remove records or extra info in parentheses
                team1_name = re.sub(r"\s*\(.*?\)", "", team1_full).lower().strip()
                team2_name = re.sub(r"\s*\(.*?\)", "", team2_full).lower().strip()
                
                # Try fuzzy matching for team names in stream titles
                def fuzzy_match(title, team1, team2):
                    t = re.sub(r'\[/?[a-z]+.*?\]', '', title.lower())
                    t = re.sub(r'[^a-z0-9 ]', '', t)
                    team1_clean = re.sub(r'[^a-z0-9 ]', '', team1)
                    team2_clean = re.sub(r'[^a-z0-9 ]', '', team2)
                    debug_log(f"[DEBUG] Matching '{team1_clean}' and '{team2_clean}' against '{t}'", xbmc.LOGINFO)
                    result = (team1_clean in t or team1_clean.split()[-1] in t) and (team2_clean in t or team2_clean.split()[-1] in t)
                    debug_log(f"[DEBUG] Result: {result}", xbmc.LOGINFO)
                    return result
                
                # Use lock-aware progress dialog
                progress = xbmcgui.DialogProgress()
                progress.create('Searching', f'Searching for {team1_name} vs {team2_name}...\n{game_title}')
                if "wnba" in self.sport:
                    url = f'https://magnetic.website/MAD_TITAN_SPORTS/SPORTS/LEAGUE/titansports_nba.json'
                elif "mls" in self.sport or "premierleague" in self.sport or "laliga" in self.sport or "bundesliga" in self.sport or "seriea" in self.sport or "ligue1" in self.sport or "championsleague" in self.sport:
                    url = f'https://magnetic.website/MAD_TITAN_SPORTS/SPORTS/LEAGUE/titansports_soccer.json'
                else:
                    url = f'https://magnetic.website/MAD_TITAN_SPORTS/SPORTS/LEAGUE/titansports_{self.sport}.json'
                try:
                    response = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'}, timeout=10)
                    response.raise_for_status()
                    data = response.json()
                except Exception as e:
                    progress.close()
                    xbmcgui.Dialog().ok("Error", f"Failed to load game data: {str(e)}")
                    self.release_dialog_lock('handleGameSelection')
                    return
                progress.update(25, 'Loading game data...')
                stream_links = []
                stream_names = []
                total_items = len(data.get('items', []))
                if total_items == 0:
                    progress.close()
                    xbmcgui.Dialog().ok("Error", "No games found in data source")
                    self.release_dialog_lock('handleGameSelection')
                    return
                for idx, game in enumerate(data['items']):
                    if progress.iscanceled():
                        progress.close()
                        self.release_dialog_lock('handleGameSelection')
                        return
                    progress.update(50 + int((idx / total_items) * 50), f'Checking game {idx + 1} of {total_items}...')
                    if (game.get('type') == 'item' and
                        game.get('title') and
                        fuzzy_match(game.get('title',''), team1_name, team2_name)):
                        
                        if 'link' in game:
                            links = game.get('link', [])
                            for i, link in enumerate(links):
                                clean_url = link
                                stream_name = f"Stream {i + 1}"
                                if '(' in link and ')' in link:
                                    stream_name = link[link.rindex('(')+1:link.rindex(')')].strip()
                                    clean_url = link[:link.rindex('(')].strip()
                                elif '[COLOR' in link and '[/COLOR]' in link:
                                    clean_url = re.sub(r'\[COLOR.*?\](.*?)\[/COLOR\]', r'\1', link).strip()
                                    if '(' in clean_url and ')' in clean_url:
                                        stream_name = clean_url[clean_url.rindex('(')+1:clean_url.rindex(')')].strip()
                                        clean_url = clean_url[:clean_url.rindex('(')].strip()

                                stream_links.append(clean_url)
                                stream_names.append(stream_name)
                progress.close()
                if not stream_links:
                    self.release_dialog_lock('handleGameSelection')
                    return
                dialog = xbmcgui.Dialog()
                choice = dialog.select('Choose Stream', stream_names)
            
                if choice is not None and choice >= 0:
                    selected_url = stream_links[choice]
                    list_item = xbmcgui.ListItem(game_title)
                    list_item.setInfo('video', {'title': game_title})
                    list_item.setProperty('IsPlayable', 'true')
                    try:
                        from youtube_guide import cancel_youtube_playback
                        cancel_youtube_playback()
                    except ImportError:
                        pass
                    xbmc.Player().play(selected_url, list_item)
                # Only trigger playback if a stream was explicitly selected
                self.release_dialog_lock('handleGameSelection')

            except Exception as e:
                xbmcgui.Dialog().ok("Error", f"Failed to play stream: {str(e)}")
                self.release_dialog_lock('handleGameSelection')
    def onClick(self, control_id):
        """Handle click events"""
        # Handle sport selection buttons
        if control_id in range(900, 911):
            self.handle_sport_button(control_id)
            return
        # Handle click on time panel (right side)
        if control_id == 101 and self.time_panel:
            if hasattr(self, 'handleGameSelection') and callable(getattr(self, 'handleGameSelection')):
                self.handleGameSelection()
            elif hasattr(self, 'handleGameSelection__patched') and callable(getattr(self, 'handleGameSelection__patched')):
                self.handleGameSelection__patched()
            else:
                # Try to call as a method of the class (handleGameSelection may be indented inside another method)
                try:
                    type(self).handleGameSelection(self)
                except Exception as e:
                    # import xbmcgui
                    xbmcgui.Dialog().ok("Error", f"Could not trigger game selection: {str(e)}")
            return
    
    def switch_sport(self, new_sport):
        """Switch to a different sport by using executebuiltin to properly navigate"""
        try:
            debug_log(f"SportsGrid: Switching to sport: {new_sport}", xbmc.LOGINFO)
            # Close current window first
            self.close()
            # Force close any remaining dialogs/windows
            xbmc.executebuiltin('Dialog.Close(all,true)')
            xbmc.sleep(200)
            # Use executebuiltin to open the sports grid
            xbmc.executebuiltin(f'RunPlugin(plugin://plugin.video.jet_guide/?action=sports_grid&sport={new_sport})')
        except Exception as e:
            debug_log(f"SportsGrid: Error in switch_sport: {str(e)}", xbmc.LOGERROR)
            xbmcgui.Dialog().ok("Error", f"Failed to switch sport: {str(e)}")
    
    def show_more_sports(self):
        """Show dialog with more sports options"""
        more_sports = [
            ("CFL", "cfl"),
            ("Bundesliga", "bundesliga"),
            ("Serie A", "seriea"),
            ("Ligue 1", "ligue1"),
            ("Champions League", "championsleague"),
        ]
        
        sport_names = [name for name, _ in more_sports]
        dialog = xbmcgui.Dialog()
        choice = dialog.select('Select Sport', sport_names)
        
        if choice >= 0:
            sport_code = more_sports[choice][1]
            self.switch_sport(sport_code)
    
    def onAction(self, action):
        """Handle navigation and selection actions"""
        try:
            action_id = action.getId()
            focused_id = self.getFocusId()

            if self.is_android and self.android_optimize_mode:
                now_ts = int(time.time() * 1000)
                last_ms = int(self.last_interaction_time * 1000)
                if now_ts - last_ms < self.android_input_debounce_ms:
                    return
            self.last_interaction_time = time.time()

            # Handle button clicks for sport selection
            if action_id == 7:  # SELECT button pressed
                # Check if a sport button was clicked
                if focused_id in range(900, 911):  # Our sport buttons are 900-910
                    self.handle_sport_button(focused_id)
                    return
            
            # Handle navigation actions
            if action_id == 7:
                if focused_id == 101 and self.time_panel:
                    self.handleGameSelection()
                    return
                    
            elif action_id == 1 and focused_id == 101:
                if self.channel_panel and self.channel_panel.size() > 0:
                    # Fix: Check if control 100 exists and is valid before focusing
                    try:
                        self.setFocusId(100)
                        self.channel_panel.selectItem(0)
                    except Exception as e:
                        debug_log(f"SportsGrid: Could not set focus to control 100: {str(e)}", xbmc.LOGWARNING)
                    self.update_selected_info()
                return
                
            elif action_id == 2 and focused_id == 100:
                if self.time_panel and self.time_panel.size() > 0:
                    self.setFocusId(101)
                    self.time_panel.selectItem(0)
                    self.update_selected_info()
                return
            
            elif action_id in [3, 4]:
                if focused_id in [100, 101]:
                    self.update_selected_info()
                    return
            
            elif action_id in [9, 10, 92, 117, 216, 247, 257, 275, 61467, 61448]:
                # Close all windows and go to home
                self.close()
                xbmc.sleep(100)
                xbmc.executebuiltin('Dialog.Close(all,true)')
                xbmc.sleep(100)
                xbmc.executebuiltin('ActivateWindow(10024)')  # Home screen
                return
            
        except Exception as e:
            pass
    
    def handle_sport_button(self, control_id):
        """Handle sport selection button clicks"""
        sport_map = {
            900: 'mlb',
            901: 'nba',
            902: 'nhl',
            903: 'nfl',
            904: 'wnba',
            905: 'ncaab',
            906: 'mls',
            907: 'premierleague',
            908: 'laliga',
            909: 'more',  # More sports dialog
            910: 'exit',  # Exit
        }
        
        sport = sport_map.get(control_id)
        
        if sport == 'exit':
            # Close all addon windows and go to home
            self.close()
            xbmc.sleep(100)
            xbmc.executebuiltin('Dialog.Close(all,true)')
            xbmc.sleep(100)
            xbmc.executebuiltin('ActivateWindow(10024)')  # Home screen
            return
        elif sport == 'more':
            self.show_more_sports()
            return
        elif sport:
            # Don't reload if already on this sport
            if sport == self.sport:
                return
            self.switch_sport(sport)