"""
MCP Tool Adapter - Bridge between MCP tools and groknroll tool system

Wraps MCP tools to work with the groknroll tool registry,
allowing them to be used seamlessly alongside built-in tools.
"""

from typing import Any, Optional

from groknroll.mcp.registry import MCPRegistry, get_registry
from groknroll.mcp.types import MCPTool
from groknroll.tools.base_tool import BaseTool


class MCPToolAdapter(BaseTool):
    """
    Adapter that wraps an MCP tool as a groknroll BaseTool

    This allows MCP tools to be registered with the ToolRegistry
    and used alongside built-in tools.

    Example:
        # From MCP tool
        mcp_tool = MCPTool(name="read_file", description="Read a file")

        # Create adapter
        adapter = MCPToolAdapter("filesystem", mcp_tool)

        # Register with tool registry
        registry.register(adapter)

        # Use like any other tool
        result = await adapter.execute(path="/etc/hosts")
    """

    def __init__(
        self,
        server_name: str,
        mcp_tool: MCPTool,
        mcp_registry: Optional[MCPRegistry] = None,
    ):
        """
        Initialize MCP tool adapter

        Args:
            server_name: Name of the MCP server providing this tool
            mcp_tool: The MCP tool definition
            mcp_registry: MCP registry instance (defaults to global)
        """
        self._server_name = server_name
        self._mcp_tool = mcp_tool
        self._mcp_registry = mcp_registry

    @property
    def name(self) -> str:
        """
        Tool name with server prefix to avoid collisions

        Returns:
            Name in format "mcp:{server}:{tool}"
        """
        return f"mcp:{self._server_name}:{self._mcp_tool.name}"

    @property
    def simple_name(self) -> str:
        """Original MCP tool name without prefix"""
        return self._mcp_tool.name

    @property
    def description(self) -> str:
        """Tool description"""
        return f"[MCP:{self._server_name}] {self._mcp_tool.description}"

    @property
    def server_name(self) -> str:
        """Name of the MCP server"""
        return self._server_name

    @property
    def mcp_tool(self) -> MCPTool:
        """Underlying MCP tool definition"""
        return self._mcp_tool

    def validate_params(self, **kwargs) -> dict[str, Any]:
        """
        Validate parameters against MCP tool schema

        Args:
            **kwargs: Parameters to validate

        Returns:
            Validated parameters

        Raises:
            ValueError: If required parameters are missing
        """
        validated = {}

        for param in self._mcp_tool.parameters:
            if param.name in kwargs:
                validated[param.name] = kwargs[param.name]
            elif param.required:
                raise ValueError(f"Required parameter '{param.name}' not provided")
            elif param.default is not None:
                validated[param.name] = param.default

        return validated

    async def execute(self, **kwargs) -> Any:
        """
        Execute the MCP tool

        Args:
            **kwargs: Tool arguments

        Returns:
            Tool execution result

        Raises:
            RuntimeError: If MCP server not connected
        """
        # Get registry
        registry = self._mcp_registry or get_registry()

        # Validate and execute
        validated = self.validate_params(**kwargs)
        result = await registry.call_tool(
            self._server_name,
            self._mcp_tool.name,
            **validated,
        )

        if result.is_error:
            raise RuntimeError(f"MCP tool error: {result.error_message or result.content}")

        return result.content


class MCPToolManager:
    """
    Manager for integrating MCP tools with groknroll tool system

    Automatically creates adapters for all MCP tools and can
    register them with the tool registry.

    Example:
        manager = MCPToolManager()

        # Connect to servers
        await manager.connect_servers()

        # Get all adapted tools
        tools = manager.get_all_tools()

        # Register with tool registry
        from groknroll.tools import ToolRegistry
        for tool in tools:
            ToolRegistry().register(tool)
    """

    def __init__(self, mcp_registry: Optional[MCPRegistry] = None):
        """
        Initialize MCP tool manager

        Args:
            mcp_registry: MCP registry instance (defaults to global)
        """
        self._mcp_registry = mcp_registry or get_registry()
        self._adapters: dict[str, MCPToolAdapter] = {}

    async def connect_servers(self) -> int:
        """
        Connect to all configured MCP servers

        Returns:
            Number of servers connected
        """
        results = await self._mcp_registry.connect_all()
        await self._update_adapters()
        return len(results)

    async def _update_adapters(self) -> None:
        """Update adapters based on connected servers"""
        self._adapters.clear()

        for server_name, tools in self._mcp_registry.list_all_tools().items():
            for tool in tools:
                adapter = MCPToolAdapter(server_name, tool, self._mcp_registry)
                self._adapters[adapter.name] = adapter

    def get_all_tools(self) -> list[MCPToolAdapter]:
        """
        Get all MCP tools as groknroll tool adapters

        Returns:
            List of MCPToolAdapter instances
        """
        return list(self._adapters.values())

    def get_tool(self, name: str) -> Optional[MCPToolAdapter]:
        """
        Get a specific tool adapter by name

        Args:
            name: Tool name (can be full name or simple name)

        Returns:
            MCPToolAdapter or None if not found
        """
        # Try full name first
        if name in self._adapters:
            return self._adapters[name]

        # Try to find by simple name
        for adapter in self._adapters.values():
            if adapter.simple_name == name:
                return adapter

        return None

    def get_tools_by_server(self, server_name: str) -> list[MCPToolAdapter]:
        """
        Get all tools from a specific server

        Args:
            server_name: Name of the MCP server

        Returns:
            List of tool adapters from that server
        """
        return [
            adapter for adapter in self._adapters.values() if adapter.server_name == server_name
        ]

    async def refresh(self) -> None:
        """Refresh tool adapters from connected servers"""
        await self._update_adapters()

    async def disconnect_all(self) -> None:
        """Disconnect from all servers"""
        await self._mcp_registry.disconnect_all()
        self._adapters.clear()
