"""Abstract base classes for LLMHosts plugins.

Every plugin inherits from :class:`LLMHostPlugin` and implements a
``register`` method that receives the FastAPI app and project config.

Three specialisation flavours are provided:

* :class:`MiddlewarePlugin` -- adds ASGI middleware to the request pipeline.
* :class:`BackendPlugin` -- registers additional LLM backends.
* :class:`HookPlugin` -- runs logic on startup / shutdown events.
"""

from __future__ import annotations

import abc
from enum import Enum
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from fastapi import FastAPI

    from llmhosts.config import LLMHostsConfig


class PluginType(str, Enum):
    """Classification of plugin purpose."""

    middleware = "middleware"
    backend = "backend"
    hook = "hook"


class LLMHostPlugin(abc.ABC):
    """Base class that every LLMHosts plugin must extend.

    Subclasses **must** implement :pyattr:`name`, :pyattr:`version`,
    :pyattr:`description`, and :pymeth:`register`.  The async lifecycle
    hooks :pymeth:`on_startup` and :pymeth:`on_shutdown` are optional.
    """

    @property
    @abc.abstractmethod
    def name(self) -> str:
        """Human-readable plugin name (unique identifier)."""

    @property
    @abc.abstractmethod
    def version(self) -> str:
        """SemVer version string (e.g. ``\"1.0.0\"``)."""

    @property
    @abc.abstractmethod
    def description(self) -> str:
        """One-line description of what this plugin does."""

    @property
    def plugin_type(self) -> PluginType:
        """Return the plugin type enum value.  Subclasses override this."""
        return PluginType.hook

    @abc.abstractmethod
    def register(self, app: FastAPI, config: LLMHostsConfig) -> None:
        """Called once during app setup to wire the plugin into the stack.

        Implementations may add middleware, include routers, attach state,
        etc.  Must **not** block or perform heavy I/O -- use
        :pymeth:`on_startup` for that.
        """

    async def on_startup(self) -> None:  # noqa: B027
        """Optional async hook invoked after the FastAPI app has started."""

    async def on_shutdown(self) -> None:  # noqa: B027
        """Optional async hook invoked before the FastAPI app shuts down."""

    def __repr__(self) -> str:
        return f"<{self.__class__.__name__} name={self.name!r} v{self.version}>"


class MiddlewarePlugin(LLMHostPlugin):
    """Plugin specialisation for adding ASGI middleware."""

    @property
    def plugin_type(self) -> PluginType:
        return PluginType.middleware


class BackendPlugin(LLMHostPlugin):
    """Plugin specialisation for registering additional LLM backends."""

    @property
    def plugin_type(self) -> PluginType:
        return PluginType.backend


class HookPlugin(LLMHostPlugin):
    """Plugin specialisation for startup / shutdown event hooks."""

    @property
    def plugin_type(self) -> PluginType:
        return PluginType.hook
