"""
AbuLang Plugin System - Extensibility through plugins
"""

import importlib.util
import sys
from pathlib import Path
from typing import Dict, Any, Callable, List, Optional
from abc import ABC, abstractmethod


class AbuPlugin(ABC):
    """Base class for AbuLang plugins"""
    
    @property
    @abstractmethod
    def name(self) -> str:
        """Plugin name"""
        pass
    
    @property
    @abstractmethod
    def version(self) -> str:
        """Plugin version"""
        pass
    
    @abstractmethod
    def initialize(self, context: Dict):
        """Initialize plugin"""
        pass
    
    @abstractmethod
    def execute(self, *args, **kwargs) -> Any:
        """Execute plugin functionality"""
        pass
    
    def cleanup(self):
        """Cleanup plugin resources"""
        pass


class PluginManager:
    """Manages AbuLang plugins"""
    
    def __init__(self):
        self.plugins: Dict[str, AbuPlugin] = {}
        self.hooks: Dict[str, List[Callable]] = {}
        self.plugin_dir = Path("./plugins")
    
    def register_plugin(self, plugin: AbuPlugin):
        """Register a plugin"""
        self.plugins[plugin.name] = plugin
        plugin.initialize({})
    
    def load_plugin(self, plugin_path: str) -> bool:
        """Load plugin from file"""
        try:
            spec = importlib.util.spec_from_file_location("plugin", plugin_path)
            module = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(module)
            
            # Find plugin class
            for attr_name in dir(module):
                attr = getattr(module, attr_name)
                if isinstance(attr, type) and issubclass(attr, AbuPlugin) and attr != AbuPlugin:
                    plugin = attr()
                    self.register_plugin(plugin)
                    return True
            
            return False
        except Exception as e:
            print(f"Failed to load plugin: {e}")
            return False
    
    def load_plugins_from_directory(self, directory: str = None) -> int:
        """Load all plugins from directory"""
        if directory is None:
            directory = self.plugin_dir
        
        plugin_dir = Path(directory)
        if not plugin_dir.exists():
            return 0
        
        loaded = 0
        for plugin_file in plugin_dir.glob("*.py"):
            if plugin_file.name != "__init__.py":
                if self.load_plugin(str(plugin_file)):
                    loaded += 1
        
        return loaded
    
    def get_plugin(self, name: str) -> Optional[AbuPlugin]:
        """Get plugin by name"""
        return self.plugins.get(name)
    
    def list_plugins(self) -> List[str]:
        """List all loaded plugins"""
        return list(self.plugins.keys())
    
    def execute_plugin(self, name: str, *args, **kwargs) -> Any:
        """Execute plugin"""
        plugin = self.get_plugin(name)
        if plugin:
            return plugin.execute(*args, **kwargs)
        raise ValueError(f"Plugin not found: {name}")
    
    def register_hook(self, hook_name: str, callback: Callable):
        """Register hook callback"""
        if hook_name not in self.hooks:
            self.hooks[hook_name] = []
        self.hooks[hook_name].append(callback)
    
    def call_hook(self, hook_name: str, *args, **kwargs) -> List[Any]:
        """Call all callbacks for hook"""
        results = []
        if hook_name in self.hooks:
            for callback in self.hooks[hook_name]:
                results.append(callback(*args, **kwargs))
        return results
    
    def unload_plugin(self, name: str) -> bool:
        """Unload plugin"""
        if name in self.plugins:
            self.plugins[name].cleanup()
            del self.plugins[name]
            return True
        return False
    
    def get_plugin_info(self, name: str) -> Dict:
        """Get plugin information"""
        plugin = self.get_plugin(name)
        if plugin:
            return {
                "name": plugin.name,
                "version": plugin.version
            }
        return None
    
    def get_all_plugin_info(self) -> List[Dict]:
        """Get information for all plugins"""
        return [self.get_plugin_info(name) for name in self.list_plugins()]


# Global plugin manager
_plugin_manager = PluginManager()


def get_plugin_manager() -> PluginManager:
    """Get global plugin manager"""
    return _plugin_manager
