"""Unified CLI output renderers.

Shared output functions for every CLI command: detail views, list views,
errors, successes, warnings, and empty-result placeholders.  All respect
the ``--format`` flag (rich/color/table/plain/json/yaml).

Provides ``_get_console()`` and ``_get_err_console()`` for lazy-initialised
shared Console instances, eliminating redundant module-level Console objects
across command modules.
"""

from __future__ import annotations

from typing import Any

from rich.console import Console
from rich.markup import escape as _esc

from cleveragents.cli.formatting import (
    OutputFormat,
    format_output,
)

__all__ = [
    "_get_console",
    "_get_err_console",
    "render_empty",
    "render_error",
    "render_success",
    "render_warning",
]


# Console helpers
_console: Console | None = None
_err_console: Console | None = None


def _get_console() -> Console:
    """Return the shared stdout Rich console (created on first call)."""
    global _console
    if _console is None:
        _console = Console()
    return _console


def _get_err_console() -> Console:
    """Return the shared stderr Rich console (created on first call)."""
    global _err_console
    if _err_console is None:
        _err_console = Console(stderr=True)
    return _err_console


# render_error


def render_error(
    label: str,
    message: str,
    *,
    recovery: str | None = None,
    details: dict[str, Any] | None = None,
    fmt: str = OutputFormat.RICH.value,
    console: Console | None = None,
) -> None:
    """Render a uniform error message.

    Parameters
    ----------
    label:
        Short error category (e.g. ``"Validation Error"``).
    message:
        Human-readable description of what went wrong.
    recovery:
        Optional recovery hint.
    details:
        Optional structured details dict for JSON/YAML.
    fmt:
        Output format string.
    """
    console = console or _get_err_console()

    if fmt in (OutputFormat.JSON.value, OutputFormat.YAML.value):
        envelope: dict[str, Any] = {
            "error": {
                "code": label,
                "message": message,
                "details": details or {},
            }
        }
        if recovery:
            envelope["error"]["recovery"] = recovery
        console.print(format_output(envelope, fmt))
        return

    if fmt in (OutputFormat.PLAIN.value, OutputFormat.TABLE.value):
        console.print(f"ERROR: {label}: {message}")
        if recovery:
            console.print(recovery)
        return

    # Rich / Color
    console.print(f"[red]{_esc(label)}:[/red] {_esc(message)}")
    if recovery:
        console.print(f"[dim]{_esc(recovery)}[/dim]")


# render_success


def render_success(
    message: str,
    *,
    fmt: str = OutputFormat.RICH.value,
    data: dict[str, Any] | None = None,
    console: Console | None = None,
) -> None:
    """Render a green success confirmation.

    Parameters
    ----------
    message:
        Confirmation text.
    fmt:
        Output format string.
    data:
        Optional dict to render as JSON/YAML instead of the plain message.
    """
    console = console or _get_console()

    if fmt in (OutputFormat.JSON.value, OutputFormat.YAML.value):
        payload = data if data is not None else {"status": "ok", "message": message}
        console.print(format_output(payload, fmt))
        return

    if fmt == OutputFormat.PLAIN.value:
        console.print(f"OK: {message}")
        return

    console.print(f"[green]\u2713[/green] {_esc(message)}")


# render_warning


def render_warning(
    message: str,
    *,
    fmt: str = OutputFormat.RICH.value,
    console: Console | None = None,
) -> None:
    """Render a yellow advisory message.

    Parameters
    ----------
    message:
        Warning text.
    fmt:
        Output format string.
    """
    console = console or _get_console()

    if fmt in (OutputFormat.JSON.value, OutputFormat.YAML.value):
        payload = {"status": "warning", "message": message}
        console.print(format_output(payload, fmt))
        return

    if fmt == OutputFormat.PLAIN.value:
        console.print(f"WARNING: {message}")
        return

    console.print(f"[yellow]{_esc(message)}[/yellow]")


# render_empty


def render_empty(
    entity_type: str,
    *,
    message: str | None = None,
    recovery: str | None = None,
    fmt: str = OutputFormat.RICH.value,
    console: Console | None = None,
) -> None:
    """Render a "no items found" message with optional recovery hint.

    Parameters
    ----------
    entity_type:
        Plural noun (e.g. ``"actions"``, ``"projects"``).
    message:
        Override the default ``"No {entity_type} found."`` text.
    recovery:
        Suggestion for what to do next.
    fmt:
        Output format string.
    """
    console = console or _get_console()
    text = message or f"No {entity_type} found."

    if fmt in (OutputFormat.JSON.value, OutputFormat.YAML.value):
        console.print(format_output([], fmt))
        return

    if fmt in (OutputFormat.PLAIN.value, OutputFormat.TABLE.value):
        console.print(text)
        if recovery:
            console.print(recovery)
        return

    console.print(f"[yellow]{_esc(text)}[/yellow]")
    if recovery:
        console.print(_esc(recovery))
