import json, os, shutil, subprocess, time
ROOT="/Users/oscar/.worktree/hot-reload/labs/hot-reload"; REC=f"{ROOT}/target/kan-hot/debug/rustc"
DEPS=f"{ROOT}/target/debug/deps"; SRC=f"{ROOT}/api-common/src/lib.rs"
BASE="/private/var/folders/ft/fkt3bwqd01g7f54wvyz9wgjc0000gn/T/opencode/pipe/out22"
def load(n): return json.load(open(f"{REC}/{n}.json"))
def strip_owned(argv):
    out=[]; i=1
    while i<len(argv):
        a=argv[i]
        if a=="-C" and i+1<len(argv) and any(argv[i+1].startswith(p) for p in ("incremental=","codegen-units=","debuginfo=")): i+=2; continue
        if a.startswith("-C") and any(a[2:].startswith(p) for p in ("incremental=","codegen-units=","debuginfo=")): i+=1; continue
        out.append(a); i+=1
    return out
common=load("api_common"); api=load("api"); orig=open(SRC).read(); assert "nested-v1" in orig
shutil.rmtree(BASE,ignore_errors=True); os.makedirs(BASE)
FRESH=f"{BASE}/fresh"; os.makedirs(FRESH)
META=f"{BASE}/meta"; os.makedirs(META)
def compile_common(mode,mark):
    open(SRC,"w").write(orig.replace("nested-v1",mark))
    ca=[common["argv"][0]]+strip_owned(common["argv"])+["-C","debuginfo=0","-C","codegen-units=1"]
    if mode=="meta":
        i=ca.index("--emit=dep-info,metadata,link"); ca[i]="--emit=metadata"
    j=ca.index("--out-dir"); ca[j+1]=FRESH
    env=dict(common["env"]); env["RUSTC_BOOTSTRAP"]="1"
    s=time.monotonic(); p=subprocess.run(ca,cwd=common["cwd"],env=env,stdout=subprocess.DEVNULL,stderr=subprocess.PIPE); t=(time.monotonic()-s)*1000
    if p.returncode: print("COMMON FAIL",p.stderr[:500])
    return t,os.path.join(FRESH,[f for f in os.listdir(FRESH) if f.startswith("libapi_common") and f.endswith(".rmeta")][0])
def api_run(name,extra,common_mode,incbase,mark):
    ct,rmeta=compile_common(common_mode,mark)
    raw=[api["argv"][0]]+[a if not a.startswith("--extern=api_common=") else f"--extern=api_common={rmeta}" for a in api["argv"][1:]]
    aa=[api["argv"][0]]+strip_owned(raw)+["-C","debuginfo=0","-C","codegen-units=8","-C",f"incremental={incbase}/{name}"]+extra
    j=aa.index("--out-dir"); aa[j+1]=FRESH
    env=dict(api["env"]); env["RUSTC_BOOTSTRAP"]="1"
    s=time.monotonic(); p=subprocess.run(aa,cwd=api["cwd"],env=env,stdout=subprocess.DEVNULL,stderr=subprocess.PIPE); t=(time.monotonic()-s)*1000
    return ct,t,p.returncode,p.stderr[:200]
variants=[("base",[],"full"),("noinline",["-Zinline-mir=no"],"full"),("mir0",["-Zmir-opt-level=0"],"full"),("noinline_meta",["-Zinline-mir=no"],"meta"),("mir0_meta",["-Zmir-opt-level=0"],"meta"),("meta_only",[],"meta")]
try:
    for v in variants:
        ct,t,rc,err=api_run(v[0],v[1],v[2],f"{BASE}/inc",f"warm-{v[0]}")
        if rc: print(v[0],"WARM FAIL",err)
    time.sleep(.2)
    res={v[0]:[] for v in variants}; cres={v[0]:[] for v in variants}
    for i in range(5):
        for v in variants:
            ct,t,rc,err=api_run(v[0],v[1],v[2],f"{BASE}/inc",f"e22-{v[0]}-{i}")
            res[v[0]].append(t); cres[v[0]].append(ct)
            if rc: print(v[0],"FAIL",err)
            time.sleep(.1)
    for k in res:
        xs=res[k]; cs=cres[k]
        print(f"{k:16s} api med={sorted(xs)[len(xs)//2]:.1f} all={[round(x,1) for x in xs]} common med={sorted(cs)[len(cs)//2]:.1f}")
finally:
    open(SRC,"w").write(orig)
