"""Parameterized preview namespace utilities.

Provides warning banners, decorators, and base classes for preview features
(alpha, beta, etc.). All functions accept a ``namespace`` parameter so the
same logic drives every stability tier.
"""

import functools
import sys
import threading
from typing import Any, Callable, TypeVar

from rich.console import Console
from rich.panel import Panel

F = TypeVar("F", bound=Callable[..., Any])

_warned_features: set[str] = set()
_warned_features_lock = threading.Lock()


def make_warning_text(namespace: str) -> str:
    ns_lower = namespace.lower()
    article = "an" if ns_lower[0] in "aeiou" else "a"
    return (
        f"This is {article} {ns_lower} feature that is unstable and subject to change.\n"
        "\n"
        "- APIs may change in breaking ways between releases\n"
        "- Functionality may be incomplete or contain bugs\n"
        f"- This feature could be removed at any time without notice\n"
        f"- Access is currently limited to select users during the {ns_lower} period\n"
        "\n"
        "For questions or feedback, contact the Komodo team."
    )


def make_warning_short(namespace: str) -> str:
    ns_cap = namespace.capitalize()
    return f"{ns_cap} feature: unstable, may change or be removed without notice. " f"Access limited to select {namespace.lower()} users."


def show_preview_warning(
    console: Console,
    namespace: str,
    feature_name: str = "Feature",
    short: bool = False,
) -> None:
    """Display a preview-feature warning banner.

    Args:
        console: Rich console instance for output.
        namespace: Preview tier name (e.g. "alpha", "beta").
        feature_name: Name of the feature being warned about.
        short: If True, show a compact single-line warning instead of a panel.
    """
    ns_upper = namespace.upper()
    if short:
        console.print(f"\n[bold yellow]\u26a0\ufe0f  {feature_name}:[/bold yellow] " f"{make_warning_short(namespace)}\n")
    else:
        console.print()
        console.print(
            Panel(
                f"[yellow]{make_warning_text(namespace)}[/yellow]",
                title=f"[bold yellow]\u26a0\ufe0f  {ns_upper}: {feature_name}[/bold yellow]",
                border_style="yellow",
            )
        )
        console.print()


def preview_warning(
    namespace: str,
    feature_name: str = "This feature",
    stacklevel: int = 4,
) -> None:
    """Emit a stderr warning for preview feature usage (once per feature per session).

    Args:
        namespace: Preview tier name (e.g. "alpha", "beta").
        feature_name: Name of the feature being warned about.
        stacklevel: Unused, kept for backwards compatibility.
    """
    ns_upper = namespace.upper()
    key = f"{namespace}:{feature_name}"

    with _warned_features_lock:
        if key in _warned_features:
            return
        _warned_features.add(key)

    message = (
        f"\n\033[33m\u26a0\ufe0f  {ns_upper}: {feature_name}\033[0m\n"
        f"\033[33mThis feature is in {namespace.lower()} and may change or be removed without notice.\n"
        f"Access is limited to select {namespace.lower()} users.\033[0m\n"
    )
    sys.stderr.write(message)
    sys.stderr.flush()


def preview(namespace: str, feature_name: str | None = None) -> Callable[[F], F]:
    """Decorator to mark a function or method as a preview feature.

    Args:
        namespace: Preview tier name (e.g. "alpha", "beta").
        feature_name: Optional name for the feature. Falls back to ``func.__name__``.

    Returns:
        Decorator function.
    """

    def decorator(func: F) -> F:
        @functools.wraps(func)
        def wrapper(*args: Any, **kwargs: Any) -> Any:
            name = feature_name or func.__name__
            preview_warning(namespace, name)
            return func(*args, **kwargs)

        return wrapper  # type: ignore

    return decorator


class PreviewAccessor:
    """Base class for preview feature accessors.

    Subclasses should implement preview feature access with
    appropriate warnings.
    """

    _warned: bool = False

    def _warn_once(self, namespace: str, feature_name: str) -> None:
        """Emit a warning once for this accessor instance."""
        if not self._warned:
            preview_warning(namespace, feature_name)
            self._warned = True
