import sys,os,json,copy,csv
from pathlib import Path
sys.path.extend(['/evidence/2026-11-01_contextra-fall-spatial-28clips_r01/helpers','/evidence/2026-11-01_contextra-fall-depth-29clips_r01/helpers','/evidence/2026-11-01_contextra-fall-review-28clips_r01/helpers','/evidence/2026-10-30_contextra-fight-space-29clips_r01/helpers','/baseline'])
from common import OUT,read,save,load,evidence,sha
from fall_candidate import features,SpatialState
from depth_features import measure
from depth_candidate import decide
import render_fall as view
import render_space as encoder
R1=Path('/evidence/2026-11-01_contextra-fall-spatial-28clips_r01');R2=Path('/evidence/2026-11-01_contextra-fall-depth-29clips_r01');a=read(R1/'conditions.json');b=read(R2/'conditions.json')
clip=os.environ['CLIP'];rows,selected,spec,cache,maps=load(clip);hashes=read(evidence(spec['rgb_hashes_remote']))
work=OUT/'work'/clip;work.mkdir(parents=True,exist_ok=True);trace=work/'decisions.jsonl'
if clip=='SELF_L02':
 src=R2/'download'/clip/'data/R2_diagnostics.jsonl';assert sha(src)==read(src.parent/'summary.json')['diagnostics_sha256'];records=[json.loads(l) for l in src.open()]
elif trace.exists():records=[json.loads(l) for l in trace.open()]
else:
 states=[SpatialState(a,clip+'_'+v) for v in ('R1','R2')];records=[]
 for row in rows:
  people=[features(p,a) for p in row['persons']];extra=[measure(p,f) for p,f in zip(row['persons'],people)];decision=[decide(p,x,b) for p,x in zip(people,extra)]
  r1=states[0].evaluate(row['seconds'],people,monotonic_now=row['seconds']-rows[0]['seconds'])
  p2=[dict(p,hit=d['hit']) for p,d in zip(people,decision)];r2=states[1].evaluate(row['seconds'],p2,monotonic_now=row['seconds']-rows[0]['seconds'])
  assert not r1['hit'] or r2['hit']
  records.append(dict(sample=row['sample'],source_frame=row['source_frame'],seconds=row['seconds'],displayed=row['sample'] in selected,people=people,extra=extra,additional=decision,r1=r1,r2=r2,annotation=dict(review_frame=None)))
 with trace.open('x') as f:
  for r in records:f.write(json.dumps(r,separators=(',',':'))+'\n')
by={r['sample']:r for r in rows};original_text=view.text
for version in (['R2'] if clip=='SELF_L02' else ['R1','R2']):
 def text(draw,rects,pos,value,*args,**kwargs):
  value=value.replace('FALL 공간 후보 R1','FALL 공간 후보 '+version)
  if '13·15의 감지 손실' in value:value='고정 후보 비교 · 청색은 모든 R2 분기의 공통 진입조건이 아닙니다.'
  if clip=='SELF_L02' and value.startswith('원본 Frame '):
   n=int(value.split()[2]);value=value.replace('원본 Frame '+str(n),'L02 Frame '+str(n-2542)+' / L01 '+str(n))
  return original_text(draw,rects,pos,value,*args,**kwargs)
 view.text=text;dest=OUT/'download'/('R1_Previous' if version=='R1' else 'R2_Current')/clip;data=dest/'data';data.mkdir(parents=True,exist_ok=True)
 entries=[];shown=[]
 for r in records:
  if not r['displayed']:continue
  row=by[r['sample']];assert (row['source_frame'],row['seconds'])==(r['source_frame'],r['seconds'])
  shown.append(r);adapt=dict(r,candidate=r[version.lower()],tracking_mode=spec['tracking_mode'])
  entries.append(dict(kind='observation',row=row,result=adapt,seconds=row['seconds'],part_id='L01_P02' if clip=='SELF_L02' else '',path=cache/'frames'/f"{r['sample']:04d}.png",rgb_sha256=hashes[f"{r['sample']:04d}.png"]))
 assert len(entries)==len(selected)
 encoder.page=view.page;name='Fall_'+version+'_Space_Review'
 encoder.render(clip,entries,dest/(name+'.mp4'),data/'video_validation.json')
 display=read(data/(name+'_display.json'));assert len(display)==len(shown)
 for r,d in zip(shown,display):
  s=r[version.lower()];assert (s['hit'],s['display'],bool(s['event']),s['colors'])==(d['hit'],d['display'],d['event'],d['group_states'])
 with (data/'diagnostics.jsonl').open('w') as f:
  for r in records:f.write(json.dumps(r,separators=(',',':'))+'\n')
 result=dict(clip=clip,version=version,frames=len(shown),red=sum(r[version.lower()]['hit'] for r in shown),events=sum(bool(r[version.lower()]['event']) for r in shown),added=[r['source_frame'] for r in shown if r['r2']['hit'] and not r['r1']['hit']],removed=[r['source_frame'] for r in shown if r['r1']['hit'] and not r['r2']['hit']],r1_sha256=sha(R1/'conditions.json'),r2_sha256=sha(R2/'conditions.json'))
 (data/'comparison.json').write_text(json.dumps(result,indent=2));print('COMPARISON',json.dumps(result),flush=True)
