"""
Storage abstraction for Mothership
"""
from typing import Optional, Dict, Any, List, Generic, TypeVar
from abc import ABC, abstractmethod
from .types import StorageFilter
from .firebase import FirebaseClient

T = TypeVar("T")


class StorageAdapter(ABC, Generic[T]):
    """Abstract storage adapter interface"""

    @abstractmethod
    async def get(self, key: str) -> Optional[T]:
        """Get item by key"""
        pass

    @abstractmethod
    async def save(self, key: str, data: T) -> None:
        """Save/update item"""
        pass

    @abstractmethod
    async def delete(self, key: str) -> None:
        """Delete item by key"""
        pass

    @abstractmethod
    async def query(self, filters: List[StorageFilter]) -> List[T]:
        """Query items with filters"""
        pass

    @abstractmethod
    async def get_all(self) -> List[T]:
        """Get all items"""
        pass

    @abstractmethod
    async def clear(self) -> None:
        """Clear all items"""
        pass


class InMemoryStorageAdapter(StorageAdapter[T]):
    """In-memory storage adapter (for development/testing)"""

    def __init__(self, bot_name: str):
        """
        Initialize in-memory storage

        Args:
            bot_name: Name of the bot
        """
        self.bot_name = bot_name
        self.data: Dict[str, T] = {}

    async def get(self, key: str) -> Optional[T]:
        """Get item by key"""
        return self.data.get(key)

    async def save(self, key: str, data: T) -> None:
        """Save/update item"""
        self.data[key] = data

    async def delete(self, key: str) -> None:
        """Delete item by key"""
        if key in self.data:
            del self.data[key]

    async def query(self, filters: List[StorageFilter]) -> List[T]:
        """Query items with filters"""
        results = list(self.data.values())

        # Apply filters
        for f in filters:
            field = f["field"]
            operator = f["operator"]
            value = f["value"]

            filtered = []
            for item in results:
                if not isinstance(item, dict):
                    continue

                item_value = item.get(field)

                # Apply operator
                match = False
                if operator == "==":
                    match = item_value == value
                elif operator == "!=":
                    match = item_value != value
                elif operator == ">":
                    match = item_value is not None and item_value > value
                elif operator == ">=":
                    match = item_value is not None and item_value >= value
                elif operator == "<":
                    match = item_value is not None and item_value < value
                elif operator == "<=":
                    match = item_value is not None and item_value <= value
                elif operator == "array-contains":
                    match = isinstance(item_value, list) and value in item_value
                elif operator == "in":
                    match = item_value in value if isinstance(value, list) else False
                elif operator == "array-contains-any":
                    match = (
                        isinstance(item_value, list)
                        and isinstance(value, list)
                        and any(v in item_value for v in value)
                    )

                if match:
                    filtered.append(item)

            results = filtered

        return results

    async def get_all(self) -> List[T]:
        """Get all items"""
        return list(self.data.values())

    async def clear(self) -> None:
        """Clear all items"""
        self.data.clear()


class FirebaseStorageAdapter(StorageAdapter[T]):
    """Firebase/Firestore storage adapter"""

    def __init__(self, bot_name: str):
        """
        Initialize Firebase storage

        Args:
            bot_name: Name of the bot

        Raises:
            RuntimeError: If Firebase not initialized
        """
        self.bot_name = bot_name
        self.firebase = FirebaseClient.get_instance()

    async def get(self, key: str) -> Optional[T]:
        """Get item by key"""
        return await self.firebase.get_bot_data(self.bot_name, key)

    async def save(self, key: str, data: T) -> None:
        """Save/update item"""
        if not isinstance(data, dict):
            raise ValueError("Data must be a dictionary for Firebase storage")
        await self.firebase.save_bot_data(self.bot_name, key, data)

    async def delete(self, key: str) -> None:
        """Delete item by key"""
        await self.firebase.delete_bot_data(self.bot_name, key)

    async def query(self, filters: List[StorageFilter]) -> List[T]:
        """Query items with filters"""
        return await self.firebase.query_bot_data(self.bot_name, filters)

    async def get_all(self) -> List[T]:
        """Get all items"""
        return await self.query([])

    async def clear(self) -> None:
        """Clear all items"""
        await self.firebase.delete_all_bot_data(self.bot_name)


class StorageClient:
    """Storage client with automatic adapter selection"""

    @staticmethod
    def _create_adapter(bot_name: str) -> StorageAdapter:
        """
        Create storage adapter (Firebase if initialized, otherwise in-memory)

        Args:
            bot_name: Name of the bot

        Returns:
            Storage adapter instance
        """
        if FirebaseClient.is_initialized():
            return FirebaseStorageAdapter(bot_name)
        return InMemoryStorageAdapter(bot_name)

    @staticmethod
    async def get(bot_name: str, key: str) -> Optional[Dict[str, Any]]:
        """
        Get item by key

        Args:
            bot_name: Name of the bot
            key: Item key

        Returns:
            Item data or None
        """
        adapter = StorageClient._create_adapter(bot_name)
        return await adapter.get(key)

    @staticmethod
    async def save(bot_name: str, key: str, data: Dict[str, Any]) -> None:
        """
        Save/update item

        Args:
            bot_name: Name of the bot
            key: Item key
            data: Item data
        """
        adapter = StorageClient._create_adapter(bot_name)
        await adapter.save(key, data)

    @staticmethod
    async def delete(bot_name: str, key: str) -> None:
        """
        Delete item by key

        Args:
            bot_name: Name of the bot
            key: Item key
        """
        adapter = StorageClient._create_adapter(bot_name)
        await adapter.delete(key)

    @staticmethod
    async def query(bot_name: str, filters: List[StorageFilter]) -> List[Dict[str, Any]]:
        """
        Query items with filters

        Args:
            bot_name: Name of the bot
            filters: List of query filters

        Returns:
            List of matching items
        """
        adapter = StorageClient._create_adapter(bot_name)
        return await adapter.query(filters)

    @staticmethod
    async def get_all(bot_name: str) -> List[Dict[str, Any]]:
        """
        Get all items

        Args:
            bot_name: Name of the bot

        Returns:
            List of all items
        """
        adapter = StorageClient._create_adapter(bot_name)
        return await adapter.get_all()

    @staticmethod
    async def clear(bot_name: str) -> None:
        """
        Clear all items

        Args:
            bot_name: Name of the bot
        """
        adapter = StorageClient._create_adapter(bot_name)
        await adapter.clear()

    @staticmethod
    def for_bot(bot_name: str) -> "BotStorage":
        """
        Create bot-scoped storage instance

        Args:
            bot_name: Name of the bot

        Returns:
            BotStorage instance
        """
        return BotStorage(bot_name)


class BotStorage:
    """Bot-scoped storage wrapper for easier API"""

    def __init__(self, bot_name: str):
        """
        Initialize bot storage

        Args:
            bot_name: Name of the bot
        """
        self.bot_name = bot_name
        self.adapter = StorageClient._create_adapter(bot_name)

    async def get(self, key: str) -> Optional[Dict[str, Any]]:
        """Get item by key"""
        return await self.adapter.get(key)

    async def save(self, key: str, data: Dict[str, Any]) -> None:
        """Save/update item"""
        await self.adapter.save(key, data)

    async def delete(self, key: str) -> None:
        """Delete item by key"""
        await self.adapter.delete(key)

    async def query(self, filters: List[StorageFilter]) -> List[Dict[str, Any]]:
        """Query items with filters"""
        return await self.adapter.query(filters)

    async def get_all(self) -> List[Dict[str, Any]]:
        """Get all items"""
        return await self.adapter.get_all()

    async def clear(self) -> None:
        """Clear all items"""
        await self.adapter.clear()
