"""
Games thread component for managing game-related operations
"""

import time
import logging
import threading
from datetime import datetime
from typing import Optional, Dict, Any, List

from .thread_manager import ThreadedComponent
from .message_bus import MessageBus, Message, MessageType, MessageBuilder
from ..database.manager import DatabaseManager
from ..database.models import MatchModel, MatchStatus

logger = logging.getLogger(__name__)


class GamesThread(ThreadedComponent):
    """Games thread for handling game operations and monitoring"""

    def __init__(self, name: str, message_bus: MessageBus, db_manager: DatabaseManager):
        super().__init__(name, message_bus)
        self.db_manager = db_manager
        self.current_fixture_id: Optional[str] = None
        self.game_active = False
        self._shutdown_event = threading.Event()
        self.message_queue = None

    def initialize(self) -> bool:
        """Initialize the games thread"""
        try:
            logger.info("Initializing GamesThread...")

            # Register with message bus first
            self.message_queue = self.message_bus.register_component(self.name)

            # Subscribe to relevant messages
            self.message_bus.subscribe(self.name, MessageType.START_GAME, self._handle_start_game)
            self.message_bus.subscribe(self.name, MessageType.SCHEDULE_GAMES, self._handle_schedule_games)
            self.message_bus.subscribe(self.name, MessageType.SYSTEM_SHUTDOWN, self._handle_shutdown_message)

            # Send ready status
            ready_message = MessageBuilder.system_status(
                sender=self.name,
                status="ready",
                details={
                    "component": "games_thread",
                    "capabilities": ["game_monitoring", "fixture_tracking"]
                }
            )
            self.message_bus.publish(ready_message)

            logger.info("GamesThread initialized successfully")
            return True

        except Exception as e:
            logger.error(f"Failed to initialize GamesThread: {e}")
            return False

    def run(self):
        """Main run loop for the games thread"""
        logger.info("GamesThread started")

        try:
            while self.running and not self._shutdown_event.is_set():
                try:
                    # Process any pending messages
                    message = self.message_bus.get_message(self.name, timeout=0.1)
                    if message:
                        self._process_message(message)

                    # If a game is active, perform game-related operations
                    if self.game_active and self.current_fixture_id:
                        self._monitor_game_state()

                    # Update heartbeat
                    self.heartbeat()

                    # Sleep for 0.1 seconds as requested
                    time.sleep(0.1)

                except Exception as e:
                    logger.error(f"GamesThread run loop error: {e}")
                    time.sleep(1.0)  # Longer sleep on error

        except Exception as e:
            logger.error(f"GamesThread run failed: {e}")
        finally:
            self._cleanup()
            logger.info("GamesThread ended")

    def shutdown(self):
        """Shutdown the games thread"""
        logger.info("GamesThread shutdown requested")
        self._shutdown_event.set()
        self.game_active = False

    def _handle_start_game(self, message: Message):
        """Handle START_GAME message with comprehensive logic"""
        try:
            logger.info(f"Processing START_GAME message from {message.sender}")

            fixture_id = message.data.get("fixture_id")

            if fixture_id:
                # If fixture_id is provided, check if it's in terminal state
                if self._is_fixture_all_terminal(fixture_id):
                    logger.info(f"Fixture {fixture_id} is in terminal state - discarding START_GAME message")
                    self._send_response(message, "discarded", f"Fixture {fixture_id} is already completed")
                    return

                # Fixture is not terminal, activate it
                logger.info(f"Activating provided fixture: {fixture_id}")
                self._activate_fixture(fixture_id, message)
                return

            # No fixture_id provided - check today's fixtures
            if self._has_today_fixtures_all_terminal():
                logger.info("All today's fixtures are in terminal states - discarding START_GAME message")
                self._send_response(message, "discarded", "All today's fixtures are already completed")
                return

            # Step 2: Handle matches currently in "ingame" status
            ingame_handled = self._handle_ingame_matches(message)
            if ingame_handled:
                # Message was handled (either discarded or processed) - return
                return

            # Step 3: Check if there are active fixtures with today's date
            active_fixture = self._find_active_today_fixture()
            if active_fixture:
                logger.info(f"Found active fixture for today: {active_fixture}")
                self._activate_fixture(active_fixture, message)
                return

            # Step 4: No active fixtures found - initialize new fixture
            logger.info("No active fixtures found - initializing new fixture")
            new_fixture_id = self._initialize_new_fixture()
            if new_fixture_id:
                self._activate_fixture(new_fixture_id, message)
            else:
                logger.warning("Could not initialize new fixture")
                self._send_response(message, "error", "Could not initialize new fixture")

        except Exception as e:
            logger.error(f"Failed to handle START_GAME message: {e}")
            self._send_response(message, "error", str(e))

    def _handle_schedule_games(self, message: Message):
        """Handle SCHEDULE_GAMES message - change status of pending matches to scheduled"""
        try:
            fixture_id = message.data.get("fixture_id")

            if not fixture_id:
                # If no fixture_id provided, find the last fixture with pending matches
                fixture_id = self._find_last_fixture_with_pending_matches()

            if fixture_id:
                logger.info(f"Scheduling games for fixture: {fixture_id}")

                # Update status of all pending matches in the fixture to scheduled
                updated_count = self._schedule_fixture_matches(fixture_id)

                if updated_count > 0:
                    logger.info(f"Successfully scheduled {updated_count} matches for fixture {fixture_id}")

                    # Send success response
                    response = Message(
                        type=MessageType.GAME_STATUS,
                        sender=self.name,
                        recipient=message.sender,
                        data={
                            "status": "scheduled",
                            "fixture_id": fixture_id,
                            "matches_scheduled": updated_count,
                            "timestamp": time.time()
                        },
                        correlation_id=message.correlation_id
                    )
                    self.message_bus.publish(response)
                else:
                    logger.warning(f"No pending matches found to schedule for fixture {fixture_id}")

                    # Send response indicating no matches were scheduled
                    response = Message(
                        type=MessageType.GAME_STATUS,
                        sender=self.name,
                        recipient=message.sender,
                        data={
                            "status": "no_matches",
                            "fixture_id": fixture_id,
                            "message": "No pending matches found to schedule",
                            "timestamp": time.time()
                        },
                        correlation_id=message.correlation_id
                    )
                    self.message_bus.publish(response)
            else:
                logger.warning("No fixture with pending matches found")

                # Send error response
                error_response = Message(
                    type=MessageType.GAME_STATUS,
                    sender=self.name,
                    recipient=message.sender,
                    data={
                        "status": "error",
                        "error": "No fixture with pending matches found",
                        "timestamp": time.time()
                    },
                    correlation_id=message.correlation_id
                )
                self.message_bus.publish(error_response)

        except Exception as e:
            logger.error(f"Failed to handle SCHEDULE_GAMES message: {e}")

            # Send error response
            error_response = Message(
                type=MessageType.GAME_STATUS,
                sender=self.name,
                recipient=message.sender,
                data={
                    "status": "error",
                    "error": str(e),
                    "timestamp": time.time()
                },
                correlation_id=message.correlation_id
            )
            self.message_bus.publish(error_response)

    def _handle_shutdown_message(self, message: Message):
        """Handle shutdown message"""
        logger.info(f"Shutdown message received from {message.sender}")
        self._shutdown_event.set()
        self.game_active = False

    def _process_message(self, message: Message):
        """Process incoming messages"""
        try:
            logger.debug(f"GamesThread processing message: {message}")

            # Handle messages directly since broadcast messages don't trigger subscription handlers
            if message.type == MessageType.START_GAME:
                self._handle_start_game(message)
            elif message.type == MessageType.SCHEDULE_GAMES:
                self._handle_schedule_games(message)
            elif message.type == MessageType.SYSTEM_SHUTDOWN:
                self._handle_shutdown_message(message)
            elif message.type == MessageType.GAME_UPDATE:
                self._handle_game_update(message)

        except Exception as e:
            logger.error(f"Failed to process message: {e}")

    def _handle_game_update(self, message: Message):
        """Handle game update messages"""
        try:
            update_data = message.data
            logger.debug(f"Game update received: {update_data}")

            # Process game update data as needed
            # This could include updating match states, processing outcomes, etc.

        except Exception as e:
            logger.error(f"Failed to handle game update: {e}")

    def _find_last_fixture_with_pending_matches(self) -> Optional[str]:
        """Find the last fixture that has pending matches"""
        try:
            session = self.db_manager.get_session()
            try:
                # Query for matches with PENDING status
                pending_matches = session.query(MatchModel).filter(
                    MatchModel.status == 'pending',
                    MatchModel.active_status == True
                ).order_by(MatchModel.fixture_active_time.desc()).all()

                if pending_matches:
                    # Get the fixture_id from the most recent pending match
                    latest_match = pending_matches[0]
                    fixture_id = latest_match.fixture_id
                    logger.info(f"Found fixture with pending matches: {fixture_id} ({len(pending_matches)} matches)")
                    return fixture_id
                else:
                    logger.info("No pending matches found")
                    return None

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to find last fixture with pending matches: {e}")
            return None

    def _schedule_fixture_matches(self, fixture_id: str) -> int:
        """Update status of all pending matches in a fixture to scheduled"""
        try:
            session = self.db_manager.get_session()
            try:
                # Query for pending matches in the specified fixture
                pending_matches = session.query(MatchModel).filter(
                    MatchModel.fixture_id == fixture_id,
                    MatchModel.status == 'pending',
                    MatchModel.active_status == True
                ).all()

                updated_count = 0

                for match in pending_matches:
                    # Change status from PENDING to SCHEDULED
                    match.status = 'scheduled'
                    logger.debug(f"Scheduling match #{match.match_number}: {match.fighter1_township} vs {match.fighter2_township} - status changed to {match.status}")
                    updated_count += 1

                # Commit the changes
                session.commit()
                logger.info(f"Scheduled {updated_count} matches for fixture {fixture_id}")

                return updated_count

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to schedule matches for fixture {fixture_id}: {e}")
            return 0

    def _monitor_game_state(self):
        """Monitor the current game state"""
        try:
            if not self.current_fixture_id:
                return

            # Check if there are still pending or scheduled matches for this fixture
            session = self.db_manager.get_session()
            try:
                active_count = session.query(MatchModel).filter(
                    MatchModel.fixture_id == self.current_fixture_id,
                    MatchModel.status.in_(['pending', 'scheduled', 'bet', 'ingame']),
                    MatchModel.active_status == True
                ).count()

                if active_count == 0:
                    logger.info(f"All matches completed for fixture {self.current_fixture_id}")
                    self.game_active = False

                    # Send game completed message
                    completed_message = Message(
                        type=MessageType.GAME_STATUS,
                        sender=self.name,
                        data={
                            "status": "completed",
                            "fixture_id": self.current_fixture_id,
                            "timestamp": time.time()
                        }
                    )
                    self.message_bus.publish(completed_message)

                    # Reset current fixture
                    self.current_fixture_id = None

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to monitor game state: {e}")

    def _send_response(self, original_message: Message, status: str, message: str = None):
        """Send response message back to the sender"""
        try:
            response_data = {
                "status": status,
                "timestamp": time.time()
            }

            if message:
                response_data["message"] = message

            response = Message(
                type=MessageType.GAME_STATUS,
                sender=self.name,
                recipient=original_message.sender,
                data=response_data,
                correlation_id=original_message.correlation_id
            )
            self.message_bus.publish(response)

        except Exception as e:
            logger.error(f"Failed to send response: {e}")

    def _is_fixture_all_terminal(self, fixture_id: str) -> bool:
        """Check if all matches in a fixture are in terminal states (done, cancelled, failed, paused)"""
        try:
            session = self.db_manager.get_session()
            try:
                # Get all matches for this fixture
                matches = session.query(MatchModel).filter(
                    MatchModel.fixture_id == fixture_id,
                    MatchModel.active_status == True
                ).all()

                if not matches:
                    return False  # No matches means not terminal

                # Check if all matches are in terminal states
                terminal_states = ['done', 'cancelled', 'failed', 'paused']
                return all(match.status in terminal_states for match in matches)

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to check if fixture {fixture_id} is terminal: {e}")
            return False

    def _has_today_fixtures_all_terminal(self) -> bool:
        """Check if all fixtures with today's matches are in terminal states"""
        try:
            session = self.db_manager.get_session()
            try:
                # Get today's date
                today = datetime.now().date()

                # Find all fixtures that have matches with today's start_time
                fixtures_with_today_matches = session.query(MatchModel.fixture_id).filter(
                    MatchModel.start_time.isnot(None),
                    MatchModel.start_time >= datetime.combine(today, datetime.min.time()),
                    MatchModel.start_time < datetime.combine(today, datetime.max.time())
                ).distinct().all()

                if not fixtures_with_today_matches:
                    return False  # No today's fixtures

                # Check each fixture
                for fixture_row in fixtures_with_today_matches:
                    fixture_id = fixture_row.fixture_id
                    if not self._is_fixture_all_terminal(fixture_id):
                        return False  # Found a non-terminal fixture

                return True  # All fixtures are terminal

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to check today's fixtures terminal status: {e}")
            return False

    def _handle_ingame_matches(self, message: Message) -> bool:
        """Handle matches currently in 'ingame' status. Returns True if message was handled."""
        try:
            session = self.db_manager.get_session()
            try:
                # Get today's date
                today = datetime.now().date()

                # Find fixtures with ingame matches today
                ingame_matches = session.query(MatchModel).filter(
                    MatchModel.start_time.isnot(None),
                    MatchModel.start_time >= datetime.combine(today, datetime.min.time()),
                    MatchModel.start_time < datetime.combine(today, datetime.max.time()),
                    MatchModel.status == 'ingame',
                    MatchModel.active_status == True
                ).all()

                if not ingame_matches:
                    return False  # No ingame matches, continue processing

                # Get unique fixture IDs
                fixture_ids = list(set(match.fixture_id for match in ingame_matches))

                for fixture_id in fixture_ids:
                    # Check if timer is running for this fixture
                    # This is a simplified check - in real implementation you'd check the match_timer component
                    timer_running = self._is_timer_running_for_fixture(fixture_id)

                    if not timer_running:
                        # Timer not running, change status to failed
                        logger.info(f"Timer not running for fixture {fixture_id}, changing ingame matches to failed")
                        self._change_fixture_matches_status(fixture_id, 'ingame', 'failed')

                        # Check if this was the only non-terminal fixture
                        if self._is_only_non_terminal_fixture(fixture_id):
                            logger.info("This was the only non-terminal fixture - discarding START_GAME message")
                            self._send_response(message, "discarded", "Timer not running and no other active fixtures")
                            return True
                    else:
                        # Timer is running, check for other pending/bet/scheduled matches
                        other_active_matches = session.query(MatchModel).filter(
                            MatchModel.fixture_id == fixture_id,
                            MatchModel.status.in_(['pending', 'bet', 'scheduled']),
                            MatchModel.active_status == True
                        ).all()

                        if other_active_matches:
                            # Change first pending/bet/scheduled match to bet status
                            first_match = other_active_matches[0]
                            if first_match.status != 'bet':
                                logger.info(f"Changing match {first_match.match_number} status to bet")
                                first_match.status = 'bet'
                                session.commit()

                        # Timer is running, discard the message
                        logger.info(f"Timer running for fixture {fixture_id} - discarding START_GAME message")
                        self._send_response(message, "discarded", "Timer already running for active fixture")
                        return True

                return False  # Continue processing

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to handle ingame matches: {e}")
            return False

    def _is_timer_running_for_fixture(self, fixture_id: str) -> bool:
        """Check if timer is running for a specific fixture"""
        # This is a simplified implementation
        # In a real implementation, you'd check the match_timer component status
        return self.current_fixture_id == fixture_id and self.game_active

    def _change_fixture_matches_status(self, fixture_id: str, from_status: str, to_status: str):
        """Change status of matches in a fixture from one status to another"""
        try:
            session = self.db_manager.get_session()
            try:
                matches = session.query(MatchModel).filter(
                    MatchModel.fixture_id == fixture_id,
                    MatchModel.status == from_status,
                    MatchModel.active_status == True
                ).all()

                for match in matches:
                    logger.info(f"Changing match {match.match_number} status from {from_status} to {to_status}")
                    match.status = to_status

                session.commit()

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to change match statuses: {e}")

    def _is_only_non_terminal_fixture(self, fixture_id: str) -> bool:
        """Check if this is the only non-terminal fixture"""
        try:
            session = self.db_manager.get_session()
            try:
                # Get today's date
                today = datetime.now().date()

                # Find all fixtures with today's matches
                all_fixtures = session.query(MatchModel.fixture_id).filter(
                    MatchModel.start_time.isnot(None),
                    MatchModel.start_time >= datetime.combine(today, datetime.min.time()),
                    MatchModel.start_time < datetime.combine(today, datetime.max.time())
                ).distinct().all()

                # Check each fixture except the current one
                terminal_states = ['done', 'cancelled', 'failed', 'paused']
                non_terminal_count = 0

                for fixture_row in all_fixtures:
                    fid = fixture_row.fixture_id
                    if fid == fixture_id:
                        continue

                    # Check if this fixture has non-terminal matches
                    non_terminal_matches = session.query(MatchModel).filter(
                        MatchModel.fixture_id == fid,
                        MatchModel.status.notin_(terminal_states),
                        MatchModel.active_status == True
                    ).all()

                    if non_terminal_matches:
                        non_terminal_count += 1

                return non_terminal_count == 0

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to check if only non-terminal fixture: {e}")
            return False

    def _find_active_today_fixture(self) -> Optional[str]:
        """Find an active fixture with today's date"""
        try:
            session = self.db_manager.get_session()
            try:
                # Get today's date
                today = datetime.now().date()

                # Find fixtures with today's matches that are not in terminal states
                terminal_states = ['done', 'cancelled', 'failed', 'paused']

                active_matches = session.query(MatchModel).filter(
                    MatchModel.start_time.isnot(None),
                    MatchModel.start_time >= datetime.combine(today, datetime.min.time()),
                    MatchModel.start_time < datetime.combine(today, datetime.max.time()),
                    MatchModel.status.notin_(terminal_states),
                    MatchModel.active_status == True
                ).order_by(MatchModel.start_time.asc()).all()

                if active_matches:
                    return active_matches[0].fixture_id

                return None

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to find active today fixture: {e}")
            return None

    def _initialize_new_fixture(self) -> Optional[str]:
        """Initialize a new fixture by finding the first one with no start_time set"""
        try:
            session = self.db_manager.get_session()
            try:
                # Find the first fixture with no start_time set
                fixtures_no_start_time = session.query(MatchModel.fixture_id).filter(
                    MatchModel.start_time.is_(None),
                    MatchModel.active_status == True
                ).distinct().order_by(MatchModel.created_at.asc()).all()

                if not fixtures_no_start_time:
                    return None

                fixture_id = fixtures_no_start_time[0].fixture_id
                logger.info(f"Initializing new fixture: {fixture_id}")

                # Set start_time to now for all matches in this fixture
                now = datetime.utcnow()
                matches = session.query(MatchModel).filter(
                    MatchModel.fixture_id == fixture_id,
                    MatchModel.active_status == True
                ).all()

                for match in matches:
                    match.start_time = now
                    match.status = 'scheduled'
                    logger.debug(f"Set start_time for match {match.match_number}")

                session.commit()
                return fixture_id

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to initialize new fixture: {e}")
            return None

    def _activate_fixture(self, fixture_id: str, message: Message):
        """Activate a fixture and start the game"""
        try:
            logger.info(f"🎯 ACTIVATING FIXTURE: {fixture_id}")

            # Check if fixture is already active to prevent double activation
            if self.current_fixture_id == fixture_id and self.game_active:
                logger.warning(f"Fixture {fixture_id} is already active - ignoring duplicate activation")
                self._send_response(message, "already_active", f"Fixture {fixture_id} already active")
                return

            # Set current fixture
            self.current_fixture_id = fixture_id
            self.game_active = True

            # Step 1 & 2: Change match statuses in a single transaction
            logger.info(f"🔄 Starting match status changes for fixture {fixture_id}")
            self._schedule_and_apply_betting_logic(fixture_id)

            # Send game started confirmation
            logger.info(f"✅ Fixture {fixture_id} activated successfully")
            self._send_response(message, "started", f"Fixture {fixture_id} activated")

            # Start match timer
            logger.info(f"⏰ Starting match timer for fixture {fixture_id}")
            self._start_match_timer(fixture_id)

            # Dispatch START_INTRO message
            logger.info(f"🎬 Dispatching START_INTRO message for fixture {fixture_id}")
            self._dispatch_start_intro(fixture_id)

            # Refresh dashboard statuses
            self._refresh_dashboard_statuses()

        except Exception as e:
            logger.error(f"❌ Failed to activate fixture {fixture_id}: {e}")
            import traceback
            logger.error(f"Stack trace: {traceback.format_exc()}")
            self._send_response(message, "error", f"Failed to activate fixture: {str(e)}")

    def _schedule_and_apply_betting_logic(self, fixture_id: str):
        """Change match statuses in a single transaction: first to 'scheduled', then apply betting logic"""
        try:
            logger.info(f"🔄 Starting match status update for fixture {fixture_id}")
            
            # Get betting mode configuration from database (default to 'all_bets_on_start')
            betting_mode = self._get_betting_mode_config()
            logger.info(f"📋 Using betting mode: {betting_mode}")
            
            session = self.db_manager.get_session()
            try:
                # First, let's see what matches exist for this fixture
                all_matches = session.query(MatchModel).filter(
                    MatchModel.fixture_id == fixture_id,
                    MatchModel.active_status == True
                ).all()
                
                if not all_matches:
                    logger.warning(f"⚠️ No matches found for fixture {fixture_id}")
                    return
                
                logger.info(f"📊 Found {len(all_matches)} total matches in fixture {fixture_id}")
                for match in all_matches:
                    logger.info(f"  Match {match.match_number}: {match.fighter1_township} vs {match.fighter2_township} - Status: {match.status}")

                # Step 1: Change ALL matches in the fixture to 'scheduled' status first
                terminal_states = ['done', 'cancelled', 'failed', 'paused']
                matches = session.query(MatchModel).filter(
                    MatchModel.fixture_id == fixture_id,
                    MatchModel.status.notin_(terminal_states),
                    MatchModel.active_status == True
                ).all()

                logger.info(f"📋 Found {len(matches)} non-terminal matches to process")

                scheduled_count = 0
                for match in matches:
                    if match.status != 'scheduled':
                        logger.info(f"🔄 Changing match {match.match_number} status from '{match.status}' to 'scheduled'")
                        match.status = 'scheduled'
                        scheduled_count += 1
                    else:
                        logger.info(f"✅ Match {match.match_number} already scheduled")

                # Flush to make sure scheduled status is available for next step
                if scheduled_count > 0:
                    session.flush()
                    logger.info(f"✅ Scheduled {scheduled_count} matches in fixture {fixture_id}")
                else:
                    logger.info("📋 No matches needed scheduling")

                # Step 2: Apply betting logic based on configuration
                if betting_mode == 'all_bets_on_start':
                    logger.info("🎰 Applying 'all_bets_on_start' logic")
                    # Change ALL scheduled matches to 'bet' status
                    scheduled_matches = session.query(MatchModel).filter(
                        MatchModel.fixture_id == fixture_id,
                        MatchModel.status == 'scheduled',
                        MatchModel.active_status == True
                    ).all()

                    logger.info(f"📋 Found {len(scheduled_matches)} scheduled matches to change to 'bet'")

                    bet_count = 0
                    for match in scheduled_matches:
                        logger.info(f"🎰 Changing match {match.match_number} status to 'bet' (all bets on start)")
                        match.status = 'bet'
                        bet_count += 1

                    if bet_count > 0:
                        logger.info(f"✅ Changed {bet_count} matches to 'bet' status (all bets on start mode)")
                    else:
                        logger.warning("⚠️ No scheduled matches found to change to 'bet' status")

                else:  # 'one_bet_at_a_time'
                    logger.info("🎯 Applying 'one_bet_at_a_time' logic")
                    # Change only the FIRST scheduled match to 'bet' status
                    first_match = session.query(MatchModel).filter(
                        MatchModel.fixture_id == fixture_id,
                        MatchModel.status == 'scheduled',
                        MatchModel.active_status == True
                    ).order_by(MatchModel.match_number.asc()).first()

                    if first_match:
                        logger.info(f"🎯 Changing first match {first_match.match_number} status to 'bet' (one bet at a time)")
                        first_match.status = 'bet'
                    else:
                        logger.warning("⚠️ No scheduled match found to change to 'bet' status")

                # Commit all changes in a single transaction
                logger.info("💾 Committing database changes...")
                session.commit()
                logger.info(f"✅ Successfully updated match statuses for fixture {fixture_id} with betting mode: {betting_mode}")

                # Send notification to web dashboard about fixture status update
                try:
                    from .message_bus import Message, MessageType
                    status_update_message = Message(
                        type=MessageType.CUSTOM,
                        sender=self.name,
                        recipient="web_dashboard",
                        data={
                            "fixture_status_update": {
                                "fixture_id": fixture_id,
                                "betting_mode": betting_mode,
                                "timestamp": time.time()
                            }
                        }
                    )
                    self.message_bus.publish(status_update_message)
                    logger.info(f"📢 Broadcast fixture status update notification for {fixture_id}")
                except Exception as msg_e:
                    logger.warning(f"Failed to send fixture status update notification: {msg_e}")

                # Verify the changes were applied
                final_matches = session.query(MatchModel).filter(
                    MatchModel.fixture_id == fixture_id,
                    MatchModel.active_status == True
                ).all()
                
                logger.info(f"🔍 Final match statuses for fixture {fixture_id}:")
                for match in final_matches:
                    logger.info(f"  Match {match.match_number}: {match.status}")

            finally:
                session.close()

        except Exception as e:
            logger.error(f"❌ Failed to schedule and apply betting logic: {e}")
            import traceback
            logger.error(f"Stack trace: {traceback.format_exc()}")
            # Try to rollback in case of error
            try:
                if 'session' in locals():
                    session.rollback()
            except Exception as rollback_e:
                logger.error(f"Failed to rollback: {rollback_e}")

    def _get_betting_mode_config(self) -> str:
        """Get global betting mode configuration from game config (default: 'all_bets_on_start')"""
        try:
            session = self.db_manager.get_session()
            try:
                from ..database.models import GameConfigModel
                
                # Get global betting mode configuration from game_config table
                betting_mode_config = session.query(GameConfigModel).filter_by(
                    config_key='betting_mode'
                ).first()
                
                if betting_mode_config:
                    return betting_mode_config.get_typed_value()
                else:
                    # Default to 'all_bets_on_start' if no configuration found
                    logger.debug("No betting mode configuration found, using default: 'all_bets_on_start'")
                    return 'all_bets_on_start'

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to get betting mode config: {e}")
            # Default fallback
            return 'all_bets_on_start'

    def _refresh_dashboard_statuses(self):
        """Refresh dashboard statuses by sending update messages"""
        try:
            # Send refresh message to web dashboard
            refresh_message = Message(
                type=MessageType.GAME_STATUS,
                sender=self.name,
                data={
                    "action": "refresh",
                    "timestamp": time.time()
                }
            )
            self.message_bus.publish(refresh_message, broadcast=True)

        except Exception as e:
            logger.error(f"Failed to refresh dashboard statuses: {e}")

    def _start_match_timer(self, fixture_id: str):
        """Start the match timer for the fixture"""
        try:
            # Send message to match timer component
            timer_message = Message(
                type=MessageType.START_GAME,
                sender=self.name,
                recipient="match_timer",
                data={
                    "fixture_id": fixture_id,
                    "action": "start_timer",
                    "timestamp": time.time()
                }
            )
            self.message_bus.publish(timer_message)

            logger.info(f"Started match timer for fixture {fixture_id}")

        except Exception as e:
            logger.error(f"Failed to start match timer: {e}")

    def _dispatch_start_intro(self, fixture_id: str):
        """Dispatch START_INTRO message to trigger intro content"""
        try:
            from .message_bus import MessageBuilder

            # Find the first match that was set to 'bet' status
            first_bet_match_id = self._get_first_bet_match_id(fixture_id)

            # Unzip the ZIP file of the first match if it exists
            self._unzip_match_zip_file(first_bet_match_id)

            # Create and send START_INTRO message
            start_intro_message = MessageBuilder.start_intro(
                sender=self.name,
                fixture_id=fixture_id,
                match_id=first_bet_match_id
            )
            self.message_bus.publish(start_intro_message, broadcast=True)

            logger.info(f"START_INTRO message dispatched for fixture {fixture_id}, match {first_bet_match_id}")

        except Exception as e:
            logger.error(f"Failed to dispatch START_INTRO message: {e}")

    def _get_first_bet_match_id(self, fixture_id: str) -> Optional[int]:
        """Get the ID of the first match set to 'bet' status in the fixture"""
        try:
            session = self.db_manager.get_session()
            try:
                from ..database.models import MatchModel

                # Find the first match with 'bet' status in this fixture
                first_bet_match = session.query(MatchModel).filter(
                    MatchModel.fixture_id == fixture_id,
                    MatchModel.status == 'bet',
                    MatchModel.active_status == True
                ).order_by(MatchModel.match_number.asc()).first()

                if first_bet_match:
                    return first_bet_match.id
                else:
                    logger.warning(f"No match with 'bet' status found in fixture {fixture_id}")
                    return None

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to get first bet match ID for fixture {fixture_id}: {e}")
            return None

    def _unzip_match_zip_file(self, match_id: int):
        """Unzip the ZIP file associated with a match to a temporary directory"""
        try:
            import zipfile
            import tempfile
            import os
            from pathlib import Path

            session = self.db_manager.get_session()
            try:
                # Get the match from database
                match = session.query(MatchModel).filter_by(id=match_id).first()

                if not match:
                    logger.warning(f"Match {match_id} not found, skipping ZIP extraction")
                    return

                if not match.zip_filename:
                    logger.info(f"Match {match_id} has no associated ZIP file, skipping extraction")
                    return

                # Determine ZIP file location (ZIP files are stored in the zip_files directory)
                from ..config.settings import get_user_data_dir
                user_data_dir = get_user_data_dir()
                zip_file_path = user_data_dir / "zip_files" / match.zip_filename

                if not zip_file_path.exists():
                    logger.warning(f"ZIP file not found: {zip_file_path}")
                    return

                # Create temporary directory for extraction
                temp_dir = Path(tempfile.mkdtemp(prefix=f"match_{match_id}_"))
                logger.info(f"Extracting ZIP file {zip_file_path} to temporary directory: {temp_dir}")

                # Extract the ZIP file
                with zipfile.ZipFile(str(zip_file_path), 'r') as zip_ref:
                    zip_ref.extractall(str(temp_dir))

                # Log extraction results
                extracted_files = list(temp_dir.rglob("*"))
                logger.info(f"Successfully extracted {len(extracted_files)} files from {match.zip_filename}")

                # Store the temporary directory path for potential cleanup
                # In a real implementation, you might want to track this for cleanup
                match.temp_extract_path = str(temp_dir)

                # Update match in database with temp path (optional)
                session.commit()

                logger.info(f"ZIP extraction completed for match {match_id}")

            finally:
                session.close()

        except Exception as e:
            logger.error(f"Failed to unzip ZIP file for match {match_id}: {e}")

    def _cleanup(self):
        """Perform cleanup operations"""
        try:
            logger.info("GamesThread performing cleanup...")

            # Reset state
            self.game_active = False
            self.current_fixture_id = None

            # Send final status
            final_status = MessageBuilder.system_status(
                sender=self.name,
                status="shutdown",
                details={
                    "component": "games_thread",
                    "cleanup_completed": True
                }
            )
            self.message_bus.publish(final_status)

            logger.info("GamesThread cleanup completed")

        except Exception as e:
            logger.error(f"GamesThread cleanup error: {e}")