#!/usr/bin/env python3
"""Compose a flake.lock for the freshly installed machine — offline.

The generated downstream flake has exactly one input, `nomarchy`. A normal
`nix flake lock` would fetch it from its forge; on an offline install we
already KNOW the answer: the live ISO was built from a specific nomarchy
rev whose source (and all transitive inputs, via the ISO's pinned store
paths) is on hand. So we write the lock nix would have written:

  root ─▶ nomarchy (locked to the baked rev+narHash)
              └─▶ every node from nomarchy's own flake.lock, verbatim

Nix resolves locked inputs by narHash against the store before touching
the network, so evaluation on the target works without connectivity.

Usage:
  compose-lock.py <nomarchy-flake.lock> <out> <locked-json> <original-json>

where <locked-json>/<original-json> are the flake-lock node fields for the
nomarchy input (any input type — github, git, …), baked at package build.
"""
import json
import sys


def main() -> None:
    src_lock, out, locked_json, original_json = sys.argv[1:5]

    locked = json.loads(locked_json)
    if not locked.get("narHash"):
        sys.exit("compose-lock: no narHash in locked metadata")

    with open(src_lock) as f:
        upstream = json.load(f)

    nodes = dict(upstream["nodes"])
    # nomarchy's root node describes ITS inputs; that mapping becomes the
    # input set of the new `nomarchy` node.
    nomarchy_inputs = nodes.pop("root")["inputs"]
    if "nomarchy" in nodes:
        sys.exit("compose-lock: upstream lock already has a 'nomarchy' node")

    # Follows paths (list-valued inputs) are absolute from the lock's
    # root; the copied nodes now live one level down, so ["nixpkgs"]
    # must become ["nomarchy", "nixpkgs"]. Plain string values reference
    # node keys directly and stay as they are.
    for node in nodes.values():
        for name, ref in node.get("inputs", {}).items():
            if isinstance(ref, list):
                node["inputs"][name] = ["nomarchy"] + ref

    nodes["nomarchy"] = {
        "inputs": nomarchy_inputs,
        "locked": locked,
        "original": json.loads(original_json),
    }
    nodes["root"] = {"inputs": {"nomarchy": "nomarchy"}}

    with open(out, "w") as f:
        json.dump({"nodes": nodes, "root": "root", "version": 7}, f, indent=2)
        f.write("\n")
    pin = locked.get("rev", locked["narHash"])[:12]
    print(f"compose-lock: wrote {out} (nomarchy @ {pin})")


if __name__ == "__main__":
    main()
