"""Collector registry and discovery."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

import structlog

from curadise_agent.errors import ConfigurationError

if TYPE_CHECKING:
    from curadise_agent.collectors.base import DomainCollector
    from curadise_agent.config.schema import CollectorsConfig

log = structlog.get_logger(__name__)


class CollectorRegistry:
    """
    Registry for collector classes and instances.

    Manages collector discovery, registration, and instantiation.
    """

    def __init__(self) -> None:
        """Initialize registry."""
        self._collector_classes: dict[str, type[DomainCollector]] = {}
        self._collectors: dict[str, DomainCollector] = {}

    @property
    def registered_types(self) -> list[str]:
        """Get list of registered collector types."""
        return list(self._collector_classes.keys())

    @property
    def active_collectors(self) -> list[str]:
        """Get list of active collector instances."""
        return list(self._collectors.keys())

    def register_class(
        self,
        name: str,
        collector_class: type[DomainCollector],
    ) -> None:
        """
        Register a collector class.

        Args:
            name: Collector type name
            collector_class: Collector class
        """
        self._collector_classes[name] = collector_class
        log.debug("collector_class_registered", name=name)

    def unregister_class(self, name: str) -> None:
        """Unregister a collector class."""
        self._collector_classes.pop(name, None)

    def create_collector(
        self,
        name: str,
        collector_type: str,
        **kwargs: Any,
    ) -> DomainCollector:
        """
        Create a collector instance.

        Args:
            name: Instance name
            collector_type: Type of collector (registered name)
            **kwargs: Arguments to pass to collector constructor

        Returns:
            Collector instance

        Raises:
            ConfigurationError: If collector type not found
        """
        if collector_type not in self._collector_classes:
            raise ConfigurationError(
                f"Unknown collector type: {collector_type}. "
                f"Available: {', '.join(self._collector_classes.keys())}"
            )

        collector_class = self._collector_classes[collector_type]
        collector = collector_class(name=name, **kwargs)
        self._collectors[name] = collector

        log.info("collector_created", name=name, type=collector_type)
        return collector

    def get_collector(self, name: str) -> DomainCollector | None:
        """Get a collector instance by name."""
        return self._collectors.get(name)

    def remove_collector(self, name: str) -> DomainCollector | None:
        """Remove a collector instance."""
        return self._collectors.pop(name, None)

    def get_all_collectors(self) -> list[DomainCollector]:
        """Get all collector instances."""
        return list(self._collectors.values())

    def get_enabled_collectors(self) -> list[DomainCollector]:
        """Get all enabled collector instances."""
        return [c for c in self._collectors.values() if c.enabled]


def register_builtin_collectors(registry: CollectorRegistry) -> None:
    """Register all built-in collectors."""
    from curadise_agent.collectors.it.http import HTTPCollector
    from curadise_agent.collectors.it.system import SystemCollector
    from curadise_agent.collectors.self_metrics import SelfMetricsCollector

    registry.register_class("system", SystemCollector)
    registry.register_class("http", HTTPCollector)
    registry.register_class("self", SelfMetricsCollector)

    log.info("builtin_collectors_registered", count=3)


def create_collectors_from_config(
    config: CollectorsConfig,
    registry: CollectorRegistry,
    tags: dict[str, str] | None = None,
) -> list[DomainCollector]:
    """
    Create collectors based on configuration.

    Args:
        config: Collectors configuration
        registry: Collector registry
        tags: Default tags for all collectors

    Returns:
        List of created collectors
    """
    collectors: list[DomainCollector] = []

    # Create system collector
    if config.system.enabled:
        collector = registry.create_collector(
            name="system",
            collector_type="system",
            config=config.system,
            tags=tags,
        )
        collectors.append(collector)

    # Create HTTP collector if checks are configured
    if config.http.enabled and config.http_checks:
        from curadise_agent.collectors.it.http import HTTPCollector

        collector = HTTPCollector(
            name="http",
            config=config.http,
            checks=config.http_checks,
            tags=tags,
        )
        registry._collectors["http"] = collector
        collectors.append(collector)

    log.info("collectors_created", count=len(collectors))
    return collectors
