"""Plugin system using Python entry points for spec discovery and registration."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable

from ai4gh.core.exceptions import PluginError
from ai4gh.core.logging import get_logger

if TYPE_CHECKING:
    from ai4gh.core.config import Config

logger = get_logger(__name__)

ENTRY_POINT_GROUP = "ai4gh.plugins"


@runtime_checkable
class GA4GHPlugin(Protocol):
    """Protocol that all GA4GH spec plugins must implement."""

    name: str
    spec_version: str

    def get_tools(self) -> list[dict[str, Any]]:
        """Return MCP tool definitions for this plugin."""
        ...

    def create_client(self, config: Config) -> Any:
        """Create a client instance for this spec."""
        ...


class PluginRegistry:
    """Registry for discovering and managing GA4GH plugins."""

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

    def register(self, plugin: GA4GHPlugin) -> None:
        """Register a plugin instance."""
        self._plugins[plugin.name] = plugin
        logger.debug("registered plugin", name=plugin.name, version=plugin.spec_version)

    def get(self, name: str) -> GA4GHPlugin | None:
        """Get a registered plugin by name."""
        return self._plugins.get(name)

    def list_plugins(self) -> list[str]:
        """List all registered plugin names."""
        return list(self._plugins.keys())

    @property
    def plugins(self) -> dict[str, GA4GHPlugin]:
        """All registered plugins."""
        return dict(self._plugins)

    def discover(self) -> int:
        """Discover and load plugins from entry points.

        Returns:
            Number of plugins discovered and loaded.
        """
        count = 0

        from importlib.metadata import entry_points

        eps = entry_points(group=ENTRY_POINT_GROUP)

        for ep in eps:
            try:
                plugin_class = ep.load()
                plugin = plugin_class() if callable(plugin_class) else plugin_class

                if isinstance(plugin, GA4GHPlugin):
                    self.register(plugin)
                    count += 1
                else:
                    logger.warning(
                        "plugin does not implement GA4GHPlugin protocol",
                        name=ep.name,
                    )
            except Exception as e:
                raise PluginError(f"Failed to load plugin '{ep.name}': {e}") from e

        logger.info("plugin discovery complete", count=count)
        return count


# Global plugin registry instance
registry = PluginRegistry()
