"""Tools resource -- search, execute, and lookup tools."""

from __future__ import annotations

from typing import Any
from uuid import UUID

from mcpgateway_sdk._http import HTTPClient
from mcpgateway_sdk.models.tool import ToolExecuteResult, ToolLookup, ToolSearchResult

_ENDPOINTS = {
    "get_by_name": ("GET", "/api/v1/tools/by-name"),
    "search": ("POST", "/api/v1/tools/search"),
    "execute": ("POST", "/api/v1/tools/execute"),
}


class ToolsResource:
    """Interact with tools registered on the MCP Gateway."""

    _endpoints = _ENDPOINTS

    def __init__(self, http: HTTPClient) -> None:
        self._http = http

    async def get_by_name(self, server_name: str, tool_name: str) -> ToolLookup:
        """Resolve a tool by its exact name on a specific server.

        Args:
            server_name: The name of the server that hosts the tool.
            tool_name: The registered name of the tool.

        Returns:
            A ToolLookup with the tool metadata and input schema.
        """
        data = await self._http.request(
            "GET",
            "/api/v1/tools/by-name",
            params={"server_name": server_name, "tool_name": tool_name},
        )
        return ToolLookup.model_validate(data)

    async def search(self, query: str, limit: int = 5) -> list[ToolSearchResult]:
        """Semantic search for tools matching a natural-language query.

        Args:
            query: Natural-language description of the desired capability.
            limit: Maximum number of results to return (default 5).

        Returns:
            A list of ToolSearchResult sorted by relevance score.
        """
        data = await self._http.request(
            "POST", "/api/v1/tools/search", json={"query": query, "limit": limit}
        )
        return [ToolSearchResult.model_validate(r) for r in data.get("tools", [])]

    async def execute(
        self,
        tool_name: str,
        arguments: dict[str, Any] | None = None,
        *,
        server_id: str | UUID | None = None,
        server_name: str | None = None,
    ) -> ToolExecuteResult:
        """Execute a tool on the gateway.

        Exactly one of ``server_id`` or ``server_name`` must be provided so the
        gateway knows which server hosts the tool.

        Args:
            tool_name: Name of the tool to execute.
            arguments: Input arguments for the tool. Defaults to empty dict.
            server_id: UUID of the server that hosts the tool.
            server_name: Name of the server that hosts the tool.

        Returns:
            A ToolExecuteResult with the output and execution metadata.

        Raises:
            ValueError: If both or neither of server_id/server_name are given.
        """
        if server_id is not None and server_name is not None:
            raise ValueError("Provide exactly one of server_id or server_name, not both")
        if server_id is None and server_name is None:
            raise ValueError("Provide exactly one of server_id or server_name")

        body: dict[str, Any] = {
            "tool_name": tool_name,
            "arguments": arguments or {},
        }
        if server_id is not None:
            body["server_id"] = str(server_id)
        if server_name is not None:
            body["server_name"] = server_name

        data = await self._http.request(
            "POST",
            "/api/v1/tools/execute",
            json=body,
        )
        return ToolExecuteResult.model_validate(data)
