"""
Storage abstraction layer for BaoLife.

Provides an interface for game storage operations, allowing switching
between MySQL (production) and in-memory (testing) storage backends.
"""
import os
from typing import Protocol, Optional, List, Tuple, Any


class IGameStorage(Protocol):
    """
    Interface for game storage operations.

    Defines the contract that all storage implementations must follow.
    """

    def save_game(self, player) -> bool:
        """Save a game."""
        ...

    def load_game(self, user_id: str):
        """Load a game by user ID."""
        ...

    def load_games(self) -> List[Tuple]:
        """Load all games."""
        ...

    def game_exists(self, user_id: str) -> bool:
        """Check if a game exists."""
        ...


class MySQLStorage:
    """
    MySQL storage implementation (production).

    Wraps existing saveGame()/loadGame() functions for compatibility.
    """

    def __init__(self):
        """Initialize MySQL storage."""
        pass

    def save_game(self, player) -> bool:
        """
        Save a game to MySQL database.

        Args:
            player: The player object to save

        Returns:
            True if successful, False otherwise
        """
        from functions import saveGame
        try:
            return saveGame(player)
        except Exception as e:
            print(f"Error saving game to MySQL: {e}")
            return False

    def load_game(self, user_id: str):
        """
        Load a game from MySQL database.

        Args:
            user_id: The user ID to load

        Returns:
            Player object if found, None otherwise
        """
        from functions import loadGame
        try:
            return loadGame(user_id)
        except Exception as e:
            print(f"Error loading game from MySQL: {e}")
            return None

    def load_games(self) -> List[Tuple]:
        """
        Load all games from MySQL database.

        Returns:
            List of (user_id,) tuples
        """
        from functions import loadGames
        try:
            return loadGames()
        except Exception as e:
            print(f"Error loading games from MySQL: {e}")
            return []

    def game_exists(self, user_id: str) -> bool:
        """
        Check if a game exists in MySQL database.

        Args:
            user_id: User ID to check

        Returns:
            True if game exists, False otherwise
        """
        try:
            game = self.load_game(user_id)
            return game is not None
        except Exception:
            return False

    def __repr__(self):
        return "MySQLStorage()"


def storage_factory(test_mode: Optional[bool] = None) -> IGameStorage:
    """
    Factory function to create appropriate storage backend.

    Args:
        test_mode: Force test mode (True) or production mode (False).
                  If None, uses BAOLIFE_TEST_MODE environment variable.

    Returns:
        Storage implementation (MySQLStorage or InMemoryStorage)
    """
    # Determine test mode
    if test_mode is None:
        test_mode = os.environ.get('BAOLIFE_TEST_MODE', 'false').lower() == 'true'

    if test_mode:
        # Import here to avoid circular dependencies
        from tests.mocks.storage_mock import InMemoryStorage
        return InMemoryStorage()
    else:
        return MySQLStorage()


def get_storage() -> IGameStorage:
    """
    Get the current storage backend.

    Uses environment variables to determine whether to use
    test or production storage.

    Returns:
        Storage implementation
    """
    return storage_factory()
