#!/usr/bin/env python3
"""Generate Typst tables of unit tests for chapter 5."""
from __future__ import annotations

import re
from collections import defaultdict
from pathlib import Path


def typst_escape(s: str) -> str:
    return s.replace("\\", "\\\\").replace("`", "\\`")


def emit_table(
    lines: list[str],
    caption: str,
    ncol: int,
    headers: list[str],
    data_rows: list[list[str]],
    label: str,
) -> None:
    lines.append("#pz-test-table(\n")
    lines.append(f"  [{caption}],\n")
    lines.append(f"  {ncol},\n")
    lines.append("  table.header(\n")
    for h in headers:
        lines.append(f"    [{typst_escape(h)}],\n")
    lines.append("  ),\n")
    for row in data_rows:
        cells = ", ".join(f"[{typst_escape(c)}]" for c in row)
        lines.append(f"  {cells},\n")
    lines.append(f") <{label}>\n\n")


def main() -> None:
    root = Path(__file__).resolve().parents[2]
    out = Path(__file__).resolve().parents[1] / "includes" / "ch05-tests-generated.typ"
    rows: list[tuple[str, str, str, str]] = []

    for p in sorted(root.rglob("*.kt")):
        if "/src/test/" not in p.as_posix():
            continue
        text = p.read_text(encoding="utf-8", errors="replace")
        cls_m = re.search(r"class\s+(\w+)", text)
        if not cls_m:
            continue
        cls = cls_m.group(1)
        mod = p.parts[p.parts.index("src") - 1]
        rel = p.relative_to(root).as_posix()
        for m in re.finditer(r"@Test[\s\S]*?fun\s+(?:`([^`]+)`|(\w+))\s*\(", text):
            name = m.group(1) or m.group(2)
            rows.append((mod, cls, name, rel))

    by_mod: dict[str, list] = defaultdict(list)
    for mod, cls, name, rel in rows:
        by_mod[mod].append((cls, name, rel))

    lines = [
        "// AUTO-GENERATED by gen_test_tables.py — include from ch05.typ\n",
        '#import "common.typ": pz-test-table\n\n',
    ]

    summary_rows = []
    for mod in sorted(by_mod):
        for cls, name, rel in by_mod[mod]:
            short = rel.split("/")[-1]
            summary_rows.append([mod, cls, name, short])

    emit_table(
        lines,
        "Сводка модульных unit-тестов (src/test)",
        4,
        ["Модуль", "Класс", "Метод", "Файл"],
        summary_rows,
        "tbl-unit-all",
    )

    for mod in sorted(by_mod):
        safe = mod.replace("-", "_")
        lines.append(f"=== Реестр тестов модуля :{mod}\n\n")
        mod_rows = [
            [cls, name, rel.split("/")[-1]]
            for cls, name, rel in by_mod[mod]
        ]
        emit_table(
            lines,
            f"Unit-тесты модуля :{mod}",
            3,
            ["Класс", "Метод", "Файл"],
            mod_rows,
            f"tbl-unit-{safe}",
        )

    out.write_text("".join(lines), encoding="utf-8")
    print(f"Wrote {out} ({len(rows)} tests)", flush=True)


if __name__ == "__main__":
    main()
