"""Step definitions for cli_renderers_coverage.feature.

Tests the four shared renderer helpers (render_error, render_success,
render_warning, render_empty) across all output formats to ensure full
branch coverage of ``cleveragents.cli.renderers``.
"""

from __future__ import annotations

import contextlib
from io import StringIO

from behave import given, then, when
from behave.runner import Context
from rich.console import Console

from cleveragents.cli.renderers import (
    render_empty,
    render_error,
    render_success,
    render_warning,
)


@given("a captured console for renderers")
def step_captured_console(context: Context) -> None:
    """Create a Rich Console that writes to a StringIO buffer."""
    context.renderer_buf = StringIO()
    context.renderer_stdout = StringIO()
    context.renderer_console = Console(
        file=context.renderer_buf,
        width=200,
        no_color=True,
        highlight=False,
        force_terminal=False,
    )
    context.renderer_recovery = None


def _get_output(context: Context) -> str:
    """Combine Rich console buffer and any direct stdout writes."""
    return context.renderer_buf.getvalue() + context.renderer_stdout.getvalue()


@given('a recovery hint "{recovery}"')
def step_set_recovery(context: Context, recovery: str) -> None:
    """Store a recovery hint for the next renderer call."""
    context.renderer_recovery = recovery


# ---------------------------------------------------------------------------
# render_error
# ---------------------------------------------------------------------------


@when('I call render_error with label "{label}" message "{msg}" fmt "{fmt}"')
def step_call_render_error(context: Context, label: str, msg: str, fmt: str) -> None:
    """Invoke render_error with the given parameters."""
    recovery = getattr(context, "renderer_recovery", None)
    with contextlib.redirect_stdout(context.renderer_stdout):
        render_error(
            label,
            msg,
            fmt=fmt,
            recovery=recovery,
            console=context.renderer_console,
        )


# ---------------------------------------------------------------------------
# render_success
# ---------------------------------------------------------------------------


@when('I call render_success with message "{msg}" fmt "{fmt}"')
def step_call_render_success(context: Context, msg: str, fmt: str) -> None:
    """Invoke render_success with the given parameters."""
    with contextlib.redirect_stdout(context.renderer_stdout):
        render_success(msg, fmt=fmt, console=context.renderer_console)


# ---------------------------------------------------------------------------
# render_warning
# ---------------------------------------------------------------------------


@when('I call render_warning with message "{msg}" fmt "{fmt}"')
def step_call_render_warning(context: Context, msg: str, fmt: str) -> None:
    """Invoke render_warning with the given parameters."""
    with contextlib.redirect_stdout(context.renderer_stdout):
        render_warning(msg, fmt=fmt, console=context.renderer_console)


# ---------------------------------------------------------------------------
# render_empty
# ---------------------------------------------------------------------------


@when('I call render_empty with entity_type "{etype}" fmt "{fmt}"')
def step_call_render_empty(context: Context, etype: str, fmt: str) -> None:
    """Invoke render_empty with the given parameters."""
    recovery = getattr(context, "renderer_recovery", None)
    with contextlib.redirect_stdout(context.renderer_stdout):
        render_empty(
            etype,
            fmt=fmt,
            recovery=recovery,
            console=context.renderer_console,
        )


# ---------------------------------------------------------------------------
# THEN assertions
# ---------------------------------------------------------------------------


@then('the renderer output should contain "{expected}"')
def step_renderer_output_contains(context: Context, expected: str) -> None:
    """Assert the captured output contains the expected text."""
    output = _get_output(context)
    assert expected in output, (
        f"Expected {expected!r} in renderer output, got:\n{output}"
    )
