"""MCP server registry — tracks available MCP servers and their capabilities."""

from __future__ import annotations

from dataclasses import dataclass, field
from enum import Enum

import structlog

logger = structlog.get_logger()


class MCPTransport(str, Enum):
    """Transport protocol for MCP communication."""
    HTTP = "http"
    STDIO = "stdio"
    SSE = "sse"


@dataclass
class MCPServerSpec:
    """Specification of a registered MCP server.

    Attributes
    ----------
    name : str
        Unique server identifier (e.g. "github", "filesystem").
    url : str
        Endpoint URL (for HTTP/SSE) or command (for stdio).
    transport : MCPTransport
        Communication transport.
    tools : list[str]
        Tool names this server provides.
    description : str
        Human-readable description.
    enabled : bool
        Whether this server is active.
    priority : int
        Lower = higher priority when multiple servers provide the same tool.
    """

    name: str
    url: str = ""
    transport: MCPTransport = MCPTransport.HTTP
    tools: list[str] = field(default_factory=list)
    description: str = ""
    enabled: bool = True
    priority: int = 10


class MCPRegistry:
    """Registry of available MCP servers.

    Servers can be registered programmatically or loaded from config.
    The registry provides lookup by name and by tool capability.
    """

    def __init__(self) -> None:
        self._servers: dict[str, MCPServerSpec] = {}

    def register(self, spec: MCPServerSpec) -> None:
        """Register an MCP server."""
        self._servers[spec.name] = spec
        logger.info("mcp_server_registered", name=spec.name,
                     tools=spec.tools, transport=spec.transport.value)

    def unregister(self, name: str) -> bool:
        """Unregister an MCP server by name."""
        if name in self._servers:
            del self._servers[name]
            return True
        return False

    def get(self, name: str) -> MCPServerSpec | None:
        """Get server by name."""
        return self._servers.get(name)

    def list_servers(self, enabled_only: bool = True) -> list[MCPServerSpec]:
        """List all registered servers."""
        servers = self._servers.values()
        if enabled_only:
            servers = [s for s in servers if s.enabled]
        return sorted(servers, key=lambda s: s.priority)

    def available_names(self) -> set[str]:
        """Return set of names of enabled servers."""
        return {s.name for s in self._servers.values() if s.enabled}

    def servers_for_tool(self, tool_name: str) -> list[MCPServerSpec]:
        """Find servers that provide a specific tool."""
        return sorted(
            [s for s in self._servers.values()
             if s.enabled and tool_name in s.tools],
            key=lambda s: s.priority,
        )

    def load_from_config(self, config: list[dict]) -> None:
        """Load servers from a list of config dicts.

        Each dict should have: name, url, transport, tools, description.
        """
        for entry in config:
            transport = MCPTransport(entry.get("transport", "http"))
            spec = MCPServerSpec(
                name=entry["name"],
                url=entry.get("url", ""),
                transport=transport,
                tools=entry.get("tools", []),
                description=entry.get("description", ""),
                enabled=entry.get("enabled", True),
                priority=entry.get("priority", 10),
            )
            self.register(spec)
