"""run_all.py - run the examples of krueng.ai/decider.html and keep what each one printed.

    python run_all.py                    # all thirteen, one after the other
    python run_all.py choice.py noul.py  # only these

What a file printed goes to <name>_output.txt beside it. The page's "what it printed"
boxes are those files. The seconds each file took, and the most memory it held, go to
timings.txt. A file that fails stops the run and its error is shown.

The memory figure needs the psutil library (pip install psutil). Without it the
column is empty.
"""
import os
import platform
import subprocess
import sys
import time
from importlib import metadata
from pathlib import Path

HERE = Path(__file__).resolve().parent
FILES = ["first.py", "by_hand.py", "choice.py", "noul.py", "score.py", "one_call.py",
         "look_inside.py", "fields.py", "many.py", "compare.py", "too_much.py",
         "long_text.py", "speed.py"]


def memory_gb(pid):
    """The memory a running program holds now, in GB. 0 without psutil."""
    try:
        import psutil
        return psutil.Process(pid).memory_info().rss / 2 ** 30
    except Exception:              # noqa: BLE001 - no psutil, or the program just ended
        return 0.0


def run(name):
    """Run one file. Returns (what it printed, errors, exit code, seconds, most GB)."""
    started = time.perf_counter()
    program = subprocess.Popen([sys.executable, name], cwd=HERE,
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                               env=dict(os.environ, PYTHONUTF8="1"))
    most = 0.0
    while True:
        try:
            printed, errors = program.communicate(timeout=0.5)
            break
        except subprocess.TimeoutExpired:
            most = max(most, memory_gb(program.pid))
    seconds = time.perf_counter() - started
    printed, errors = printed.decode("utf-8"), errors.decode("utf-8", "replace")
    return printed, errors, program.returncode, seconds, most


def main():
    names = sys.argv[1:] or FILES
    versions = ", ".join(f"{package} {metadata.version(package)}"
                         for package in ("decider-ai", "torch", "transformers"))
    computer = f"{platform.system()} {platform.machine()}, {os.cpu_count()} logical cores"
    lines = [f"python {platform.python_version()} on {computer}; {versions}"]
    for name in names:
        printed, errors, code, seconds, most = run(name)
        if code != 0:
            print(errors[-2000:])
            print(f"{name} failed with exit code {code}; nothing was written for it")
            return 1
        output = HERE / f"{Path(name).stem}_output.txt"
        output.write_text(printed.replace("\r\n", "\n"), encoding="utf-8", newline="\n")
        held = f"{most:4.1f} GB" if most else "      -"
        lines.append(f"{name:14} {seconds:6.1f} s  {held}")
        print(lines[-1], f" -> {output.name}", flush=True)
    if names == FILES:
        timings = HERE / "timings.txt"
        timings.write_text("\n".join(lines) + "\n", encoding="utf-8", newline="\n")
        print("wrote timings.txt")
    return 0


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