#!/usr/bin/env python3
"""Set a task's status in import/progress.json, atomically.

Sources of truth: import/progress.json. Several sessions edit it in one working tree, so
this takes an exclusive lock, rewrites in place, and stamps updated_at/updated_by. The
/plan page reads the file per request; no deploy is needed.

    python3 main/scripts/plan-set.py A1 doing "Stream A"
    python3 main/scripts/plan-set.py A1 done  "Stream A" --note "robots.py landed, 12 tests"
"""
import argparse, datetime, fcntl, json, pathlib, sys

STATUSES = ("done", "doing", "todo", "blocked", "deferred")
ROOT = pathlib.Path(__file__).resolve().parents[2]
FILE = ROOT / "import" / "progress.json"

def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("task_id"); ap.add_argument("status", choices=STATUSES); ap.add_argument("who")
    ap.add_argument("--note", default=None, help="optional short note appended to the title in brackets")
    a = ap.parse_args()
    with FILE.open("r+") as fh:
        fcntl.flock(fh, fcntl.LOCK_EX)
        data = json.load(fh)
        hit = None
        for s in data["streams"]:
            for t in s["tasks"]:
                if t["id"] == a.task_id:
                    t["status"] = a.status
                    if a.note:
                        t["title"] = t["title"].split(" [")[0] + f" [{a.note}]"
                    hit = (s["key"], t["title"])
        if not hit:
            print(f"no task {a.task_id}", file=sys.stderr); return 2
        data["updated_at"] = datetime.datetime.now(datetime.timezone.utc).isoformat(timespec="minutes")
        data["updated_by"] = a.who
        fh.seek(0); fh.truncate(); json.dump(data, fh, indent=1); fh.write("\n")
    print(f"{a.task_id} -> {a.status}  ({hit[0]}: {hit[1][:70]})")
    return 0

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