#!/usr/bin/env python3
"""Tests for regen-readme.py.

Dependency-free: run with `python code-reviews/test_regen_readme.py`.
Exits 0 if all tests pass, 1 otherwise.
"""
from __future__ import annotations

import importlib.util
import tempfile
import traceback
from pathlib import Path

HERE = Path(__file__).resolve().parent

# regen-readme.py is not an importable module name (hyphen), so load it by path.
_spec = importlib.util.spec_from_file_location("regen_readme", HERE / "regen-readme.py")
regen = importlib.util.module_from_spec(_spec)
_spec.loader.exec_module(regen)

FIXTURE = """# Code Review — Demo

| Field | Value |
|---|---|
| Module | `src/Demo` |
| Reviewer | Tester |
| Review date | 2026-05-18 |
| Commit reviewed | `abc1234` |
| Status | Reviewed |
| Open findings | 1 |

## Findings

### Demo-001

| Field | Value |
|---|---|
| Severity | High |
| Category | Security |
| Location | `src/Demo/File.cs:10` |
| Status | Open |

**Description:** A first problem that matters.

**Recommendation:** Fix it.

**Resolution:** _(open)_

### Demo-002

| Field | Value |
|---|---|
| Severity | Low |
| Category | Documentation & comments |
| Location | `src/Demo/File.cs:20` |
| Status | Resolved |

**Description:** A second, minor problem.

**Recommendation:** Tidy it.

**Resolution:** Fixed in def5678 on 2026-05-18.
"""


def _parse_fixture() -> dict:
    """Write FIXTURE to a temp Demo/findings.md and parse it."""
    with tempfile.TemporaryDirectory() as tmp:
        path = Path(tmp) / "Demo" / "findings.md"
        path.parent.mkdir()
        path.write_text(FIXTURE, encoding="utf-8")
        return regen.parse_module(path)


def test_first_table_skips_separator_and_field_header():
    table = regen.first_table("| Field | Value |\n|---|---|\n| Severity | High |\n")
    assert table == {"Severity": "High"}, table


def test_parse_module_header():
    m = _parse_fixture()
    assert m["module"] == "Demo", m["module"]
    assert m["header"]["Reviewer"] == "Tester"
    assert m["header"]["Status"] == "Reviewed"
    assert m["header"]["Open findings"] == "1"


def test_parse_module_findings():
    m = _parse_fixture()
    assert len(m["findings"]) == 2, len(m["findings"])
    first = m["findings"][0]
    assert first["id"] == "Demo-001"
    assert first["severity"] == "High"
    assert first["category"] == "Security"
    assert first["location"] == "`src/Demo/File.cs:10`"
    assert first["status"] == "Open"
    assert first["description"] == "A first problem that matters."
    assert m["findings"][1]["status"] == "Resolved"


def test_build_readme_splits_pending_and_closed():
    readme = regen.build_readme([_parse_fixture()])
    assert "## Pending findings" in readme
    assert "## Closed findings" in readme
    pending, closed = readme.split("## Closed findings", 1)
    assert "Demo-001" in pending  # Open -> pending
    assert "Demo-001" not in closed
    assert "Demo-002" in closed  # Resolved -> closed
    assert "_No pending findings._" not in pending


def test_find_inconsistencies_clean_fixture():
    assert regen.find_inconsistencies([_parse_fixture()]) == []


def test_find_inconsistencies_detects_wrong_open_count():
    m = _parse_fixture()
    m["header"]["Open findings"] = "7"
    issues = regen.find_inconsistencies([m])
    assert len(issues) == 1 and "Open findings" in issues[0], issues


def test_find_inconsistencies_detects_unknown_status():
    m = _parse_fixture()
    m["findings"][0]["status"] = "Bogus"
    issues = regen.find_inconsistencies([m])
    # Wrong status also shifts the open count, so expect the status issue present.
    assert any("unrecognised Status" in i for i in issues), issues


def test_summarize_truncates_long_text():
    long = "x" * 500
    out = regen.summarize(long)
    assert len(out) <= 240 and out.endswith("…"), len(out)
    assert regen.summarize("short") == "short"


def main() -> int:
    tests = sorted(
        (name, fn)
        for name, fn in globals().items()
        if name.startswith("test_") and callable(fn)
    )
    failed = 0
    for name, fn in tests:
        try:
            fn()
            print(f"PASS {name}")
        except Exception:  # noqa: BLE001 - test runner reports all failures
            failed += 1
            print(f"FAIL {name}")
            traceback.print_exc()
    print(f"\n{len(tests) - failed}/{len(tests)} passed.")
    return 1 if failed else 0


if __name__ == "__main__":
    raise SystemExit(main())
