from __future__ import annotations

import os
from typing import Any, Optional

from .context import Context
from .tool_runtime_utils import JsonObject
from .tools.base import ToolResult


class MCPAdapter:
    """Experimental MCP integration adapter.

    Kept out of Oturn core loop so it can be disabled/removed independently.
    """

    def __init__(self, enabled: Optional[bool] = None) -> None:
        self.enabled = (
            bool(enabled)
            if enabled is not None
            else os.getenv("ENABLE_MCP", "").strip().lower() in {"1", "true", "yes", "on"}
        )

    def merge_tool_schemas(self, ctx: Context, local_schemas: list[dict[str, Any]]) -> list[dict[str, Any]]:
        if not self.enabled:
            return local_schemas
        remote_schemas: list[dict[str, Any]] = []
        availability = ctx.get_mcp_tool_availability()
        for tool in ctx.get_mcp_tool_schemas().values():
            name = tool.get("name")
            if not name:
                continue
            if not availability.get(name):
                continue
            remote_schemas.append(
                {
                    "type": "function",
                    "function": {
                        "name": name,
                        "description": tool.get("description") or "",
                        "parameters": tool.get("inputSchema") or {"type": "object"},
                    },
                }
            )
        if remote_schemas:
            return local_schemas + remote_schemas
        return local_schemas

    async def execute_remote_tool(self, ctx: Context, name: str, args: JsonObject) -> ToolResult:
        if not self.enabled:
            return ToolResult(
                status="failure",
                error="MCP disabled (experimental; set ENABLE_MCP=1 to enable)",
                metadata={"tool": name, "remote": True},
            )

        client = ctx.get_mcp_client()
        if client is None:
            return ToolResult(
                status="failure",
                error="MCP client is not connected",
                metadata={"tool": name, "remote": True},
            )

        try:
            import mcp.types as types
            from mcp.shared.exceptions import McpError
        except Exception as exc:
            return ToolResult(
                status="failure",
                error=f"MCP runtime unavailable: {exc}",
                metadata={"tool": name, "remote": True},
            )

        params = types.CallToolRequestParams(name=name, arguments=args or None)
        request = types.CallToolRequest(params=params)
        try:
            result = await client.send_request(request, types.CallToolResult)
        except McpError as exc:
            return ToolResult(
                status="failure",
                error=f"MCP call failed: {exc}",
                metadata={"tool": name, "remote": True},
            )
        except Exception as exc:
            return ToolResult(
                status="failure",
                error=str(exc),
                metadata={"tool": name, "remote": True},
            )

        content_blocks = [block.model_dump(mode="json") for block in (result.content or [])]
        payload = {
            "tool": name,
            "content_blocks": content_blocks,
            "structuredContent": result.structuredContent,
            "isError": result.isError,
        }
        status = "failure" if result.isError else "success"
        return ToolResult(status=status, content=payload, metadata={"tool": name, "remote": True})

