"""
Shared services component for UI Router.

This module contains SharedServices - a dataclass that groups shared components
that are reused across multiple UIRouter instances.
"""

from collections.abc import Awaitable, Callable
import time
from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Protocol

from aiogram import Bot

from ui_router.events import EventBus, EventScheduler
from ui_router.state.storage import NavigationStorage
from ui_router.state.variables import VariableRepository

if TYPE_CHECKING:
    from ui_router.analytics import AnalyticsCollector


class CacheStorageProtocol(Protocol):
    """Protocol for cache storage implementations."""

    async def get(self, key: str) -> Any | None:
        """Get value from cache."""
        ...

    async def set(self, key: str, value: Any, ttl: int | None = None) -> None:
        """Set value in cache."""
        ...

    async def delete(self, key: str) -> None:
        """Delete value from cache."""
        ...


@dataclass
class SharedServices:
    """
    Shared components between multiple UIRouter instances.

    These services are used jointly by several routers to provide common state
    and coordination. They handle cross-cutting concerns like navigation state,
    variables, events, and caching.

    Attributes:
        navigation_storage: Storage for navigation state (required).
        variable_repository: Repository for managing bot variables (required).
        event_bus: Event bus for pub/sub pattern (required).
        event_scheduler: Scheduler for delayed/scheduled events (required).
        cache_storage: Optional cache storage for performance optimization.
        bot_resolver: Optional function to resolve Bot instance from bot_id
            at runtime. Signature: (bot_id: int | str) -> Awaitable[Bot].
        analytics_collector: Optional analytics collector for tracking events.
    """

    navigation_storage: NavigationStorage
    variable_repository: VariableRepository
    event_bus: EventBus
    event_scheduler: EventScheduler
    cache_storage: CacheStorageProtocol | None = None
    bot_resolver: Callable[[int | str], Awaitable[Bot]] | None = None
    analytics_collector: "AnalyticsCollector | None" = None
    enable_structlog: bool = False


class InMemoryCacheStorage:
    """Простая in-memory реализация CacheStorageProtocol с TTL."""

    def __init__(self) -> None:
        self._data: dict[str, tuple[Any, float | None]] = {}

    async def get(self, key: str) -> Any | None:
        entry = self._data.get(key)
        if entry is None:
            return None
        value, expires_at = entry
        if expires_at is not None and time.monotonic() > expires_at:
            del self._data[key]
            return None
        return value

    async def set(self, key: str, value: Any, ttl: int | None = None) -> None:
        expires_at = (time.monotonic() + ttl) if ttl else None
        self._data[key] = (value, expires_at)

    async def delete(self, key: str) -> None:
        self._data.pop(key, None)
