from abc import ABC, abstractmethod
from typing import Dict, Any, Optional
from .logger import belief_scope

from pydantic import BaseModel, Field

# [DEF:PluginBase:Class]
# @SEMANTICS: plugin, interface, base, abstract
# @PURPOSE: Defines the abstract base class that all plugins must implement to be recognized by the system. It enforces a common structure for plugin metadata and execution.
# @LAYER: Core
# @RELATION: Used by PluginLoader to identify valid plugins.
# @INVARIANT: All plugins MUST inherit from this class.
class PluginBase(ABC):
    """
    Base class for all plugins.
    Plugins must inherit from this class and implement the abstract methods.
    """

    @property
    @abstractmethod
    # [DEF:id:Function]
    # @PURPOSE: Returns the unique identifier for the plugin.
    # @PRE: Plugin instance exists.
    # @POST: Returns string ID.
    # @RETURN: str - Plugin ID.
    def id(self) -> str:
        """A unique identifier for the plugin."""
        with belief_scope("id"):
            pass
    # [/DEF:id:Function]

    @property
    @abstractmethod
    # [DEF:name:Function]
    # @PURPOSE: Returns the human-readable name of the plugin.
    # @PRE: Plugin instance exists.
    # @POST: Returns string name.
    # @RETURN: str - Plugin name.
    def name(self) -> str:
        """A human-readable name for the plugin."""
        with belief_scope("name"):
            pass
    # [/DEF:name:Function]

    @property
    @abstractmethod
    # [DEF:description:Function]
    # @PURPOSE: Returns a brief description of the plugin.
    # @PRE: Plugin instance exists.
    # @POST: Returns string description.
    # @RETURN: str - Plugin description.
    def description(self) -> str:
        """A brief description of what the plugin does."""
        with belief_scope("description"):
            pass
    # [/DEF:description:Function]

    @property
    @abstractmethod
    # [DEF:version:Function]
    # @PURPOSE: Returns the version of the plugin.
    # @PRE: Plugin instance exists.
    # @POST: Returns string version.
    # @RETURN: str - Plugin version.
    def version(self) -> str:
        """The version of the plugin."""
        with belief_scope("version"):
            pass
    # [/DEF:version:Function]

    @property
    # [DEF:required_permission:Function]
    # @PURPOSE: Returns the required permission string to execute this plugin.
    # @PRE: Plugin instance exists.
    # @POST: Returns string permission.
    # @RETURN: str - Required permission (e.g., "plugin:backup:execute").
    def required_permission(self) -> str:
        """The permission string required to execute this plugin."""
        with belief_scope("required_permission"):
            return f"plugin:{self.id}:execute"
    # [/DEF:required_permission:Function]

    @property
    # [DEF:ui_route:Function]
    # @PURPOSE: Returns the frontend route for the plugin's UI, if applicable.
    # @PRE: Plugin instance exists.
    # @POST: Returns string route or None.
    # @RETURN: Optional[str] - Frontend route.
    def ui_route(self) -> Optional[str]:
        """
        The frontend route for the plugin's UI.
        Returns None if the plugin does not have a dedicated UI page.
        """
        with belief_scope("ui_route"):
            return None
    # [/DEF:ui_route:Function]

    @abstractmethod
    # [DEF:get_schema:Function]
    # @PURPOSE: Returns the JSON schema for the plugin's input parameters.
    # @PRE: Plugin instance exists.
    # @POST: Returns dict schema.
    # @RETURN: Dict[str, Any] - JSON schema.
    def get_schema(self) -> Dict[str, Any]:
        """
        Returns the JSON schema for the plugin's input parameters.
        This schema will be used to generate the frontend form.
        """
        with belief_scope("get_schema"):
            pass
    # [/DEF:get_schema:Function]

    @abstractmethod
    # [DEF:execute:Function]
    # @PURPOSE: Executes the plugin's core logic.
    # @PARAM: params (Dict[str, Any]) - Validated input parameters.
    # @PRE: params must be a dictionary.
    # @POST: Plugin execution is completed.
    async def execute(self, params: Dict[str, Any]):
        with belief_scope("execute"):
            pass
        """
        Executes the plugin's logic.
        The `params` argument will be validated against the schema returned by `get_schema()`.
        """
        pass
    # [/DEF:execute:Function]
# [/DEF:PluginBase:Class]

# [DEF:PluginConfig:Class]
# @SEMANTICS: plugin, config, schema, pydantic
# @PURPOSE: A Pydantic model used to represent the validated configuration and metadata of a loaded plugin. This object is what gets exposed to the API layer.
# @LAYER: Core
# @RELATION: Instantiated by PluginLoader after validating a PluginBase instance.
class PluginConfig(BaseModel):
    """Pydantic model for plugin configuration."""
    id: str = Field(..., description="Unique identifier for the plugin")
    name: str = Field(..., description="Human-readable name for the plugin")
    description: str = Field(..., description="Brief description of what the plugin does")
    version: str = Field(..., description="Version of the plugin")
    ui_route: Optional[str] = Field(None, description="Frontend route for the plugin UI")
    input_schema: Dict[str, Any] = Field(..., description="JSON schema for input parameters", alias="schema")
# [/DEF:PluginConfig:Class]