"""下载器、媒体服务器和通知服务的应用层目录端口。"""

from __future__ import annotations

from collections.abc import Callable, Iterator
from typing import Any, Dict, Generic, List, Optional, Type, TypeVar

from app.schemas.system import ServiceInfo
from app.schemas.types import ModuleType, SystemConfigKey

TConf = TypeVar("TConf")
ServiceConfigLoader = Callable[[SystemConfigKey, Type[Any]], list[Any]]
RunningModuleLoader = Callable[[ModuleType], list[Any]]


def _unconfigured_configs(
    _config_key: SystemConfigKey,
    _conf_type: Type[Any],
) -> list[Any]:
    """拒绝在启动组合根装配前隐式读取服务配置。"""
    raise RuntimeError("服务配置目录尚未由启动组合根配置")


def _unconfigured_modules(_module_type: ModuleType) -> list[Any]:
    """拒绝在启动组合根装配前隐式抓取模块管理器。"""
    raise RuntimeError("运行模块目录尚未由启动组合根配置")


_config_loader: ServiceConfigLoader = _unconfigured_configs
_module_loader: RunningModuleLoader = _unconfigured_modules


def configure_service_directory(
    *,
    configs: ServiceConfigLoader,
    modules: RunningModuleLoader,
) -> None:
    """由启动组合根注入服务配置和运行模块枚举端口。"""
    global _config_loader, _module_loader
    _config_loader = configs
    _module_loader = modules


class ServiceBaseHelper(Generic[TConf]):
    """通过应用端口查询服务配置和对应运行实例。"""

    def __init__(
        self,
        config_key: SystemConfigKey,
        conf_type: Type[TConf],
        module_type: ModuleType,
    ) -> None:
        """绑定配置类型和模块能力类型，不抓取具体 Runtime 管理器。"""
        self.config_key = config_key
        self.conf_type = conf_type
        self.module_type = module_type

    def get_configs(self, include_disabled: bool = False) -> Dict[str, TConf]:
        """返回按名称索引的有效服务配置。"""
        configs = _config_loader(self.config_key, self.conf_type)
        return {
            config.name: config
            for config in configs
            if config.name
            and config.type
            and (config.enabled or include_disabled)
        }

    def get_config(self, name: str) -> Optional[TConf]:
        """按名称返回单个启用服务配置。"""
        return self.get_configs().get(name) if name else None

    def iterate_module_instances(self) -> Iterator[ServiceInfo]:
        """迭代当前类型所有运行模块实例及其配置投影。"""
        configs = self.get_configs()
        for module in _module_loader(self.module_type):
            if not module:
                continue
            instances = module.get_instances()
            if not isinstance(instances, dict):
                continue
            for name, instance in instances.items():
                if not instance:
                    continue
                config = configs.get(name)
                yield ServiceInfo(
                    name=name,
                    instance=instance,
                    module=module,
                    type=config.type if config else None,
                    config=config,
                )

    def get_services(
        self,
        type_filter: Optional[str] = None,
        name_filters: Optional[List[str]] = None,
    ) -> Dict[str, ServiceInfo]:
        """按服务类型和名称集合过滤运行实例。"""
        names = set(name_filters) if name_filters else None
        return {
            service.name: service
            for service in self.iterate_module_instances()
            if service.config
            and (type_filter is None or service.type == type_filter)
            and (names is None or service.name in names)
        }

    def get_service(
        self,
        name: str,
        type_filter: Optional[str] = None,
    ) -> Optional[ServiceInfo]:
        """按名称和可选类型返回单个运行服务。"""
        if not name:
            return None
        for service in self.iterate_module_instances():
            if (
                service.name == name
                and service.config
                and (type_filter is None or service.type == type_filter)
            ):
                return service
        return None
