import os, json, time
from pathlib import Path
ROOT = Path(r"C:\Users\decid\Documents\projects\spt-core")
PROOF = ROOT / ".spt/preserved/304-handoff/target-reclaim-20260914"
NAMES = ["300-input-acceptance", "304-product", "304-w2-bootstrap-tcp", "49-267-obs", "299-instr"]
TARGETS = {name: ROOT / ".worktrees" / name / "target" for name in NAMES}
def norm(path):
    return os.path.normcase(os.path.abspath(path)).removeprefix("\\\\?\\")
def inside(path, root):
    return path == root or path.startswith(root + os.sep)
normalized = {name:norm(path) for name,path in TARGETS.items()}
report = {"scan_root":str(ROOT.parent), "started_at":time.time(), "links":[], "errors":[], "directories":0, "files":0, "targets":{name:{"path":str(path), "bytes":0, "files":0, "inbound":[], "internal_reparse":[]} for name,path in TARGETS.items()}}
stack = [str(ROOT.parent)]
while stack:
    directory = stack.pop()
    report["directories"] += 1
    try:
        with os.scandir(directory) as entries:
            for entry in entries:
                try:
                    st = entry.stat(follow_symlinks=False)
                    path = norm(entry.path)
                    owners = [name for name,target in normalized.items() if inside(path,target)]
                    if getattr(st,"st_file_attributes",0) & 0x400:
                        link = {"path":entry.path, "raw_target":os.readlink(entry.path), "resolved":os.path.realpath(entry.path)}
                        report["links"].append(link)
                        resolved = norm(link["resolved"])
                        for name,target in normalized.items():
                            if inside(resolved,target) or inside(target,resolved):
                                report["targets"][name]["inbound"].append(link)
                        for name in owners:
                            report["targets"][name]["internal_reparse"].append(link)
                        continue
                    if entry.is_dir(follow_symlinks=False):
                        stack.append(entry.path)
                    else:
                        report["files"] += 1
                        for name in owners:
                            report["targets"][name]["bytes"] += st.st_size
                            report["targets"][name]["files"] += 1
                except OSError as error:
                    report["errors"].append({"path":entry.path,"error":repr(error)})
    except OSError as error:
        report["errors"].append({"path":directory,"error":repr(error)})
report["finished_at"] = time.time()
(PROOF / "inbound-and-sizes.json").write_text(json.dumps(report,indent=2))
print(json.dumps({key:report[key] for key in ("scan_root","directories","files","errors","targets","started_at","finished_at")},indent=2))
