from typing import Any, Awaitable, Callable, Dict, Tuple
from functools import partial

from mcp import types as mcp_types

from ..errors import MetaApiError
from ..logging import get_logger
from ..meta_client import MetaClient
from ..schemas import GraphRequest, ToolResult

logger = get_logger(__name__)

ToolHandler = Callable[[Dict[str, Any]], Awaitable[ToolResult]]

def _tool_schema(model: Any) -> Dict[str, Any]:
    """Helper to convert Pydantic model to tool schema."""
    return model.model_json_schema()

async def graph_request_handler(client: MetaClient, arguments: Dict[str, Any]) -> ToolResult:
    payload = GraphRequest.model_validate(arguments)
    try:
        response = await client.request(
            payload.method.value,
            payload.path,
            params=payload.params,
            body=payload.body,
            encoding=payload.encoding,
            files=payload.files,
            headers=payload.headers,
            use_appsecret_proof=payload.use_appsecret_proof,
        )
        return ToolResult(ok=True, data=response)
    except MetaApiError as exc:
        logger.error("tool_graph_request_failed", **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())

def get_tools(client: MetaClient) -> Dict[str, Tuple[mcp_types.Tool, ToolHandler]]:
    return {
        "meta.graph.request": (
            mcp_types.Tool(
                name="meta.graph.request",
                description="Make a direct request to the Meta Graph API for any endpoint. Supports GET, POST, DELETE methods with full parameter control. Use for advanced API access not covered by other tools.",
                inputSchema=GraphRequest.model_json_schema(),
            ),
            partial(graph_request_handler, client),
        )
    }
