"""PAPER-05 — ``--resume`` preserves the run record; machine rollup.

Before the fix, ``Supervisor.run()`` unconditionally unlinked
``run.jsonl`` (and the failure bundles) at the start of every run, so a
resumed run's record covered ONLY the resumed subset — everything that
ran before the interruption was silently erased, defeating the point of
resumability. And the only end-of-run artifacts were the human
``summary.md`` + per-test ``run.jsonl``: no consolidated verdict a CI
system could ingest without re-parsing prose.

Pins:
  * ``resume=True`` appends to ``run.jsonl`` and keeps prior failure
    bundles; outcomes seeded from state.json make ``summary.md`` /
    ``summary.json`` cover the FULL suite across the interruption.
  * A failure recorded before the interruption still reds the resumed
    run's exit code (resume must not launder red into green).
  * ``summary.json`` (counts + per-outcome id lists) and a consolidated
    ``junit.xml`` are emitted alongside ``summary.md``.
  * A fresh run (``resume=False``) still wipes — retention stays
    bounded (README OP-08).
"""

from __future__ import annotations

import json
import sys
import xml.etree.ElementTree as ET
from typing import TYPE_CHECKING

import pytest

from mgf.test_supervisor.records import read_jsonl
from mgf.test_supervisor.supervisor import RunConfig, Supervisor

if TYPE_CHECKING:
    from pathlib import Path

_SUITE = """\
def test_ok_one():
    assert True


def test_ok_two():
    assert True


def test_red():
    raise AssertionError("deliberate failure (PAPER-05 pin)")
"""

ID_OK_ONE = "tests/test_resume_suite.py::test_ok_one"
ID_OK_TWO = "tests/test_resume_suite.py::test_ok_two"
ID_RED = "tests/test_resume_suite.py::test_red"


def _write_consumer_project(root: Path) -> None:
    (root / "pyproject.toml").write_text("[tool.pytest.ini_options]\n", encoding="utf-8")
    tests_dir = root / "tests"
    tests_dir.mkdir()
    (tests_dir / "test_resume_suite.py").write_text(_SUITE, encoding="utf-8")


def _cfg(root: Path, test_ids: list[str], run_id: str, *, resume: bool = False) -> RunConfig:
    return RunConfig(
        repo_root=root,
        gates_dir=root / ".gates",
        test_ids=test_ids,
        test_markers={},
        run_id=run_id,
        pytest_cmd=[sys.executable, "-m", "pytest"],
        resume=resume,
    )


@pytest.mark.integration
@pytest.mark.regression
@pytest.mark.timeout(120)
def test_resume_appends_record_and_rollup_covers_full_suite(tmp_path: Path) -> None:
    _write_consumer_project(tmp_path)
    last_run = tmp_path / ".gates" / "last-run"

    # "Interrupted" first run: one green + one red test completed.
    rc1 = Supervisor(_cfg(tmp_path, [ID_OK_ONE, ID_RED], "run-1")).run()
    assert rc1 == 1
    first = {r["test_id"] for r in read_jsonl(last_run / "run.jsonl")}
    assert first == {ID_OK_ONE, ID_RED}
    bundles_before = list((last_run / "failures").iterdir())
    assert bundles_before, "failure bundle expected for test_red"

    # Resumed run: only the remaining test — the record must APPEND.
    rc2 = Supervisor(_cfg(tmp_path, [ID_OK_TWO], "run-2", resume=True)).run()
    # The pre-interruption failure still reds the resumed completion.
    assert rc2 == 1
    records = {r["test_id"]: r["outcome"] for r in read_jsonl(last_run / "run.jsonl")}
    assert records == {ID_OK_ONE: "passed", ID_RED: "failed", ID_OK_TWO: "passed"}
    assert list((last_run / "failures").iterdir()) == bundles_before

    # summary.json — machine rollup over the FULL suite (PAPER-05).
    rollup = json.loads((last_run / "summary.json").read_text(encoding="utf-8"))
    assert rollup["total"] == 3
    assert rollup["counts"] == {"passed": 2, "failed": 1}
    assert rollup["outcomes"]["failed"] == [ID_RED]
    assert rollup["ok"] is False
    assert rollup["run_id"] == "run-2"

    # summary.md covers all 3 tests, not just the resumed subset.
    summary_md = (last_run / "summary.md").read_text(encoding="utf-8")
    assert "tests run: 3" in summary_md

    # junit.xml — consolidated, built from run.jsonl records.
    tree = ET.parse(last_run / "junit.xml")  # noqa: S314 — supervisor-written file
    suite = tree.getroot().find("testsuite")
    assert suite is not None
    assert suite.get("tests") == "3"
    assert suite.get("failures") == "1"
    assert suite.get("errors") == "0"
    names = {tc.get("name") for tc in suite.iter("testcase")}
    assert names == {"test_ok_one", "test_ok_two", "test_red"}

    # Fresh run (resume=False) wipes again — bounded retention (OP-08).
    rc3 = Supervisor(_cfg(tmp_path, [ID_OK_ONE], "run-3")).run()
    assert rc3 == 0
    records3 = {r["test_id"] for r in read_jsonl(last_run / "run.jsonl")}
    assert records3 == {ID_OK_ONE}
    assert list((last_run / "failures").iterdir()) == []
    rollup3 = json.loads((last_run / "summary.json").read_text(encoding="utf-8"))
    assert rollup3["total"] == 1
    assert rollup3["ok"] is True
