"""
Endpoint Registry

Central registry for managing all MCP endpoints.
Handles routing requests to the correct endpoint based on path.
"""

import logging
from dataclasses import dataclass

from fastmcp import FastMCP
from starlette.routing import Mount, Route

from .config import (
    ENDPOINT_CONFIGS,
    EndpointConfig,
    EndpointType,
    create_project_endpoint_config,
)
from .factory import MCPEndpointFactory

logger = logging.getLogger(__name__)


@dataclass
class EndpointInfo:
    """Information about a registered endpoint"""

    path: str
    name: str
    description: str
    endpoint_type: EndpointType
    tool_count: int
    plugin_types: list[str]
    require_master_key: bool


class EndpointRegistry:
    """
    Central registry for all MCP endpoints.

    Manages endpoint creation, routing, and discovery.
    """

    def __init__(self, factory: MCPEndpointFactory):
        """
        Initialize the endpoint registry.

        Args:
            factory: Endpoint factory for creating MCP instances
        """
        self.factory = factory
        self._endpoints: dict[str, FastMCP] = {}
        self._configs: dict[str, EndpointConfig] = {}
        self._initialized = False

    def initialize_default_endpoints(self):
        """
        Initialize the default set of endpoints.

        Creates admin, wordpress, wordpress-specialist, and gitea endpoints.
        """
        if self._initialized:
            logger.warning("Endpoints already initialized")
            return

        logger.info("=" * 60)
        logger.info("Initializing Multi-Endpoint Architecture")
        logger.info("=" * 60)

        # Create default endpoints
        for _endpoint_type, config in ENDPOINT_CONFIGS.items():
            try:
                mcp = self.factory.create_endpoint(config)
                self._endpoints[config.path] = mcp
                self._configs[config.path] = config
                logger.info(f"  ✓ {config.path}: {config.name}")
            except Exception as e:
                logger.error(f"  ✗ Failed to create {config.path}: {e}")

        self._initialized = True

        # Log summary
        self._log_summary()

    def create_project_endpoint(
        self, project_id: str, plugin_type: str, site_alias: str | None = None
    ) -> FastMCP:
        """
        Create a dynamic endpoint for a specific project.

        Args:
            project_id: Full project ID
            plugin_type: Plugin type
            site_alias: Optional site alias

        Returns:
            Created FastMCP instance
        """
        config = create_project_endpoint_config(project_id, plugin_type, site_alias)

        # Check if already exists
        if config.path in self._endpoints:
            logger.info(f"Endpoint {config.path} already exists")
            return self._endpoints[config.path]

        mcp = self.factory.create_endpoint(config)
        self._endpoints[config.path] = mcp
        self._configs[config.path] = config

        logger.info(f"Created project endpoint: {config.path}")
        return mcp

    def get_endpoint(self, path: str) -> FastMCP | None:
        """
        Get endpoint by path.

        Args:
            path: Endpoint path

        Returns:
            FastMCP instance or None
        """
        # Exact match
        if path in self._endpoints:
            return self._endpoints[path]

        # Try with trailing slash
        if not path.endswith("/"):
            return self._endpoints.get(path + "/")

        return None

    def get_config(self, path: str) -> EndpointConfig | None:
        """Get endpoint configuration by path"""
        return self._configs.get(path)

    def list_endpoints(self) -> list[EndpointInfo]:
        """
        List all registered endpoints with their info.

        Returns:
            List of EndpointInfo objects
        """
        endpoints = []

        for path, config in self._configs.items():
            mcp = self._endpoints.get(path)
            tool_count = 0

            if mcp:
                tool_count = self.factory._tool_counts.get(path, 0)

            endpoints.append(
                EndpointInfo(
                    path=path,
                    name=config.name,
                    description=config.description,
                    endpoint_type=config.endpoint_type,
                    tool_count=tool_count,
                    plugin_types=config.plugin_types,
                    require_master_key=config.require_master_key,
                )
            )

        return endpoints

    def get_routes(self) -> list[Route]:
        """
        Get Starlette routes for all endpoints.

        Returns:
            List of Route objects for mounting
        """
        routes = []

        for path, mcp in self._endpoints.items():
            # Each MCP endpoint needs to handle its own routing
            # FastMCP provides an ASGI app
            routes.append(Mount(path, app=mcp.sse_app(), name=f"mcp_{path.replace('/', '_')}"))

        return routes

    def _log_summary(self):
        """Log a summary of all endpoints"""
        logger.info("-" * 60)
        logger.info("Endpoint Summary:")
        logger.info("-" * 60)

        total_tools = 0
        for info in self.list_endpoints():
            total_tools += info.tool_count
            auth_note = " (Master Key required)" if info.require_master_key else ""
            logger.info(f"  {info.path}: {info.tool_count} tools{auth_note}")

        logger.info("-" * 60)
        logger.info(f"Total: {len(self._endpoints)} endpoints")
        logger.info("=" * 60)


# Singleton instance
_registry: EndpointRegistry | None = None


def get_endpoint_registry() -> EndpointRegistry:
    """Get the global endpoint registry instance"""
    global _registry
    if _registry is None:
        raise RuntimeError(
            "Endpoint registry not initialized. " "Call initialize_endpoint_registry() first."
        )
    return _registry


def initialize_endpoint_registry(factory: MCPEndpointFactory) -> EndpointRegistry:
    """
    Initialize the global endpoint registry.

    Args:
        factory: Endpoint factory to use

    Returns:
        Initialized EndpointRegistry
    """
    global _registry
    _registry = EndpointRegistry(factory)
    return _registry
