"""
REST API do wywoływania narzędzi poza Claude'em.

Odpowiedzialność:
- Udostępnia endpointy HTTP (Starlette) do wywołania dowolnego narzędzia
- POST /tools/{tool_name} — wywołuje narzędzie z podanymi argumentami
- GET /tools — zwraca listę dostępnych narzędzi
- Używa tej samej ścieżki co Gateway: Registry -> Executor
- Nie duplikuje logiki — deleguje do tych samych komponentów co Gateway
- Opcjonalnie: autoryzacja przez API key (nagłówek X-API-Key)
"""

import logging

from starlette.applications import Starlette
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.routing import Route

from .executor import Executor
from .registry import Registry

logger = logging.getLogger(__name__)


class RestApi:
    def __init__(self, registry: Registry, executor: Executor, api_key: str | None = None):
        self._registry = registry
        self._executor = executor
        self._api_key = api_key

    def _authorized(self, request: Request) -> bool:
        if self._api_key is None:
            return True
        return request.headers.get("X-API-Key") == self._api_key

    async def list_tools(self, request: Request) -> JSONResponse:
        if not self._authorized(request):
            return JSONResponse({"error": "Unauthorized"}, status_code=401)
        return JSONResponse([
            {
                "name": m.public_name,
                "description": m.definition.description,
                "input_schema": m.definition.input_schema,
            }
            for m in self._registry.list_tools()
        ])

    async def call_tool(self, request: Request) -> JSONResponse:
        if not self._authorized(request):
            return JSONResponse({"error": "Unauthorized"}, status_code=401)

        tool_name = request.path_params["tool_name"]

        try:
            mapping = self._registry.resolve(tool_name)
        except KeyError:
            return JSONResponse({"error": f"Unknown tool: {tool_name}"}, status_code=404)

        try:
            args = await request.json()
        except Exception:
            args = {}

        try:
            result = await self._executor.call_tool(mapping, args)
        except Exception as e:
            logger.error("Tool call failed for %s: %s", tool_name, e)
            return JSONResponse({"error": str(e), "isError": True}, status_code=500)

        return JSONResponse({
            "isError": result.isError,
            "content": [c.model_dump() for c in result.content],
        })

    def create_app(self) -> Starlette:
        return Starlette(routes=[
            Route("/tools", self.list_tools, methods=["GET"]),
            Route("/tools/{tool_name}", self.call_tool, methods=["POST"]),
        ])
