"""
Plugin Manager

Provides centralized management for plugins including:
- Loading and unloading
- Activation and deactivation
- Configuration management
"""

import json
import logging
from pathlib import Path
from typing import Optional

from groknroll.plugins.base import Plugin, PluginConfig, PluginStatus
from groknroll.plugins.hooks import get_hook_manager
from groknroll.plugins.loader import load_plugin

logger = logging.getLogger(__name__)


class PluginManager:
    """
    Manager for plugin lifecycle

    Example:
        manager = PluginManager()

        # Load plugin
        manager.load("./my_plugin.py")

        # Activate plugin
        manager.activate("my-plugin")

        # List plugins
        for name, plugin in manager.list_plugins().items():
            print(f"{name}: {plugin.status}")
    """

    DEFAULT_CONFIG_PATH = Path.home() / ".groknroll" / "plugins.json"

    def __init__(self, config_path: Optional[Path] = None):
        self.config_path = config_path or self.DEFAULT_CONFIG_PATH
        self._plugins: dict[str, Plugin] = {}
        self._configs: dict[str, PluginConfig] = {}
        self._load_config()

    def _load_config(self) -> None:
        """Load plugin configurations from disk"""
        if self.config_path.exists():
            try:
                data = json.loads(self.config_path.read_text())
                for name, config_data in data.get("plugins", {}).items():
                    self._configs[name] = PluginConfig(
                        path=Path(config_data["path"]),
                        enabled=config_data.get("enabled", True),
                        settings=config_data.get("settings", {}),
                    )
            except Exception as e:
                logger.error(f"Failed to load plugin config: {e}")

    def _save_config(self) -> None:
        """Save plugin configurations to disk"""
        self.config_path.parent.mkdir(parents=True, exist_ok=True)
        data = {
            "plugins": {
                name: {
                    "path": str(config.path),
                    "enabled": config.enabled,
                    "settings": config.settings,
                }
                for name, config in self._configs.items()
            }
        }
        self.config_path.write_text(json.dumps(data, indent=2))

    def load(self, source: str) -> Optional[Plugin]:
        """
        Load a plugin from a source

        Args:
            source: Plugin source (path or NPM package)

        Returns:
            Loaded plugin or None
        """
        plugin = load_plugin(source)
        if plugin:
            self._plugins[plugin.info.name] = plugin
            self._configs[plugin.info.name] = PluginConfig(path=Path(source))
            self._save_config()
            logger.info(f"Loaded plugin: {plugin.info.name}")
        return plugin

    def unload(self, name: str) -> bool:
        """
        Unload a plugin

        Args:
            name: Plugin name

        Returns:
            True if unloaded
        """
        if name not in self._plugins:
            return False

        self.deactivate(name)
        del self._plugins[name]
        if name in self._configs:
            del self._configs[name]
        self._save_config()
        logger.info(f"Unloaded plugin: {name}")
        return True

    def activate(self, name: str) -> bool:
        """
        Activate a plugin

        Args:
            name: Plugin name

        Returns:
            True if activated
        """
        if name not in self._plugins:
            return False

        plugin = self._plugins[name]
        if plugin.status == PluginStatus.ACTIVE:
            return True

        try:
            plugin.activate()
            plugin._status = PluginStatus.ACTIVE

            # Register hooks with global manager
            hook_manager = get_hook_manager()
            for hook in plugin.hooks:
                hook_manager.register(hook)

            logger.info(f"Activated plugin: {name}")
            return True

        except Exception as e:
            plugin._status = PluginStatus.ERROR
            logger.error(f"Failed to activate plugin {name}: {e}")
            return False

    def deactivate(self, name: str) -> bool:
        """
        Deactivate a plugin

        Args:
            name: Plugin name

        Returns:
            True if deactivated
        """
        if name not in self._plugins:
            return False

        plugin = self._plugins[name]
        if plugin.status != PluginStatus.ACTIVE:
            return True

        try:
            # Unregister hooks
            hook_manager = get_hook_manager()
            hook_manager.unregister_all(name)

            plugin.deactivate()
            plugin._status = PluginStatus.LOADED

            logger.info(f"Deactivated plugin: {name}")
            return True

        except Exception as e:
            logger.error(f"Failed to deactivate plugin {name}: {e}")
            return False

    def get(self, name: str) -> Optional[Plugin]:
        """Get a plugin by name"""
        return self._plugins.get(name)

    def list_plugins(self) -> dict[str, Plugin]:
        """List all loaded plugins"""
        return self._plugins.copy()

    def list_active(self) -> list[str]:
        """List names of active plugins"""
        return [n for n, p in self._plugins.items() if p.status == PluginStatus.ACTIVE]

    def enable(self, name: str) -> bool:
        """Enable a plugin (load on startup)"""
        if name in self._configs:
            self._configs[name].enabled = True
            self._save_config()
            return True
        return False

    def disable(self, name: str) -> bool:
        """Disable a plugin (don't load on startup)"""
        if name in self._configs:
            self._configs[name].enabled = False
            self._save_config()
            self.deactivate(name)
            return True
        return False

    def load_enabled(self) -> int:
        """Load all enabled plugins"""
        count = 0
        for name, config in self._configs.items():
            if config.enabled and name not in self._plugins:
                if self.load(str(config.path)):
                    count += 1
        return count

    def activate_all(self) -> int:
        """Activate all loaded plugins"""
        count = 0
        for name in self._plugins:
            if self.activate(name):
                count += 1
        return count


# Global plugin manager
_plugin_manager: Optional[PluginManager] = None


def get_plugin_manager() -> PluginManager:
    """Get the global plugin manager"""
    global _plugin_manager
    if _plugin_manager is None:
        _plugin_manager = PluginManager()
    return _plugin_manager


def reset_plugin_manager() -> None:
    """Reset the global plugin manager (for testing)"""
    global _plugin_manager
    _plugin_manager = None
