from pathlib import Path
import json, shutil, subprocess
import numpy as np
from PIL import Image, ImageDraw, ImageFont

ROOT=Path('/tmp/issue-lead-26950-r1/evidence-capture')
OUT=ROOT/'deliverables'
OUT.mkdir(exist_ok=True)
RUNS={'F1':('1336','1336'),'F2':('1350','1354'),'F3':('1338','1338'),'F4':('1411-final','1411-final'),'F5':('1410','1410'),'F6':('1415','1415')}
PAIRS={'F1':['toa','Curs'],'F2':['mixed'],'F3':['empty','recovered'],'F4':['qualified'],'F5':['checks','status','removed'],'F6':['passing']}
font=ImageFont.truetype('/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf',20)
small=ImageFont.truetype('/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf',16)
summary={}
for fixture,dirs in RUNS.items():
    summary[fixture]={'manifests':{},'pairs':[]}
    for side,run in zip(('before','after'),dirs):
        src=ROOT/('run-20261029-'+run)
        manifest=json.loads((src/f'{fixture}-{side}-manifest.json').read_text())
        summary[fixture]['manifests'][side]=manifest
        for p in src.glob(f'{fixture}-{side}*'):
            shutil.copy2(p,OUT/p.name)
        video=OUT/f'{fixture}-{side}.mp4'
        probe=json.loads(subprocess.check_output(['ffprobe','-v','quiet','-show_format','-show_streams','-of','json',str(video)]))
        duration=float(probe['format']['duration'])
        actions=manifest['final']['actions'];offset=manifest['final']['recordOffset']
        times=sorted(set([0.5,max(0,duration-.5)]+[max(0,min(duration-.1,(a['t']-offset)/1000+.4)) for a in actions]))
        strip=Image.new('RGB',(4*480,((len(times)+3)//4)*328),(22,22,26));draw=ImageDraw.Draw(strip)
        for i,t in enumerate(times):
            png=OUT/f'{fixture}-{side}-video-frame-{i}.png'
            subprocess.run(['ffmpeg','-hide_banner','-loglevel','error','-ss',str(t),'-i',str(video),'-frames:v','1','-y','-update','1',str(png)],check=True)
            img=Image.open(png).convert('RGB').resize((480,300))
            x=(i%4)*480;y=(i//4)*328
            strip.paste(img,(x,y+28));draw.text((x+8,y+4),f'{fixture} {side} {t:.1f}s',font=small,fill='white')
        strip.save(OUT/f'{fixture}-{side}-filmstrip.png')
    sheet=Image.new('RGB',(4*640,len(PAIRS[fixture])*440+70),(22,22,26));draw=ImageDraw.Draw(sheet)
    draw.text((12,8),f'{fixture} | web 1440 x 900 CSS | dark | full surface, scaled for sheet | DiffT >16/255',font=font,fill='white')
    for col,title in enumerate(('Before 6d450a4284','After 5c1c8b0004','Diff0: any channel >0','DiffT: any channel >16')):
        draw.text((col*640+12,40),title,font=small,fill='white')
    for row,label in enumerate(PAIRS[fixture]):
        b=Image.open(OUT/f'{fixture}-before-{label}.png').convert('RGB');a=Image.open(OUT/f'{fixture}-after-{label}.png').convert('RGB')
        delta=np.abs(np.asarray(a).astype(np.int16)-np.asarray(b).astype(np.int16)).max(axis=2)
        info={'label':label}
        imgs=[b,a]
        for threshold,name in ((0,'Diff0'),(16,'DiffT')):
            mask=delta>threshold
            context=np.asarray(b)//4
            context[mask]=[255,0,255]
            result=Image.fromarray(context.astype(np.uint8))
            path=OUT/f'{fixture}-{label}-{name}.png';result.save(path);imgs.append(result)
            yy,xx=np.where(mask)
            info[name]={'pixels':int(mask.sum()),'bounds':[int(xx.min()),int(yy.min()),int(xx.max()),int(yy.max())] if len(xx) else None}
        for col,img in enumerate(imgs):
            y=70+row*440
            draw.text((col*640+12,y+5),label,font=small,fill='white')
            sheet.paste(img.resize((640,400)),(col*640,y+32))
        summary[fixture]['pairs'].append(info)
    sheet.save(OUT/f'{fixture}-sheet.png')
    print(fixture,json.dumps(summary[fixture]['pairs']))
(OUT/'comparison-manifest.json').write_text(json.dumps(summary,indent=2))
