import os
import json
import importlib
import logging
from typing import Dict, Type, Any
from plugins import DriverPlugin, CountermeasurePlugin

# 配置日志
logger = logging.getLogger(__name__)

class PluginManager:
    '''
    插件管理器，负责加载和管理驱动插件与反制动作插件。
    '''
    def __init__(self, plugin_dirs: list):
        self.plugin_dirs = plugin_dirs
        self.drivers: Dict[str, Type[DriverPlugin]] = {}
        self.countermeasures: Dict[str, Type[CountermeasurePlugin]] = {}

    def load_plugins(self):
        '''扫描并加载所有插件'''
        for plugin_dir in self.plugin_dirs:
            if not os.path.isdir(plugin_dir):
                logger.warning(f"Plugin directory {plugin_dir} does not exist.")
                continue

            # 检查 plugin_dir 本身是否有 plugin.json (为了兼容旧结构或单文件插件)
            plugin_config_path = os.path.join(plugin_dir, 'plugin.json')
            if os.path.exists(plugin_config_path):
                self._load_plugin_from_config(plugin_dir, plugin_config_path)
                continue

            # 如果没有，检查 plugin_dir 下的直接子目录
            try:
                for item in os.listdir(plugin_dir):
                    item_path = os.path.join(plugin_dir, item)
                    if os.path.isdir(item_path):
                        sub_plugin_config_path = os.path.join(item_path, 'plugin.json')
                        if os.path.exists(sub_plugin_config_path):
                            self._load_plugin_from_config(item_path, sub_plugin_config_path)
                        else:
                            logger.debug(f"Plugin config {sub_plugin_config_path} not found.")
            except OSError as e:
                logger.error(f"Error scanning directory {plugin_dir}: {e}")

    def _load_plugin_from_config(self, plugin_dir: str, plugin_config_path: str):
        '''从配置文件加载单个插件'''
        try:
            with open(plugin_config_path, 'r', encoding='utf-8') as f:
                config = json.load(f)
        except json.JSONDecodeError as e:
            logger.error(f"Error decoding JSON from {plugin_config_path}: {e}")
            return
        except Exception as e:
            logger.error(f"Error reading {plugin_config_path}: {e}")
            return

        plugin_type = config.get('type')
        if plugin_type == 'driver':
            self._load_driver_plugin(plugin_dir, config)
        elif plugin_type == 'countermeasure':
            self._load_countermeasure_plugin(plugin_dir, config)
        else:
            logger.warning(f"Unknown plugin type '{plugin_type}' in {plugin_config_path}")

    def _load_driver_plugin(self, plugin_dir: str, config: dict):
        '''加载驱动插件'''
        name = config.get('name')
        entry_point = config.get('entry_point')
        if not name or not entry_point:
            logger.error(f"Invalid driver plugin config in {plugin_dir}")
            return

        try:
            # 假设插件模块在 plugin_dir 下
            module_name, class_name = entry_point.rsplit('.', 1)
            spec = importlib.util.spec_from_file_location(module_name, os.path.join(plugin_dir, f"{module_name}.py"))
            if spec is None:
                logger.error(f"Failed to create spec for driver plugin {name} from {plugin_dir}")
                return
            module = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(module)
            driver_class = getattr(module, class_name)
            
            if issubclass(driver_class, DriverPlugin):
                self.drivers[name] = driver_class
                logger.info(f"Loaded driver plugin: {name}")
            else:
                logger.error(f"Plugin {name} does not implement DriverPlugin interface.")
        except (ImportError, AttributeError) as e:
            logger.error(f"Failed to load driver plugin {name}: {e}")
        except Exception as e:
            logger.error(f"Unexpected error loading driver plugin {name}: {e}")

    def _load_countermeasure_plugin(self, plugin_dir: str, config: dict):
        '''加载反制动作插件'''
        name = config.get('name')
        entry_point = config.get('entry_point')
        if not name or not entry_point:
            logger.error(f"Invalid countermeasure plugin config in {plugin_dir}")
            return

        try:
            # 假设插件模块在 plugin_dir 下
            module_name, class_name = entry_point.rsplit('.', 1)
            spec = importlib.util.spec_from_file_location(module_name, os.path.join(plugin_dir, f"{module_name}.py"))
            if spec is None:
                logger.error(f"Failed to create spec for countermeasure plugin {name} from {plugin_dir}")
                return
            module = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(module)
            cm_class = getattr(module, class_name)
            
            if issubclass(cm_class, CountermeasurePlugin):
                self.countermeasures[name] = cm_class
                logger.info(f"Loaded countermeasure plugin: {name}")
            else:
                logger.error(f"Plugin {name} does not implement CountermeasurePlugin interface.")
        except (ImportError, AttributeError) as e:
            logger.error(f"Failed to load countermeasure plugin {name}: {e}")
        except Exception as e:
            logger.error(f"Unexpected error loading countermeasure plugin {name}: {e}")

    def get_driver(self, name: str) -> DriverPlugin:
        '''获取驱动实例'''
        driver_class = self.drivers.get(name)
        if driver_class:
            return driver_class()
        return None

    def get_countermeasure(self, name: str) -> CountermeasurePlugin:
        '''获取反制动作实例'''
        cm_class = self.countermeasures.get(name)
        if cm_class:
            return cm_class()
        return None