#!/usr/bin/env python3
"""
Master-Test-Runner fuer das EEG-Abrechnungs-Lizenzsystem.

Fuehrt alle Phasen-Tests sequentiell aus, isoliert Python-Cache pro Lauf,
und fasst Pass/Fail am Ende zusammen.

Aufruf (aus v1_upload/ heraus):
    python tests/run_all_tests.py
    python tests/run_all_tests.py --only 7         # nur Phase 7
    python tests/run_all_tests.py --skip 5,6       # Phase 5 und 6 auslassen
    python tests/run_all_tests.py --verbose        # volle Ausgabe jedes Tests
"""
from __future__ import annotations

import argparse
import os
import subprocess
import sys
import tempfile
import time
from pathlib import Path

TESTS_DIR = Path(__file__).resolve().parent
PROJECT_ROOT = TESTS_DIR.parent

try:
    sys.stdout.reconfigure(encoding='utf-8', errors='replace')
    sys.stderr.reconfigure(encoding='utf-8', errors='replace')
except Exception:
    pass

PHASES = [
    (5, "test_phase5.py", "Atomare Token-Abbuchung + Session-Replay-Schutz"),
    (6, "test_phase6.py", "Admin-Web-UI + DB-Session-Auth + Audit-Log"),
    (7, "test_phase7.py", "Rate-Limiting + DSGVO (Export/Loeschen) + Banner"),
]


def _parse_list(value):
    return {int(v.strip()) for v in value.split(",") if v.strip()}


def run_phase(phase_num, filename, verbose):
    cache_dir = str(Path(tempfile.gettempdir()) /
                    ("pyc_runner_%d_%d" % (phase_num, int(time.time()))))
    env = os.environ.copy()
    env["PYTHONDONTWRITEBYTECODE"] = "1"
    env["PYTHONPYCACHEPREFIX"] = cache_dir
    env["PYTHONUNBUFFERED"] = "1"
    env["PYTHONIOENCODING"] = "utf-8"
    env["PYTHONUTF8"] = "1"
    existing_pp = env.get("PYTHONPATH", "")
    env["PYTHONPATH"] = str(PROJECT_ROOT) + (os.pathsep + existing_pp if existing_pp else "")

    start = time.monotonic()
    try:
        result = subprocess.run(
            [sys.executable, str(TESTS_DIR / filename)],
            cwd=str(PROJECT_ROOT),
            env=env,
            capture_output=True,
            text=True,
            encoding="utf-8",
            errors="replace",
            timeout=180,
        )
    except subprocess.TimeoutExpired as exc:
        return False, time.monotonic() - start, "TIMEOUT: %s" % exc

    duration = time.monotonic() - start
    stdout = result.stdout or ""
    stderr = result.stderr or ""
    combined = stdout + ("\n---STDERR---\n" + stderr if stderr.strip() else "")

    if verbose:
        print(combined)

    tail = "\n".join(combined.strip().splitlines()[-6:])
    return result.returncode == 0, duration, tail


def main():
    parser = argparse.ArgumentParser(description="EEG Lizenz-Test-Runner")
    parser.add_argument("--only", type=_parse_list, default=set())
    parser.add_argument("--skip", type=_parse_list, default=set())
    parser.add_argument("--verbose", action="store_true")
    args = parser.parse_args()

    selected = [p for p in PHASES
                if (not args.only or p[0] in args.only)
                and p[0] not in args.skip]

    if not selected:
        print("Keine Phasen ausgewaehlt. Abbruch.")
        return 1

    print("=" * 72)
    print(" EEG Lizenz-System - Master Test Runner")
    print(" Projekt-Root: %s" % PROJECT_ROOT)
    print(" Phasen:       %s" % ", ".join(str(p[0]) for p in selected))
    print("=" * 72)

    results = []
    overall_start = time.monotonic()

    for phase_num, filename, desc in selected:
        print("")
        print("> Phase %d: %s" % (phase_num, desc))
        print("  Datei: tests/%s" % filename)
        ok, duration, tail = run_phase(phase_num, filename, args.verbose)
        status = "PASS" if ok else "FAIL"
        print("  [%s]  (%.1fs)" % (status, duration))
        if not ok or not args.verbose:
            for line in tail.splitlines():
                print("    | %s" % line)
        results.append((phase_num, desc, ok, duration, tail))

    total = time.monotonic() - overall_start
    passed = sum(1 for r in results if r[2])
    failed = len(results) - passed

    print("")
    print("=" * 72)
    print(" ZUSAMMENFASSUNG")
    print("=" * 72)
    for phase_num, desc, ok, duration, _ in results:
        mark = "[OK]  " if ok else "[FAIL]"
        print("  %s  Phase %d  (%5.1fs)  %s" % (mark, phase_num, duration, desc))
    print("-" * 72)
    print("  Gesamt: %d/%d Phasen OK  |  %d fehlgeschlagen  |  %.1fs" %
          (passed, len(results), failed, total))
    print("=" * 72)

    return 0 if failed == 0 else 2


if __name__ == "__main__":
    sys.exit(main())
