"""
Wykonuje wywołania narzędzi na backendowych serwerach MCP.

Odpowiedzialność:
- Przyjmuje ToolMapping z Registry i argumenty wywołania
- Pobiera sesję z ConnectionPool
- Wykonuje call_tool i list_tools przez MCP ClientSession
- Zwraca surowy wynik — nie przetwarza ani nie transformuje danych
- Udostępnia metody: call_tool(mapping, args) -> result, list_tools(backend) -> list[Tool]
- Nie zna publicznych nazw narzędzi — operuje na oryginalnych nazwach z backendu
"""

from typing import Any

from mcp.types import CallToolResult, ReadResourceResult, Resource, ResourceTemplate, Tool
from pydantic import AnyUrl

from .connection_pool import ConnectionPool
from .models import Backend, ResourceMapping, ToolMapping


class Executor:
    def __init__(self, pool: ConnectionPool):
        self._pool = pool

    async def call_tool(self, mapping: ToolMapping, args: dict[str, Any] | None = None) -> CallToolResult:
        session = await self._pool.get(mapping.backend.id, mapping.backend.url)
        return await session.call_tool(mapping.original_name, args)

    async def list_tools(self, backend: Backend) -> list[Tool]:
        session = await self._pool.get(backend.id, backend.url)
        result = await session.list_tools()
        return result.tools

    async def list_resources(self, backend: Backend) -> list[Resource]:
        session = await self._pool.get(backend.id, backend.url)
        result = await session.list_resources()
        return result.resources

    async def list_resource_templates(self, backend: Backend) -> list[ResourceTemplate]:
        session = await self._pool.get(backend.id, backend.url)
        result = await session.list_resource_templates()
        return result.resourceTemplates

    async def read_resource(self, mapping: ResourceMapping) -> ReadResourceResult:
        session = await self._pool.get(mapping.backend.id, mapping.backend.url)
        return await session.read_resource(AnyUrl(mapping.original_uri))

    async def read_resource_uri(self, backend: Backend, uri: str) -> ReadResourceResult:
        """Read by raw URI — for resources resolved via a template (where
        we don't have a `ResourceMapping` to dispatch through)."""
        session = await self._pool.get(backend.id, backend.url)
        return await session.read_resource(AnyUrl(uri))

    async def subscribe_resource(self, backend: Backend, uri: str) -> None:
        session = await self._pool.get(backend.id, backend.url)
        await session.subscribe_resource(AnyUrl(uri))

    async def unsubscribe_resource(self, backend: Backend, uri: str) -> None:
        session = await self._pool.get(backend.id, backend.url)
        await session.unsubscribe_resource(AnyUrl(uri))
