#!/usr/bin/env python3
from __future__ import annotations
import json, pathlib, subprocess
ROOT=pathlib.Path(__file__).resolve().parents[1]
QA=ROOT/'qa_screenshots'
EXP=ROOT/'assets/data/image-admin/rc48_green_motion_expansion.json'
TRACE=ROOT/'assets/data/image-admin/rc48_motion_trace_verification.json'
QA.mkdir(exist_ok=True)
exp=json.loads(EXP.read_text(encoding='utf-8'))
trace=json.loads(TRACE.read_text(encoding='utf-8'))

def esc(s):
    return str(s).replace('&','&amp;').replace('<','&lt;').replace('>','&gt;').replace('"','&quot;').replace("'",'&#39;')

def make_html(name,w,h):
    rs=exp['report']; ts=trace['summary']; issues=trace.get('issues',[])
    cards=[('Seq changes',rs['sequenceChanges']),('New MP active',rs['newMediaPipeActivations']),('Retained MP',rs['retainedOrReactivatedMediaPipe']),('Trace errors',ts['issues']['error']),('Active anchor frames',ts['activeMediapipeAnchorFrames']),('Review holds',ts['reviewHoldExercises']),('Missing anchors',ts['missingAnchors']),('Jump errors',ts['jumpContactErrors'])]
    exs=list(exp.get('exerciseDecisions',{}).items())
    cards_html=''.join(f"<div class='metric'><b>{esc(v)}</b><span>{esc(k)}</span></div>" for k,v in cards)
    ex_html=''.join(f"<div class='ex'><b>{esc(k)}</b><span>{esc(v.get('action',''))}</span><em>{esc(v.get('runtimeImpact',''))}</em></div>" for k,v in exs[:12])
    held=''.join(f"<span>{esc(x)}</span>" for x in exp.get('activationPolicy',{}).get('heldExercises',[]))
    issue_html=''.join(f"<li class='{esc(i['level'])}'><b>{esc(i['level']).upper()} · {esc(i['code'])}</b> {esc(i['message'])} <code>{esc(i.get('exerciseKey',''))}</code></li>" for i in issues) or '<li>No issues</li>'
    return f"""<!doctype html><html><head><meta charset='utf-8'><style>
@page{{size:{w}px {h}px;margin:0}}*{{box-sizing:border-box}}body{{margin:0;width:{w}px;height:{h}px;overflow:hidden;background:linear-gradient(135deg,#051320,#0b2b3b 55%,#041018);color:#effbff;font-family:Inter,system-ui,-apple-system,Segoe UI,sans-serif}}.wrap{{padding:{max(20,int(w*.034))}px}}.hero{{border:1px solid rgba(125,211,252,.32);border-radius:26px;padding:22px;background:rgba(12,36,51,.74)}}.eyebrow{{color:#7dd3fc;font-size:13px;text-transform:uppercase;font-weight:900;letter-spacing:.16em}}h1{{font-size:{max(36,int(w*.055))}px;letter-spacing:-.055em;line-height:.94;margin:8px 0 12px}}p{{font-size:{max(15,int(w*.017))}px;color:#cfe7f0;margin:0;max-width:920px}}.grid{{display:grid;grid-template-columns:repeat({2 if w<700 else 4},1fr);gap:12px;margin:18px 0}}.metric{{border:1px solid rgba(125,211,252,.2);border-radius:18px;padding:14px;background:rgba(16,47,66,.62)}}.metric b{{display:block;font-size:{max(22,int(w*.028))}px;color:#6ee7b7}}.metric span{{color:#aecbd8;font-size:12px}}h2{{font-size:{max(20,int(w*.024))}px;margin:18px 0 10px}}.exwrap{{display:grid;grid-template-columns:repeat({1 if w<700 else 3},1fr);gap:10px}}.ex{{border:1px solid rgba(125,211,252,.18);border-radius:16px;background:rgba(16,47,66,.45);padding:12px;min-height:76px}}.ex b{{font-size:15px;display:block}}.ex span{{display:block;color:#d9fbff;font-size:12px;margin:4px 0}}.ex em{{font-style:normal;color:#fbbf24;font-size:11px}}.held{{display:flex;gap:8px;flex-wrap:wrap}}.held span{{border:1px solid rgba(251,191,36,.3);border-radius:999px;padding:6px 9px;color:#fbbf24;background:rgba(251,191,36,.07);font-size:12px;font-weight:800}}ul{{margin:8px 0 0;padding:0;list-style:none}}li{{border:1px solid rgba(125,211,252,.18);padding:10px;border-radius:14px;margin:8px 0;background:rgba(18,56,77,.45);font-size:13px}}li.info{{border-color:rgba(125,211,252,.42)}}code{{background:rgba(0,0,0,.24);border-radius:6px;padding:1px 4px}}.footer{{position:absolute;left:{max(20,int(w*.034))}px;right:{max(20,int(w*.034))}px;bottom:14px;color:#8cb5c4;font-size:12px}}
</style></head><body><div class='wrap'><section class='hero'><div class='eyebrow'>NEXT Pose Atlas · {esc(name)}</div><h1>RC48 Green Motion Expansion</h1><p>{esc(rs['principle'])}</p></section><div class='grid'>{cards_html}</div><h2>Expanded / tightened movements</h2><div class='exwrap'>{ex_html}</div><h2>Held gates</h2><div class='held'>{held}</div><h2>Trace issues</h2><ul>{issue_html}</ul></div><div class='footer'>Static fallback QA · visual app animation not browser-tested in sandbox · {esc(exp['createdAt'])}</div></body></html>"""

def render(name,w,h):
    html=QA/f'rc48_{name}_static_qa.html'; pdf=QA/f'rc48_{name}_static_qa.pdf'; png=QA/f'rc48_{name}_static_qa'
    html.write_text(make_html(name,w,h),encoding='utf-8')
    subprocess.run(['weasyprint',str(html),str(pdf)],check=True)
    subprocess.run(['pdftoppm','-png','-singlefile','-r','144',str(pdf),str(png)],check=True)
for args in [('mobile',390,844),('ipad',820,1180),('desktop',1180,820)]: render(*args)
print('Rendered RC48 QA screenshots to',QA)
