"""Pluggable scope chain resolution extension API."""

from __future__ import annotations

from typing import Any, Protocol

from pydantic import BaseModel, Field


class ScopeResolutionContext(BaseModel):
    """Context passed to scope resolvers during resolution."""

    scope: str = Field(
        ...,
        description="The scope reference to resolve (e.g., 'issue:123').",
    )

    metadata: dict[str, Any] = Field(
        default_factory=dict,
        description="Additional metadata for resolution (e.g., project context).",
    )

    resolved_fragments: list[str] = Field(
        default_factory=list,
        description="List of already-resolved fragment identifiers.",
    )


class ScopeChainResolver(Protocol):
    """Protocol for custom scope chain resolvers."""

    def resolve(
        self,
        scope: str,
        context: ScopeResolutionContext,
    ) -> list[str]:
        """Resolve a scope reference to a list of fragment identifiers."""
        ...


class ScopeResolverRegistry:
    """Registry for discovering and managing scope chain resolvers."""

    def __init__(self) -> None:
        """Initialize the registry and discover resolvers from entry points."""
        self._resolvers: dict[str, tuple[ScopeChainResolver, int]] = {}
        self._discover_resolvers()

    def _discover_resolvers(self) -> None:
        """Discover resolvers from Python entry points."""
        try:
            import importlib.metadata as metadata
        except ImportError:
            import importlib_metadata as metadata  # type: ignore

        try:
            entry_points = metadata.entry_points()
            if hasattr(entry_points, "select"):
                scope_resolvers = entry_points.select(
                    group="cleveragents.scope_resolvers"
                )
            else:
                # Fallback for older Python/importlib_metadata versions where
                # entry_points() returns a dict-like mapping of group -> list.
                ep_dict: dict[str, list[Any]] = dict(entry_points)  # type: ignore[arg-type]
                scope_resolvers = ep_dict.get("cleveragents.scope_resolvers", [])

            for ep in scope_resolvers:
                try:
                    resolver_factory = ep.load()
                    resolver = resolver_factory()
                    priority = getattr(ep, "priority", 0)
                    self._resolvers[ep.name] = (resolver, priority)
                except Exception:
                    pass
        except Exception:
            pass

    def register(
        self,
        name: str,
        resolver: ScopeChainResolver,
        priority: int = 0,
    ) -> None:
        """Register a resolver with the given name and priority."""
        self._resolvers[name] = (resolver, priority)

    def unregister(self, name: str) -> None:
        """Unregister a resolver by name."""
        self._resolvers.pop(name, None)

    def resolve(
        self,
        scope: str,
        context: ScopeResolutionContext,
    ) -> list[str]:
        """Resolve a scope using registered resolvers in priority order."""
        sorted_resolvers = sorted(
            self._resolvers.values(),
            key=lambda x: x[1],
            reverse=True,
        )

        for resolver, _ in sorted_resolvers:
            result = resolver.resolve(scope, context)
            if result:
                return result

        return []

    def get_resolvers(self) -> dict[str, tuple[ScopeChainResolver, int]]:
        """Get all registered resolvers with their priorities."""
        return dict(self._resolvers)

    def list_resolvers(self) -> list[tuple[str, int]]:
        """List all registered resolvers with their priorities."""
        items = [(name, priority) for name, (_, priority) in self._resolvers.items()]
        return sorted(items, key=lambda x: x[1], reverse=True)
