"""
Plugin manager for issue backends.

This module handles discovery, loading, and configuration of issue management backends.
"""

import importlib
import yaml
from pathlib import Path
from typing import Dict, Any, Type, Optional

from .base import IssueBackend
from .exceptions import PluginNotFoundError, ConfigurationError


class IssuePluginManager:
    """Manages issue backend plugins and configuration."""

    def __init__(self, config_path: Optional[str] = None):
        """
        Initialize plugin manager.

        Args:
            config_path: Optional path to configuration file
        """
        self.config = self._load_config(config_path)
        self.plugins = self._discover_plugins()

    def get_backend(self, backend_name: Optional[str] = None) -> IssueBackend:
        """
        Get configured backend instance.

        Args:
            backend_name: Backend name to use, or None for default

        Returns:
            IssueBackend instance

        Raises:
            PluginNotFoundError: If backend not found
        """
        backend_name = backend_name or self.config.get('default_backend', 'gitea')

        plugin_class = self.plugins.get(backend_name)
        if not plugin_class:
            raise PluginNotFoundError(f"Unknown backend: {backend_name}")

        backend_config = self.config.get('backends', {}).get(backend_name, {})
        return plugin_class(backend_config)

    def _load_config(self, config_path: Optional[str] = None) -> Dict[str, Any]:
        """
        Load configuration from file or return defaults.

        Args:
            config_path: Path to configuration file

        Returns:
            Configuration dictionary
        """
        from config.manager import UnifiedConfigManager

        # Get main markitect configuration to extract API token and settings
        try:
            config_manager = UnifiedConfigManager()
            markitect_config = config_manager.get_config()
            main_config = markitect_config.__dict__ if hasattr(markitect_config, '__dict__') else {}
        except Exception:
            main_config = {}

        if config_path is None:
            config_path = Path('.markitect/config/issues.yml')
        else:
            config_path = Path(config_path)

        # Extract configuration from main markitect config
        gitea_url = main_config.get('gitea_url', 'http://92.205.130.254:32166')
        api_token = main_config.get('api_token', '')
        repo_owner = main_config.get('repo_owner', 'coulomb')
        repo_name = main_config.get('repo_name', 'markitect_project')

        # Default configuration using main config values
        default_config = {
            'default_backend': 'gitea',
            'backends': {
                'gitea': {
                    'url': gitea_url,
                    'token': api_token,
                    'repo_owner': repo_owner,
                    'repo_name': repo_name,
                    'repo': f'{repo_owner}/{repo_name}'
                },
                'local': {
                    'directory': '.markitect/issues',
                    'auto_git': True
                }
            }
        }

        if not config_path.exists():
            return default_config

        try:
            with open(config_path, 'r') as f:
                config = yaml.safe_load(f) or {}

            # Merge with defaults
            merged_config = default_config.copy()
            merged_config.update(config)

            # Ensure gitea backend has token from main config if not overridden
            if 'backends' in merged_config and 'gitea' in merged_config['backends']:
                gitea_config = merged_config['backends']['gitea']
                if not gitea_config.get('token'):
                    gitea_config['token'] = api_token
                if not gitea_config.get('repo_owner'):
                    gitea_config['repo_owner'] = repo_owner
                if not gitea_config.get('repo_name'):
                    gitea_config['repo_name'] = repo_name

            return merged_config
        except Exception:
            # Return defaults if config loading fails
            return default_config

    def _discover_plugins(self) -> Dict[str, Type[IssueBackend]]:
        """
        Discover available backend plugins.

        Returns:
            Dictionary mapping backend names to plugin classes
        """
        plugins = {}

        # Try to import known plugins
        plugin_modules = [
            ('gitea', 'markitect.issues.plugins.gitea', 'GiteaPlugin'),
            ('local', 'markitect.issues.plugins.local', 'LocalPlugin'),
        ]

        for name, module_path, class_name in plugin_modules:
            try:
                module = importlib.import_module(module_path)
                plugin_class = getattr(module, class_name)
                if issubclass(plugin_class, IssueBackend):
                    plugins[name] = plugin_class
            except (ImportError, AttributeError):
                # Plugin not available, skip
                continue

        return plugins