import importlib.util
from pathlib import Path

import yaml

from common_logging import get_logger

from .plugin_interface import IPlugin

logger = get_logger("plugin_loader")

class PluginLoader:

    def __init__(self, plugins_dir: str='industry_accelerator'):
        self.plugins_dir = Path(plugins_dir)
        self.loaded_plugins: dict[str, IPlugin] = {}

    def discover_plugins(self) -> list[str]:
        plugins = []
        if not self.plugins_dir.exists():
            return plugins
        for item in self.plugins_dir.iterdir():
            if item.is_dir() and (item / 'config' / 'plugin.yaml').exists():
                plugins.append(item.name)
        return plugins

    def load_plugin(self, plugin_name: str) -> IPlugin:
        if plugin_name in self.loaded_plugins:
            return self.loaded_plugins[plugin_name]
        plugin_dir = self.plugins_dir / plugin_name
        config_file = plugin_dir / 'config' / 'plugin.yaml'
        with open(config_file) as f:
            config = yaml.safe_load(f)
        backend_entry = config['backend']['entry']
        class_name = config['backend']['class']
        import sys
        plugin_backend_dir = str(plugin_dir / 'backend')
        if plugin_backend_dir not in sys.path:
            sys.path.insert(0, plugin_backend_dir)
        module_path = plugin_dir / backend_entry
        spec = importlib.util.spec_from_file_location(f'{plugin_name}_plugin', module_path)
        module = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(module)
        plugin_class = getattr(module, class_name)
        plugin_instance = plugin_class()
        self.loaded_plugins[plugin_name] = plugin_instance
        return plugin_instance

    def load_all_plugins(self) -> dict[str, IPlugin]:
        plugin_names = self.discover_plugins()
        for name in plugin_names:
            try:
                self.load_plugin(name)
            except Exception as e:
                logger.opt(exception=e).error(f"Failed to load plugin {name}")
        return self.loaded_plugins
