"""Plugin discovery and mounting via importlib.metadata entry_points.

CLI plugins: entry_points group = "kuberoku.plugins"
  - Package name determines command name: kuberoku-mongodb -> "mongodb"
  - Each plugin is a Click group mounted as a top-level command
  - Core commands are protected (cannot be overridden)

Addon plugins: entry_points group = "kuberoku.addons"
  - Each entry point provides an AddonDef instance
  - Built-in types (postgres, redis) are protected
"""

from __future__ import annotations

import importlib.metadata
import sys
import warnings
from typing import TYPE_CHECKING

from kuberoku.branding import PLUGIN_GROUP, PLUGIN_PREFIX

if TYPE_CHECKING:
    import click

CORE_COMMANDS = frozenset(
    {
        "apps",
        "config",
        "deploy",
        "ps",
        "releases",
        "services",
        "addons",
        "domains",
        "clusters",
        "plugins",
    }
)


def _is_frozen() -> bool:
    """Check if running as a PyInstaller frozen binary."""
    return getattr(sys, "frozen", False)


def load_plugins(root_group: click.Group) -> list[str]:
    """Discover and mount installed kuberoku-* plugins. Returns loaded names."""
    if _is_frozen():
        return []

    eps = importlib.metadata.entry_points(group=PLUGIN_GROUP)
    loaded: list[str] = []

    for ep in eps:
        dist = ep.dist
        if dist is None:
            continue

        package_name = dist.name
        command_name = package_name.removeprefix(PLUGIN_PREFIX)

        if command_name in CORE_COMMANDS:
            warnings.warn(
                f"Plugin '{package_name}' conflicts with core command '{command_name}'. Skipped.",
                stacklevel=2,
            )
            continue

        try:
            plugin_group = ep.load()
            root_group.add_command(plugin_group, command_name)
            loaded.append(command_name)
        except Exception:
            warnings.warn(
                f"Failed to load plugin '{package_name}'.",
                stacklevel=2,
            )

    return loaded
