"""Runs one command and appends an execution record to results/experiment-log.jsonl.

usage: python3 code/tools/logrun.py NAME [--log results/NAME.log] -- CMD ARG...

The record has the fields required by the AutoScholar artifact contract:
name, command, startedAt, endedAt, exitCode (plus durationSeconds, log path,
cwd and worker). Output of the command is passed through to stdout/stderr and,
if --log is given, also appended to that file. The exit code of the command is
propagated so that `set -e` scripts stop on failure. Nothing is ever logged as
successful unless the child process really exited with status 0.
"""
import datetime
import json
import os
import subprocess
import sys

ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
LOG = os.environ.get("AUTOSCHOLAR_EXPLOG") or os.path.join(ROOT, "results", "experiment-log.jsonl")


def utc():
    return datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="seconds")


def main(argv):
    name = argv[0]
    log = None
    i = 1
    if argv[i] == "--log":
        log = argv[i + 1]
        i += 2
    assert argv[i] == "--", "usage: logrun.py NAME [--log FILE] -- CMD..."
    cmd = argv[i + 1:]
    os.chdir(ROOT)
    started = utc()
    t0 = datetime.datetime.now()
    lf = open(log, "a") if log else None
    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
    for line in proc.stdout:
        sys.stdout.write(line)
        sys.stdout.flush()
        if lf:
            lf.write(line)
            lf.flush()
    code = proc.wait()
    if lf:
        lf.close()
    ended = utc()
    rec = {"name": name, "command": " ".join(cmd), "startedAt": started, "endedAt": ended, "exitCode": code,
           "durationSeconds": round((datetime.datetime.now() - t0).total_seconds(), 3),
           "ok": code == 0, "cwd": ".", "log": log, "worker": os.environ.get("AUTOSCHOLAR_WORKER", "M4M64c")}
    with open(LOG, "a") as f:
        f.write(json.dumps(rec, sort_keys=True) + "\n")
    sys.exit(code)


if __name__ == "__main__":
    main(sys.argv[1:])
