"""CLI tests for `attractor render`. SPEC §13.

Unit-level coverage of the serializer lives in
`tests/test_workflow/test_serialize.py`; this file drives the CLI
surface end-to-end via `click.testing.CliRunner`.
"""

from __future__ import annotations

from pathlib import Path

from click.testing import CliRunner

from attractor.cli.main import cli

_VALID = """\
digraph V {
    start [shape=Mdiamond, label="S"]
    exit  [shape=Msquare,  label="E"]
    work  [shape=parallelogram, script="echo work"]
    start -> work -> exit
}
"""

_PARSE_ERROR = "digraph X {\n    start [shape=Mdiamond\n}\n"

_VALIDATION_ERROR = """\
digraph NoExit {
    start [shape=Mdiamond, label="S"]
    a [shape=parallelogram, script="true"]
    start -> a
}
"""


# [int->REQ-CLI-RENDER]
def test_render_emits_canonical_dot_on_stdout(tmp_path: Path) -> None:
    wf = tmp_path / "wf.dot"
    wf.write_text(_VALID, encoding="utf-8")
    result = CliRunner().invoke(cli, ["render", str(wf)])
    assert result.exit_code == 0, result.output
    assert result.output.startswith("digraph V {")
    assert "start" in result.output
    assert "work" in result.output
    assert "exit" in result.output
    assert "->" in result.output


# [int->REQ-CLI-RENDER]
def test_render_output_reparses(tmp_path: Path) -> None:
    """The CLI output must itself parse + validate."""
    wf = tmp_path / "wf.dot"
    wf.write_text(_VALID, encoding="utf-8")
    result = CliRunner().invoke(cli, ["render", str(wf)])
    assert result.exit_code == 0, result.output

    from attractor.workflow import parse, validate
    reparsed = parse(result.output)
    valid = validate(reparsed)
    assert len(valid.nodes) == 3
    assert len(valid.edges) == 2


# [int->REQ-CLI-RENDER]
def test_render_missing_file_exits_2(tmp_path: Path) -> None:
    missing = tmp_path / "does-not-exist.dot"
    result = CliRunner().invoke(cli, ["render", str(missing)])
    assert result.exit_code == 2
    assert "not found" in result.output.lower()


# [int->REQ-CLI-RENDER]
def test_render_parse_error_exits_2_with_diagnostics(tmp_path: Path) -> None:
    wf = tmp_path / "bad.dot"
    wf.write_text(_PARSE_ERROR, encoding="utf-8")
    result = CliRunner().invoke(cli, ["render", str(wf)])
    assert result.exit_code == 2
    # `<file>:<line>:<col>: <message>` diagnostic format.
    assert str(wf) in result.output
    assert ":" in result.output


# [int->REQ-CLI-RENDER]
def test_render_validation_error_exits_2(tmp_path: Path) -> None:
    wf = tmp_path / "novexit.dot"
    wf.write_text(_VALIDATION_ERROR, encoding="utf-8")
    result = CliRunner().invoke(cli, ["render", str(wf)])
    assert result.exit_code == 2
    assert str(wf) in result.output
