"""Base class for sub-agent toolkits."""

from abc import ABC, abstractmethod
from pathlib import Path
from typing import TYPE_CHECKING, Optional

from ..tools.base import BaseTool, ToolResult

if TYPE_CHECKING:
    from ..agents import AgentMCPServerConfig
    from ..mcp.manager import MCPServerManager


class BaseToolkit(ABC):
    """Abstract base class for sub-agent toolkits.

    Each toolkit provides a curated set of tools appropriate for a specific
    agent type. Toolkits are responsible for:
    - Registering appropriate tools
    - Providing OpenAI function schemas
    - Executing tools by name
    - Managing per-agent MCP servers (optional)
    """

    # List of tool names this toolkit provides (for documentation)
    TOOLS: list[str] = []

    def __init__(
        self,
        repo_root: Path,
        mcp_servers: Optional[list["AgentMCPServerConfig"]] = None,
    ):
        """Initialize the toolkit.

        Args:
            repo_root: Root directory of the repository
            mcp_servers: Optional list of MCP server configurations for this agent
        """
        self.repo_root = repo_root.resolve()
        self._tools: dict[str, BaseTool] = {}
        self._mcp_manager: Optional["MCPServerManager"] = None
        self._mcp_servers_config = mcp_servers or []

        self._register_tools()
        self._init_mcp_servers()

    @abstractmethod
    def _register_tools(self) -> None:
        """Register tools for this toolkit.

        Subclasses must implement this to register their specific tools.
        """
        pass

    def _init_mcp_servers(self) -> None:
        """Initialize MCP servers for this agent if configured.

        Creates an MCPServerManager with the agent's MCP server configs
        and registers the tools from those servers. Only enabled servers
        are started.
        """
        if not self._mcp_servers_config:
            return

        # Filter to only enabled servers
        enabled_servers = [s for s in self._mcp_servers_config if s.enabled]
        if not enabled_servers:
            return

        from ..mcp.config import MCPServerConfig, MCPConfigFile
        from ..mcp.manager import MCPServerManager
        from ..mcp.tool_factory import create_tools_from_mcp
        from ...utils.logger import log

        log.info(f"Initializing {len(enabled_servers)} MCP servers for agent")

        # Create a temporary config file object with our servers
        config = MCPConfigFile()
        for server_cfg in enabled_servers:
            mcp_config = MCPServerConfig(
                name=server_cfg.name,
                command=server_cfg.command,
                args=server_cfg.args,
                env=server_cfg.env,
                enabled=True,
                timeout=server_cfg.timeout,
            )
            config.add_server(mcp_config)

        # Create manager with in-memory config (not from file)
        self._mcp_manager = MCPServerManager(repo_root=self.repo_root)
        self._mcp_manager._config = config  # Inject our config directly

        # Start all servers and register tools
        try:
            started = self._mcp_manager.start_all_enabled()
            log.info(f"Started MCP servers for agent: {started}")

            # Create tool wrappers and register them
            mcp_tools = create_tools_from_mcp(self._mcp_manager)
            for tool in mcp_tools:
                self.register_tool(tool)
                log.debug(f"Registered MCP tool: {tool.name}")

        except Exception as e:
            log.warning(f"Failed to initialize MCP servers for agent: {e}")

    def shutdown(self) -> None:
        """Shutdown the toolkit and cleanup resources.

        Stops any running MCP servers.
        """
        if self._mcp_manager:
            from ...utils.logger import log
            log.info("Shutting down agent MCP servers")
            self._mcp_manager.shutdown_all()
            self._mcp_manager = None

    def __del__(self):
        """Cleanup on garbage collection."""
        try:
            self.shutdown()
        except Exception:
            pass

    def register_tool(self, tool: BaseTool) -> None:
        """Register a tool.

        Args:
            tool: Tool instance to register
        """
        self._tools[tool.name] = tool

    def get_tool(self, name: str) -> Optional[BaseTool]:
        """Get a tool by name.

        Args:
            name: Tool name

        Returns:
            Tool instance or None if not found
        """
        return self._tools.get(name)

    def list_tools(self) -> list[str]:
        """List all tool names in this toolkit.

        Returns:
            List of tool names
        """
        return list(self._tools.keys())

    def execute(self, tool_name: str, **params) -> ToolResult:
        """Execute a tool by name.

        Args:
            tool_name: Name of the tool
            **params: Tool parameters

        Returns:
            ToolResult
        """
        tool = self.get_tool(tool_name)
        if not tool:
            return ToolResult.error_result(
                f"Unknown tool: {tool_name}",
                suggestions=[f"Available tools: {self.list_tools()}"],
            )

        try:
            return tool.execute(**params)
        except Exception as e:
            return ToolResult.error_result(f"Tool execution failed: {str(e)}")

    def get_all_schemas(self) -> list[dict]:
        """Get OpenAI function calling schemas for all tools.

        Returns:
            List of function schemas
        """
        return [tool.get_schema() for tool in self._tools.values()]
