"""Security-oriented step definitions for actor run signature tests."""

from __future__ import annotations

import contextlib
from typing import Any
from unittest.mock import MagicMock, patch

import click
import typer
from behave import then, when

with contextlib.suppress(ImportError, ModuleNotFoundError):
    from cleveragents.cli.commands._resolve_actor import resolve_config_files
from cleveragents.core.exceptions import NotFoundError


@when("I call resolve_config_files with a control-character actor name")
def step_resolve_with_control_character_name(context: Any) -> None:
    actor_name = "local/\x1b[31mevil\x1b[0m\x00actor"

    mock_registry = MagicMock()
    mock_registry.get.side_effect = NotFoundError(
        resource_type="actor",
        resource_id=actor_name,
    )

    mock_container = MagicMock()
    mock_container.actor_registry.return_value = mock_registry

    captured_stderr: list[str] = []
    original_echo = typer.echo

    def _capture_echo(message: str = "", err: bool = False, **kwargs: Any) -> None:
        if err:
            captured_stderr.append(message)
        original_echo(message, err=err, **kwargs)

    with (
        patch(
            "cleveragents.cli.commands._resolve_actor.get_container",
            return_value=mock_container,
        ),
        patch(
            "cleveragents.cli.commands._resolve_actor.typer.echo",
            side_effect=_capture_echo,
        ),
    ):
        try:
            resolve_config_files(actor_name, [])
            context.resolve_exit_code = 0
        except (SystemExit, click.exceptions.Exit) as exc:
            context.resolve_exit_code = getattr(
                exc, "exit_code", getattr(exc, "code", 1)
            )

    context.resolve_stderr = " ".join(captured_stderr)


@then("the not-found error should not include control characters")
def step_error_sanitises_control_characters(context: Any) -> None:
    assert context.resolve_exit_code == 2
    assert "not found in registry" in context.resolve_stderr
    assert "\x1b" not in context.resolve_stderr
    assert "\x00" not in context.resolve_stderr
    assert "evil" in context.resolve_stderr
