#!/usr/bin/env python3
"""Make full-viewport comparison and recording review grids from selected captures."""
from pathlib import Path
from PIL import Image,ImageDraw
import json,subprocess,concurrent.futures,sys
R=Path('/tmp/issue-lead-33252-r2/evidence-capture');M=json.loads((R/'manifest.json').read_text());O=R/'review';O.mkdir(exist_ok=True)
def grid(files,out,columns=4,width=390):
 ims=[]
 for title,p in files:
  im=Image.open(p).convert('RGB');im.thumbnail((width,900));ims.append((title,im))
 h=max(im.height for _,im in ims)+30
 canvas=Image.new('RGB',(width*columns,h*((len(ims)+columns-1)//columns)),'#ddd');d=ImageDraw.Draw(canvas)
 for i,(title,im) in enumerate(ims):
  x=i%columns*width;y=i//columns*h;d.text((x+4,y+8),title,fill='black');canvas.paste(im,(x,y+30))
 canvas.save(out)
for row in sorted({e['row'] for e in M}):
 scenes=[e for e in M if e['row']==row]
 for key in ['before','after','Diff0','DiffT','amplified32']:
  grid([(f"{row} {key} {e['width']} {e['theme']}",e[key]) for e in scenes],O/f'{row}-{key}.png',4,720 if key in ('Diff0','DiffT') else 520)
def contact(e,side):
 if side+'Video' not in e:return
 video=Path(e[side+'Video']);duration=float(json.loads(subprocess.check_output(['ffprobe','-v','error','-show_entries','format=duration','-of','json',video]))['format']['duration'])
 timeline=json.loads(Path(e[side+'Timeline']).read_text())
 # Retain initial, every scripted milestone, and final scene.
 times=[.05]+[min(duration-.1,t.get('seconds',t.get('ms',0)/1000)+.65) for t in timeline]+[duration-.1]
 out=R/'publish'/(video.stem+'-review-frames');out.mkdir(exist_ok=True)
 files=[]
 for i,t in enumerate(times):
  p=out/f'{i:02d}.png';subprocess.run(['ffmpeg','-v','error','-y','-ss',str(t),'-i',video,'-frames:v','1',p],check=True)
  files.append((f'{video.stem} {t:.2f}s',p))
 grid(files,video.with_name(video.stem+'-contact.png'),4,480 if e['width']==1440 else 390)
 return str(video)
if '--stills-only' in sys.argv:sys.exit(0)
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as p:
 for result in p.map(lambda task:contact(*task),[(e,s) for e in M for s in (('after',) if '--after-only' in sys.argv else ('before',) if '--before-only' in sys.argv else ('before','after'))]):
  if result:print(result,flush=True)
