"""Unit tests for the agent-progress preview helper (REQ-AGENT-PROGRESS-EVENTS).

`_preview_tool_args` renders a tool call's args dict as a short,
secrets-conservative summary that lands in
:class:`attractor.engine.events.AgentToolUse`. Pure / side-effect-free
so we can exercise the truncation policy without spawning pi.
"""

from __future__ import annotations

from attractor.agent.runner import (
    _preview_tool_args,  # pyright: ignore[reportPrivateUsage]
)


# [unit->REQ-AGENT-PROGRESS-EVENTS]
def test_preview_empty_input_returns_empty_string() -> None:
    """No args (None or empty dict) renders as the empty string."""
    assert _preview_tool_args(None) == ""
    assert _preview_tool_args({}) == ""


# [unit->REQ-AGENT-PROGRESS-EVENTS]
def test_preview_single_key_simple_value() -> None:
    """Typical Read-style call: one key, short value, no truncation."""
    assert _preview_tool_args({"file_path": "SPEC.md"}) == "file_path=SPEC.md"


# [unit->REQ-AGENT-PROGRESS-EVENTS]
def test_preview_multi_key_joined_by_comma_space() -> None:
    """Multi-key dict joins with `, ` between entries (preserves insertion order)."""
    out = _preview_tool_args({"pattern": "TODO", "path": "src/"})
    assert out == "pattern=TODO, path=src/"


# [unit->REQ-AGENT-PROGRESS-EVENTS]
def test_preview_truncates_long_value_at_40_chars() -> None:
    """A long single value gets clipped to 37 chars + `...` (40 total).

    Guards against a prompt or free-form string spilling secrets into
    progress output or filling the terminal with one tool call.
    """
    long_value = "x" * 200
    out = _preview_tool_args({"prompt": long_value})
    # 37 x's + "..." = 40-char value; prefix is "prompt="
    assert out == f"prompt={'x' * 37}..."
    assert len(out) == len("prompt=") + 40


# [unit->REQ-AGENT-PROGRESS-EVENTS]
def test_preview_truncates_whole_line_at_max_chars() -> None:
    """Many short values together can exceed the line cap — clip the line."""
    args = {f"k{i}": "v" for i in range(50)}
    out = _preview_tool_args(args, max_chars=100)
    assert len(out) <= 100
    assert out.endswith("...")


# [unit->REQ-AGENT-PROGRESS-EVENTS]
def test_preview_coerces_non_string_values() -> None:
    """Ints, bools, lists all str-coerce — no TypeError, no silent drop."""
    out = _preview_tool_args({"limit": 5, "recursive": True, "globs": ["*.py"]})
    assert "limit=5" in out
    assert "recursive=True" in out
    assert "globs=['*.py']" in out


# [unit->REQ-AGENT-PROGRESS-EVENTS]
def test_preview_bash_style_command_survives() -> None:
    """A typical Bash command (under 40 chars) lands intact in the preview."""
    out = _preview_tool_args({"command": "uv run pytest -k routing"})
    assert out == "command=uv run pytest -k routing"
