"""插件类与运行实例注册表。"""

from typing import Any, Dict, Optional

from app.schemas.plugin import PluginRuntimeStatus


class PluginRegistry:
    """集中持有插件类和运行实例，并为读取方提供稳定快照。"""

    def __init__(self) -> None:
        """创建彼此独立但生命周期一致的类表和实例表。"""
        self._classes: Dict[str, Any] = {}
        self._running: Dict[str, Any] = {}
        self._runtime_statuses: Dict[str, PluginRuntimeStatus] = {}
        self._settling = False
        self._generation = 0

    @property
    def classes(self) -> Dict[str, Any]:
        """返回兼容旧调用方可变访问语义的插件类表。"""
        return self._classes

    @property
    def running(self) -> Dict[str, Any]:
        """返回兼容旧调用方可变访问语义的运行实例表。"""
        return self._running

    def has_class(self, plugin_id: str) -> bool:
        """判断插件类是否已经登记。"""
        return plugin_id in self._classes

    def plugin_class(self, plugin_id: str) -> Optional[Any]:
        """读取指定插件类，未登记时返回空。"""
        return self._classes.get(plugin_id)

    def instance(self, plugin_id: str) -> Optional[Any]:
        """读取指定运行实例，未运行时返回空。"""
        return self._running.get(plugin_id)

    def plugin_ids(self) -> list[str]:
        """返回保持登记顺序的插件类 ID 快照。"""
        return list(self._classes)

    def running_ids(self) -> list[str]:
        """返回保持登记顺序的运行实例 ID 快照。"""
        return list(self._running)

    def running_snapshot(self) -> Dict[str, Any]:
        """复制运行实例表，避免插件重载期间迭代失效。"""
        return dict(self._running)

    def set_runtime_status(
        self,
        plugin_id: str,
        status: PluginRuntimeStatus,
    ) -> None:
        """记录插件当前状态，并在实际变化时推进前端刷新代次。"""
        if self._runtime_statuses.get(plugin_id) == status:
            return
        self._runtime_statuses[plugin_id] = status
        self._generation += 1

    def runtime_status(self, plugin_id: str) -> Optional[PluginRuntimeStatus]:
        """读取指定插件状态。"""
        return self._runtime_statuses.get(plugin_id)

    def runtime_status_snapshot(self) -> Dict[str, PluginRuntimeStatus]:
        """复制插件状态表，避免后台加载期间迭代失效。"""
        return dict(self._runtime_statuses)

    def set_settling(self, settling: bool) -> None:
        """标记启动后的插件源码与依赖收敛任务是否仍在执行。"""
        if self._settling == settling:
            return
        self._settling = settling
        self._generation += 1

    @property
    def settling(self) -> bool:
        """返回插件后台收敛任务是否仍在执行。"""
        return self._settling

    @property
    def generation(self) -> int:
        """返回状态变化代次，供读取方识别刷新边界。"""
        return self._generation

    def remove(self, plugin_id: str) -> None:
        """同时移除指定插件类、运行实例和状态。"""
        self._classes.pop(plugin_id, None)
        self._running.pop(plugin_id, None)
        if self._runtime_statuses.pop(plugin_id, None) is not None:
            self._generation += 1

    def clear(self) -> None:
        """原地清空注册表，保持外部持有的兼容字典引用有效。"""
        self._classes.clear()
        self._running.clear()
        if self._runtime_statuses:
            self._runtime_statuses.clear()
            self._generation += 1
