"""插件管理器 - Phase 8.2"""

import importlib.util
import os
import sys
from typing import Any

from app.agents.plugins.manifest import PluginManifest
from app.agents.plugins.sandbox import PluginSandbox


class PluginManager:
    """插件管理器

    负责插件的安装、卸载、启用、禁用和生命周期管理。
    """

    def __init__(self, plugins_dir: str | None = None):
        """
        Args:
            plugins_dir: 插件目录，None 则使用默认目录
        """
        if plugins_dir is None:
            plugins_dir = os.path.join(os.path.dirname(__file__), "..", "..", "..", "plugins")
        self.plugins_dir = plugins_dir
        self._plugins: dict[str, PluginManifest] = {}
        self._enabled: dict[str, bool] = {}
        self._modules: dict[str, Any] = {}
        self._sandbox = PluginSandbox()

    def install(self, plugin_path: str) -> bool:
        """安装插件

        Args:
            plugin_path: 插件目录路径或 manifest.json 所在目录

        Returns:
            是否安装成功
        """
        try:
            manifest_path = os.path.join(plugin_path, "manifest.json")

            if not os.path.exists(manifest_path):
                return False

            with open(manifest_path, "r", encoding="utf-8") as f:
                import json

                data = json.load(f)

            manifest = PluginManifest.from_dict(data)

            # 验证 manifest
            if not self._validate_manifest(manifest, plugin_path):
                return False

            # 复制插件到 plugins_dir
            target_dir = os.path.join(self.plugins_dir, manifest.id)
            os.makedirs(os.path.dirname(target_dir), exist_ok=True)

            # 保存 manifest
            with open(os.path.join(target_dir, "manifest.json"), "w", encoding="utf-8") as f:
                json.dump(manifest.to_dict(), f, indent=2, ensure_ascii=False)

            # 注册插件
            self._plugins[manifest.id] = manifest
            self._enabled[manifest.id] = True

            return True

        except Exception:
            return False

    def uninstall(self, plugin_id: str) -> bool:
        """卸载插件

        Args:
            plugin_id: 插件 ID

        Returns:
            是否卸载成功
        """
        if plugin_id not in self._plugins:
            return False

        # 禁用插件
        self.disable(plugin_id)

        # 移除模块
        if plugin_id in self._modules:
            del self._modules[plugin_id]

        # 移除插件
        del self._plugins[plugin_id]
        del self._enabled[plugin_id]

        # 删除目录
        plugin_dir = os.path.join(self.plugins_dir, plugin_id)
        if os.path.exists(plugin_dir):
            import shutil

            shutil.rmtree(plugin_dir)

        return True

    def enable(self, plugin_id: str) -> bool:
        """启用插件

        Args:
            plugin_id: 插件 ID

        Returns:
            是否启用成功
        """
        if plugin_id not in self._plugins:
            return False

        self._enabled[plugin_id] = True
        return True

    def disable(self, plugin_id: str) -> bool:
        """禁用插件

        Args:
            plugin_id: 插件 ID

        Returns:
            是否禁用成功
        """
        if plugin_id not in self._plugins:
            return False

        self._enabled[plugin_id] = False
        return True

    def reload(self, plugin_id: str) -> bool:
        """重新加载插件

        Args:
            plugin_id: 插件 ID

        Returns:
            是否重新加载成功
        """
        if plugin_id not in self._plugins:
            return False

        # 卸载模块
        if plugin_id in self._modules:
            del self._modules[plugin_id]

        # 重新加载
        return self._load_plugin_module(plugin_id)

    def list_plugins(self) -> list[PluginManifest]:
        """列出所有插件"""
        return list(self._plugins.values())

    def get_plugin(self, plugin_id: str) -> PluginManifest | None:
        """获取插件清单"""
        return self._plugins.get(plugin_id)

    def is_enabled(self, plugin_id: str) -> bool:
        """检查插件是否启用"""
        return self._enabled.get(plugin_id, False)

    def _validate_manifest(self, manifest: PluginManifest, plugin_path: str) -> bool:
        """验证 manifest"""
        # 检查主入口文件是否存在
        main_path = os.path.join(plugin_path, manifest.main)
        if not os.path.exists(main_path):
            return False

        return True

    def _load_plugin_module(self, plugin_id: str) -> bool:
        """加载插件模块"""
        plugin_dir = os.path.join(self.plugins_dir, plugin_id)
        manifest = self._plugins.get(plugin_id)
        if not manifest:
            return False

        try:
            main_path = os.path.join(plugin_dir, manifest.main)
            spec = importlib.util.spec_from_file_location(plugin_id, main_path)
            if spec and spec.loader:
                module = importlib.util.module_from_spec(spec)
                sys.modules[plugin_id] = module
                spec.loader.exec_module(module)
                self._modules[plugin_id] = module
                return True
        except Exception:
            pass

        return False


# 全局单例
_manager: PluginManager | None = None


def get_plugin_manager() -> PluginManager:
    """获取全局插件管理器"""
    global _manager
    if _manager is None:
        _manager = PluginManager()
    return _manager
