"""
Base plugin classes for FileManager V2.

Hierarchy:
- BasePlugin: Base for ALL FileManager plugins (linters, formatters, analyzers)
- LinterPlugin: Specialized for linting/type checking
"""

import inspect
import logging
from abc import ABC, abstractmethod
from typing import Dict, Type, TYPE_CHECKING

if TYPE_CHECKING:
    from .plugin_manager import PluginManager
    from ..models import LintResults

logger = logging.getLogger(__name__)


class BasePlugin(ABC):
    """
    Base class for ALL FileManager plugins.

    Supports any type of file processing:
    - Linters (type checking, style checking)
    - Formatters (code formatting)
    - Analyzers (complexity analysis, coverage)

    Features:
    - Auto-registration via __init_subclass__
    - Plugin discovery via _registry
    - Lifecycle hooks (on_plugin_enabled)
    """

    _registry: Dict[str, Type['BasePlugin']] = {}

    def __init_subclass__(cls, **kwargs):
        """Auto-register all non-abstract plugins."""
        super().__init_subclass__(**kwargs)

        # Only register concrete classes (not abstract base classes)
        if not inspect.isabstract(cls):
            # Extract plugin name: "PyrightLinterPlugin" -> "pyright"
            plugin_name = cls.__name__.lower().replace('plugin', '').replace('linter', '')
            BasePlugin._registry[plugin_name] = cls
            logger.debug(f"Registered plugin: {plugin_name} -> {cls.__name__}")

    @property
    @abstractmethod
    def name(self) -> str:
        """Plugin name (e.g., 'pyright', 'black', 'prettier')."""
        pass

    def on_plugin_enabled(self, manager: 'PluginManager') -> None:
        """
        Optional: Called when plugin is enabled.

        Args:
            manager: PluginManager instance
        """
        pass


class LinterPlugin(BasePlugin):
    """
    Base class for linter plugins - inherits from BasePlugin.

    Linter plugins provide:
    - File type detection (can_handle_file)
    - Content linting (lint_content)
    - Optional custom hints (generate_hint)
    """

    @abstractmethod
    def can_handle_file(self, path: str) -> bool:
        """
        Check if this linter can handle the file type.

        Args:
            path: File path

        Returns:
            True if linter can process this file type
        """
        pass

    @abstractmethod
    def lint_content(self, path: str, content: str) -> 'LintResults':
        """
        Lint file content and return results.

        Args:
            path: File path
            content: File content

        Returns:
            LintResults with errors, warnings, and info
        """
        pass

    def generate_hint(self, path: str, results: 'LintResults') -> str:
        """
        Optional: Generate custom hints based on linting results.

        Args:
            path: File path
            results: Linting results

        Returns:
            Custom hint string
        """
        return ""
