"""
Navigation storage Protocol and implementations
"""

from typing import Protocol, runtime_checkable
from .context import NavigationState


@runtime_checkable
class NavigationStorage(Protocol):
    """Protocol for navigation state storage with optional prefix for router isolation"""

    async def get_state(
        self,
        bot_id: int | str,
        user_id: int,
        chat_id: int,
        prefix: str | None = None,
    ) -> NavigationState | None:
        """
        Get navigation state for user

        Args:
            bot_id: Bot identifier
            user_id: User ID
            chat_id: Chat ID
            prefix: Optional prefix for router isolation (router1, router2, etc)

        Returns:
            NavigationState or None if not found
        """
        ...

    async def save_state(
        self,
        bot_id: int | str,
        user_id: int,
        chat_id: int,
        state: NavigationState,
        prefix: str | None = None,
    ) -> None:
        """
        Save navigation state for user

        Args:
            bot_id: Bot identifier
            user_id: User ID
            chat_id: Chat ID
            state: Navigation state to save
            prefix: Optional prefix for router isolation (router1, router2, etc)
        """
        ...

    async def delete_state(
        self,
        bot_id: int | str,
        user_id: int,
        chat_id: int,
        prefix: str | None = None,
    ) -> None:
        """
        Delete navigation state for user

        Args:
            bot_id: Bot identifier
            user_id: User ID
            chat_id: Chat ID
            prefix: Optional prefix for router isolation (router1, router2, etc)
        """
        ...


class InMemoryNavigationStorage:
    """In-memory implementation of NavigationStorage with prefix support for router isolation"""

    def __init__(self, prefix: str | None = None) -> None:
        """
        Initialize in-memory storage

        Args:
            prefix: Optional prefix for router isolation (router1, router2, etc)
        """
        self._storage: dict[str, NavigationState] = {}
        self.prefix = prefix

    def _make_key(
        self,
        bot_id: int | str,
        user_id: int,
        chat_id: int,
        prefix: str | None = None,
    ) -> str:
        """
        Generate storage key with optional prefix

        Args:
            bot_id: Bot identifier
            user_id: User ID
            chat_id: Chat ID
            prefix: Optional prefix for router isolation

        Returns:
            Storage key in format: {prefix}:{bot_id}:{user_id}:{chat_id} or {bot_id}:{user_id}:{chat_id}
        """
        if prefix:
            return f"{prefix}:{bot_id}:{user_id}:{chat_id}"
        return f"{bot_id}:{user_id}:{chat_id}"

    async def get_state(
        self,
        bot_id: int | str,
        user_id: int,
        chat_id: int,
        prefix: str | None = None,
    ) -> NavigationState | None:
        """
        Get navigation state

        Args:
            bot_id: Bot identifier
            user_id: User ID
            chat_id: Chat ID
            prefix: Optional prefix for router isolation

        Returns:
            NavigationState or None if not found
        """
        key = self._make_key(bot_id, user_id, chat_id, prefix or self.prefix)
        return self._storage.get(key)

    async def save_state(
        self,
        bot_id: int | str,
        user_id: int,
        chat_id: int,
        state: NavigationState,
        prefix: str | None = None,
    ) -> None:
        """
        Save navigation state

        Args:
            bot_id: Bot identifier
            user_id: User ID
            chat_id: Chat ID
            state: Navigation state to save
            prefix: Optional prefix for router isolation
        """
        key = self._make_key(bot_id, user_id, chat_id, prefix or self.prefix)
        self._storage[key] = state

    async def delete_state(
        self,
        bot_id: int | str,
        user_id: int,
        chat_id: int,
        prefix: str | None = None,
    ) -> None:
        """
        Delete navigation state

        Args:
            bot_id: Bot identifier
            user_id: User ID
            chat_id: Chat ID
            prefix: Optional prefix for router isolation
        """
        key = self._make_key(bot_id, user_id, chat_id, prefix or self.prefix)
        self._storage.pop(key, None)
