#!/usr/bin/env python3
"""Generate the PROSE (diagnostic) version from canonical structured YAML.
NOT canonical. A node that won't render cleanly has a defect in the structured form.
Usage: python3 rb_render_prose.py <structured.yaml> <out.txt>"""
import sys, yaml, textwrap

LABEL={'settled':'SETTLED','correction':'CORRECTION','neg-only':'NEGATIVE CLAIM ONLY',
 'decomposable-excluded-residual':'DECOMPOSABLE (residual excluded)','do-not-assert-yet':'DO NOT ASSERT YET',
 'reconcile':'RECONCILE (may exist in unseen corpus)','illustration':'ILLUSTRATION (no claim)'}
PART={'A':'THE FLOOR','B':'THE GEOMETRY','C':'EVOLUTION & GATED STABILIZATION',
 'D':'BRAINSTEM AS STATE MACHINE','E':'SAMPLING LOOP & RETURN','F':'TISSUE REGIMES & RECOVERY',
 'G':'ASYNCHRONY & CONSTRUCTED CONTINUITY','H':'SCOPE BOUNDARY','Y':'OPEN / RECONCILE'}

def wrap(s,i=0):
    s=' '.join(str(s).split()); p=' '*i
    return '\n'.join(textwrap.wrap(s,92,initial_indent=p,subsequent_indent=p))

def mech(m,defects,nid):
    out=[]
    if m is None: return out
    if isinstance(m,list):
        for item in m: out.append(wrap("- "+str(item),6))
    elif isinstance(m,dict):
        for k,v in m.items(): out.append(wrap(f"- {k}: {v}",6))
    else:
        defects.append(f"{nid}: mechanism has unexpected type"); out.append(wrap(str(m),6))
    return out

def render(n,defects):
    nid=n['id']; o=[]
    if not n.get('definition') or len(' '.join(n['definition'].split()))<12:
        defects.append(f"{nid}: definition missing/too thin")
    if n.get('status') not in LABEL: defects.append(f"{nid}: unknown status")
    o.append(f"{nid}. [{LABEL.get(n.get('status'),'?')}]  ({n.get('type','?')})")
    o.append(wrap(n.get('definition',''),4))
    if n.get('mechanism') is not None:
        o.append("    mechanism:"); o+=mech(n['mechanism'],defects,nid)
    dep=n.get('depends_on') or []; fed=n.get('feeds') or []
    if dep: o.append(wrap("Holds only while: "+", ".join(dep)+".",4))
    if fed: o.append(wrap("Feeds: "+", ".join(fed)+".",4))
    df=n.get('distinguishes_from')
    if df and isinstance(df,dict):
        o.append("    distinguishes:")
        for k,v in df.items(): o.append(wrap(f"- {k}: {v}",6))
    if n.get('supersedes'): o.append(wrap("RETRACTS: "+n['supersedes'],4))
    g=n.get('guards') or {}
    for bad in (g.get('rewrite') or []):
        fix=(g.get('rewrite_to') or {}).get(bad)
        o.append(wrap(f'DRIFT (rewrite): "{bad}"',4))
        if fix: o.append(wrap("rewrite to: "+fix,8))
    ill=n.get('illustration')
    if ill:
        if isinstance(ill,dict):
            note=f" ({ill['note']})" if ill.get('note') else ""
            o.append(wrap(f"Illustration only (no claim): {ill.get('text','')}{note}",4))
            if ill.get('carries_claim',False): defects.append(f"{nid}: illustration carries_claim true")
        else: o.append(wrap(f"Illustration only (no claim): {ill}",4))
    if n.get('disconfirms_if'): o.append(wrap("Weakens if: "+n['disconfirms_if'],4))
    if n.get('open'): o.append(wrap("OPEN: "+n['open'],4))
    if n.get('reconcile'): o.append(wrap("RECONCILE: "+n['reconcile'],4))
    return '\n'.join(o)

def main():
    src,dst=sys.argv[1],sys.argv[2]
    doc=yaml.safe_load(open(src)); meta=doc.get('meta',{}); defects=[]
    L=["REMODELED BRAIN / MOVING BEYOND MAGIC","PROSE (DIAGNOSTIC) RENDER -- GENERATED, NOT CANONICAL","="*92]
    L.append(wrap(f"Generated from {src}. Do NOT hand-edit; regenerate from the structured file. "
                  f"Divergence is a defect in the structured file, not an edit to make here."))
    L+=["",wrap(f"Version: {meta.get('version')}. Scope: {meta.get('scope','')}"),
        wrap(f"Operating variable: {meta.get('operating_variable')} = {meta.get('operating_variable_def','')}"),""]
    pg=meta.get('process_graphs',{})
    for k,v in pg.items(): L.append(wrap(f"{k}: "+" -> ".join(v)))
    L+=["",wrap("KERNEL: "+meta.get('kernel_summary','')),"","="*92,""]
    gov=meta.get('governance',{})
    if gov:
        L+=["","--- GOVERNANCE (build-time boundary) ---",""]
        L.append(wrap("PRINCIPLE: "+gov.get('compact_principle','')))
        lp=gov.get('layer_partition',{})
        if lp:
            L.append(wrap("claim layer (protected): "+", ".join(lp.get('claim_layer',[]))))
            L.append(wrap("support layer (ingestion-writable): "+", ".join(lp.get('support_layer',[]))))
        for r in gov.get('rules',[]):
            L.append(wrap(f"{r['id']} [{r.get('type')}]: "+r.get('definition',''),2))
        L+=[""]
    part=None
    for n in doc['nodes']:
        p=n['id'][0]
        if p!=part: part=p; L+=["",f"--- PART {part}: {PART.get(part,'')} ---",""]
        L.append(render(n,defects)); L.append("")
    open(dst,'w').write('\n'.join(L))
    print(f"Rendered {len(doc['nodes'])} nodes -> {dst}")
    print("No translation defects." if not defects else f"DEFECTS ({len(defects)}):")
    for d in defects: print("  -",d)

if __name__=='__main__': main()
