"""Discover channel descriptors and load their runtimes lazily."""

from __future__ import annotations

import pkgutil
from typing import TYPE_CHECKING

from loguru import logger

from nanobot.channels.plugin import (
    ChannelPlugin,
    has_channel_package,
    load_channel_package,
)

if TYPE_CHECKING:
    from nanobot.channels.base import BaseChannel


def _channel_package_names() -> list[str]:
    import nanobot.channels as package

    return [
        name
        for _, name, is_package in pkgutil.iter_modules(package.__path__)
        if is_package and has_channel_package(name)
    ]


def discover_plugins(
    enabled_names: set[str] | None = None,
) -> dict[str, ChannelPlugin]:
    """Load dependency-free descriptors from self-contained channel packages."""
    plugins: dict[str, ChannelPlugin] = {}
    for name in _channel_package_names():
        if enabled_names is not None and name not in enabled_names:
            continue
        try:
            plugin = load_channel_package(name)
            if plugin is not None:
                plugins[name] = plugin
        except Exception as exc:
            logger.warning("Failed to load channel package descriptor '{}': {}", name, exc)
    return plugins


def load_channel_plugin(name: str) -> ChannelPlugin:
    """Load one channel package descriptor."""
    plugin = discover_plugins({name}).get(name)
    if plugin is None:
        raise ImportError(f"Unknown channel: {name}")
    return plugin


def channel_default_enabled(name: str) -> bool:
    """Return the activation default declared by a channel descriptor."""
    try:
        return load_channel_plugin(name).default_enabled
    except ImportError:
        return False


def load_channel_class(name: str) -> type[BaseChannel]:
    """Load the runtime declared by one channel descriptor."""
    return load_channel_plugin(name).load_channel_class()


def discover_enabled(
    enabled_names: set[str],
    *,
    _plugins: dict[str, ChannelPlugin] | None = None,
    warn_import_errors: bool = False,
) -> dict[str, type[BaseChannel]]:
    """Load runtime classes only for enabled descriptors."""
    plugins = _plugins if _plugins is not None else discover_plugins(enabled_names)
    result: dict[str, type[BaseChannel]] = {}
    for name, plugin in plugins.items():
        if name not in enabled_names:
            continue
        try:
            result[name] = plugin.load_channel_class()
        except Exception as exc:
            message = "Enabled channel '{}' runtime is not available: {}"
            if warn_import_errors:
                logger.warning(message, name, exc)
            else:
                logger.debug(message, name, exc)
    return result


def discover_all() -> dict[str, type[BaseChannel]]:
    """Load every available channel runtime."""
    plugins = discover_plugins()
    return discover_enabled(set(plugins), _plugins=plugins)


__all__ = [
    "channel_default_enabled",
    "discover_all",
    "discover_enabled",
    "discover_plugins",
    "load_channel_class",
    "load_channel_plugin",
]
