#!/usr/bin/env python3
"""Reproduce reviewed crops/masks and amplified exact/5%-fuzz diffs.
Requires curl and ImageMagick convert/compare. No resampling or noise removal.
Coordinates are half-open source pixels. G1 source URLs are supplied by the report.
"""
import hashlib
import json
from pathlib import Path
import subprocess
import sys
HOST='https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/'
ROWS={
 'F2':('0fa27d0aeffa7fd2/before-F2.png','92d1e9a06b0f6379/after-F2.png',(820,24,1080,764)),
 'F3':('eb1c39fc4b561e40/F3-before-source.png','59beacb26313c3e2/F3-after-source.png',(0,30,375,812)),
 'F5':('cd7988e5de8eb89c/before-F5.png','308a25d0002c96dd/after-F5.png',(820,24,1080,764)),
 'F8':('3930bac3299ccc9c/before-I3.png','d7a85e326a0745e4/after-I3.png',(0,0,375,812)),
 'I2':('8a712e861ddeb568/before-I2.png','75246e3afd71530c/after-I2-final.png',(820,24,1080,764)),
}
def compare(a,b,out,fuzz):
 r=subprocess.run(['compare','-metric','AE','-fuzz',fuzz,'-highlight-color','#ff00ff','-lowlight-color','#151515','-compose','src',str(a),str(b),str(out)],capture_output=True,text=True)
 if r.returncode not in (0,1):raise RuntimeError(r.stderr)
 return int(r.stderr)
def render(root,row,box):
 left,top,right,bottom=box
 outputs=[]
 for side in ('before','after'):
  src=root/f'{row}-{side}-source.png';out=root/f'{row}-{side}-crop.png'
  cmd=['convert',str(src),'-alpha','off','-crop',f'{right-left}x{bottom-top}+{left}+{top}','+repage']
  if row=='F8':cmd+=['-fill','#888888','-draw','rectangle 276,605 328,621 rectangle 77,677 127,694']
  subprocess.run([*cmd,str(out)],check=True);outputs.append(out)
 exact=compare(*outputs,root/f'{row}-Diff0.png','0%')
 threshold=compare(*outputs,root/f'{row}-DiffT-5pct.png','5%')
 files=[root/f'{row}-{side}-source.png' for side in ('before','after')]+outputs+[root/f'{row}-Diff0.png',root/f'{row}-DiffT-5pct.png']
 return {'crop_half_open':box,'timestamp_masks':[(276,605,329,622),(77,677,128,695)] if row=='F8' else [],'diff0_pixels':exact,'diffT_5pct_pixels':threshold,'sha256':{f.name:hashlib.sha256(f.read_bytes()).hexdigest() for f in files}}
def main():
 root=Path(sys.argv[1]).resolve();root.mkdir(parents=True,exist_ok=True);manifest={}
 for row,(before,after,box) in ROWS.items():
  for side,url in [('before',before),('after',after)]:
   subprocess.run(['curl','-fsSL',HOST+url,'-o',str(root/f'{row}-{side}-source.png')],check=True)
  manifest[row]=render(root,row,box);manifest[row]['source_urls']={'before':HOST+before,'after':HOST+after};print(row,manifest[row]['diff0_pixels'],manifest[row]['diffT_5pct_pixels'])
 if (root/'G1-before-source.png').exists() and (root/'G1-after-source.png').exists():manifest['G1']=render(root,'G1',(726,34,1210,834))
 (root/'manifest.json').write_text(json.dumps(manifest,indent=2)+'\n')
if __name__=='__main__':main()
