"""Subagent registry for role-to-factory mapping.

Maintains a registry mapping agent roles (planner, coder, evaluator, etc.)
to their corresponding subagent factories. Each role gets a factory that
knows how to construct the appropriate runner with the right spec.
"""

from __future__ import annotations

import logging
from dataclasses import dataclass, field
from typing import Any

from cyberbrain26.orchestration.subagent.interface import (
    BaseSubagent,
    SubagentFactory,
)
from cyberbrain26.orchestration.subagent.types import (
    ContextMode,
    PatternType,
    SubagentSpec,
)

logger = logging.getLogger(__name__)


@dataclass
class SubagentRegistration:
    """Registration entry for a subagent factory."""

    factory: SubagentFactory
    default_trust_level: Any = None
    default_tool_whitelist: list[str] = field(default_factory=list)
    default_context_mode: str = "isolated"
    pattern: str = "subagent"


class SubagentRegistry:
    """Registry mapping roles to subagent factories.

    Enables dynamic subagent creation without hardcoding imports.
    Follows the extension layer pattern for framework-agnostic orchestration.
    """

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

    def register(
        self,
        role: str,
        factory: SubagentFactory,
        *,
        default_trust_level: Any = None,
        default_tool_whitelist: list[str] | None = None,
        default_context_mode: str = "isolated",
        pattern: str = "subagent",
    ) -> None:
        """Register a factory for a given role."""
        self._registry[role] = SubagentRegistration(
            factory=factory,
            default_trust_level=default_trust_level,
            default_tool_whitelist=default_tool_whitelist or [],
            default_context_mode=default_context_mode,
            pattern=pattern,
        )
        logger.info(
            "Registered subagent role=%s runner=%s pattern=%s",
            role, factory.runner_class.__name__, pattern,
        )

    def create(self, role: str, spec: SubagentSpec | None = None) -> BaseSubagent:
        """Create a subagent instance for the given role.

        Args:
            role: Agent role name (planner, coder, evaluator, etc.)
            spec: Optional specification; if None, uses registration defaults

        Raises:
            KeyError: If no factory is registered for the role
        """
        if role not in self._registry:
            raise KeyError(f"No subagent factory registered for role={role}")

        registration = self._registry[role]
        if spec is None:
            spec = SubagentSpec(
                role=role,
                pattern=PatternType(registration.pattern),
                tools_whitelist=list(registration.default_tool_whitelist),
                context_mode=ContextMode(registration.default_context_mode),
                trust_level=registration.default_trust_level,
            )

        return registration.factory.create(spec)

    def list_roles(self) -> list[str]:
        """Return all registered role names."""
        return list(self._registry.keys())

    def has_role(self, role: str) -> bool:
        """Return True if a factory is registered for the role."""
        return role in self._registry