"""
Tool routing: local IndexedDB reads with official Linear MCP fallback/writes.
"""

from __future__ import annotations

import logging
from typing import Any

from . import local_handlers
from .official_session import OfficialMcpSessionManager
from .reader import LinearLocalReader

logger = logging.getLogger(__name__)


class ToolRouter:
    """Routes read calls through local cache first, falling back to official MCP."""

    def __init__(
        self,
        reader: LinearLocalReader,
        official: OfficialMcpSessionManager,
    ):
        self._reader = reader
        self._official = official

    def _call_local(
        self,
        tool_name: str,
        arguments: dict[str, Any],
    ) -> Any:
        handler = local_handlers.LOCAL_READ_HANDLERS.get(tool_name)
        if handler is None:
            raise local_handlers.LocalFallbackRequested(
                "unsupported_tool", f"tool '{tool_name}' not implemented in local cache"
            )
        return handler(self._reader, **arguments)

    def call_official(self, tool_name: str, arguments: dict[str, Any] | None = None) -> Any:
        """Call official MCP directly (used for writes and explicit fallback)."""
        return self._official.call_tool(tool_name, arguments or {})

    def call_read(self, tool_name: str, arguments: dict[str, Any] | None = None) -> Any:
        """Read with local-first strategy and narrow official fallback conditions."""
        args = arguments or {}
        try:
            self._reader.refresh_cache()
        except Exception as exc:
            # Refresh failures should not immediately force official fallback when
            # stale local cache is still usable.
            logger.warning("Local cache refresh failed; continuing with existing cache: %s", exc)

        if not self._reader.has_cached_data():
            return self.call_official(tool_name, args)

        try:
            return self._call_local(tool_name, args)
        except local_handlers.LocalFallbackRequested:
            return self.call_official(tool_name, args)
