import json, os, shutil, subprocess, sys, time

ROOT="/Users/oscar/.worktree/hot-reload/labs/hot-reload"
REC=f"{ROOT}/target/kan-hot/debug/rustc"
SCRATCH="/private/var/folders/ft/fkt3bwqd01g7f54wvyz9wgjc0000gn/T/opencode/pipe/out"

def load(n):
    return json.load(open(f"{REC}/{n}.json"))

def env_of(d):
    e=dict(d["env"])
    e["PATH"]=os.environ["PATH"]
    return e

def run(d, extra_args=(), extra_env=None, outdir=None, replace=None):
    argv=list(d["argv"])
    if outdir:
        i=argv.index("--out-dir"); argv[i+1]=outdir
    if replace:
        for old,new in replace:
            argv=[new if a==old else a for a in argv]
    argv += list(extra_args)
    env=env_of(d)
    if extra_env: env.update(extra_env)
    t=time.monotonic()
    p=subprocess.run(argv, cwd=d["cwd"], env=env, capture_output=True, text=True)
    dt=(time.monotonic()-t)*1000
    return dt,p,argv

def extern_rmeta(d, name, path):
    return [(a, f"--extern={name}={path}") for a in d["argv"] if a.startswith(f"--extern={name}=")]

common=load("api_common"); api=load("api")
shutil.rmtree(SCRATCH, ignore_errors=True); os.makedirs(SCRATCH)

print("=== full compile api-common (fresh, edited source already) ===")
dt,p,_=run(common, outdir=SCRATCH)
print("full", f"{dt:.1f}ms", "rc",p.returncode)
print("files", sorted(os.listdir(SCRATCH)))
rmeta=[f for f in os.listdir(SCRATCH) if f.endswith(".rmeta")]
rlib=[f for f in os.listdir(SCRATCH) if f.endswith(".rlib")]
print("rmeta",rmeta,"rlib",rlib)

print("\n=== metadata-only rmeta (--emit=metadata) ===")
meta_only=[a for a in common["argv"]]
i=meta_only.index("--emit=dep-info,metadata,link"); meta_only[i]="--emit=metadata"
def run_argv(argv, cwd, env):
    t=time.monotonic(); p=subprocess.run(argv,cwd=cwd,env=env,capture_output=True,text=True); return (time.monotonic()-t)*1000,p

# strip codegen flags we don't want for metadata? keep same
argv=list(meta_only)
dt,p=run_argv(argv, common["cwd"], env_of(common))
print("meta-only", f"{dt:.1f}ms", "rc",p.returncode)
# find output rmeta in deps dir (same name as real)
dep=f"{ROOT}/target/debug/deps"
name=[f for f in os.listdir(SCRATCH) if f.endswith(".rmeta")][0]
m=os.path.join(dep,name)
print("meta exists", os.path.exists(m), m)
if os.path.exists(m):
    # copy aside, then compile api against it with fresh incremental dir
    dst=os.path.join(SCRATCH,"meta_only.rmeta"); shutil.copy(m,dst)
    inc=f"{SCRATCH}/inc_api_meta"; shutil.rmtree(inc,ignore_errors=True)
    api_argv=[a if not a.startswith("--extern=api_common=") else f"--extern=api_common={dst}" for a in api["argv"]]
    # replace incremental dir
    api_argv=[f"-C incremental={inc}" if a.startswith("-C") and False else a for a in api_argv]
    # find -C incremental=... form (two args? recorded uses single "-C incremental=...")
    out=[]; j=0
    while j<len(api_argv):
        if api_argv[j]=="-C" and j+1<len(api_argv) and api_argv[j+1].startswith("incremental="):
            out+=["-C",f"incremental={inc}"]; j+=2; continue
        out.append(api_argv[j]); j+=1
    dt2,p2=run_argv(out, api["cwd"], env_of(api))
    print("api against meta-only", f"{dt2:.1f}ms", "rc",p2.returncode)
    if p2.returncode: print(p2.stderr[:2000])

print("\n=== metadata-only + -Zalways-encode-mir ===")
env_boom=env_of(common); env_boom["RUSTC_BOOTSTRAP"]="1"
argv=list(meta_only)+["-Zalways-encode-mir"]
dt,p=run_argv(argv, common["cwd"], env_boom)
print("meta-only+mir", f"{dt:.1f}ms", "rc",p.returncode, p.stderr.splitlines()[-1] if p.stderr else "")
m=os.path.join(dep,name)
if os.path.exists(m):
    dst=os.path.join(SCRATCH,"meta_mir.rmeta"); shutil.copy(m,dst)
    inc=f"{SCRATCH}/inc_api_mir"; shutil.rmtree(inc,ignore_errors=True)
    api_argv=[a if not a.startswith("--extern=api_common=") else f"--extern=api_common={dst}" for a in api["argv"]]
    out=[]; j=0
    while j<len(api_argv):
        if api_argv[j]=="-C" and j+1<len(api_argv) and api_argv[j+1].startswith("incremental="):
            out+=["-C",f"incremental={inc}"]; j+=2; continue
        out.append(api_argv[j]); j+=1
    env_api=env_of(api); env_api["RUSTC_BOOTSTRAP"]="1"
    dt2,p2=run_argv(out, api["cwd"], env_api)
    print("api against meta+mir", f"{dt2:.1f}ms", "rc",p2.returncode)
    if p2.returncode:
        for line in p2.stderr.splitlines():
            if '"level":"error"' in line or 'missing' in line: print(line[:600])
