#!/usr/bin/env python3
import hashlib,json,subprocess,sys,time,urllib.request
from datetime import datetime,timezone
from pathlib import Path
PROJECT=Path(__file__).resolve().parents[1]
CONFIGS={'footage':{'submission':PROJECT/'log/footage-submission.json','receipt':PROJECT/'log/footage-job.json','output':PROJECT/'output/footage/footage.mp4','base':'http://192.168.1.104:8022','path':'/v1/footage-render-huyenan/jobs/'},'final':{'submission':PROJECT/'log/final-submission.json','receipt':PROJECT/'log/final-render.json','output':PROJECT/'output/final.mp4','base':'http://192.168.1.104:8023','path':'/v1/huyenan-render-final/jobs/'}}
def get(url):
 with urllib.request.urlopen(url,timeout=30) as r:return json.load(r)
def sha(path):
 h=hashlib.sha256()
 with path.open('rb') as f:
  for b in iter(lambda:f.read(8*1024*1024),b''):h.update(b)
 return h.hexdigest()
def probe(path):return json.loads(subprocess.run(['ffprobe','-v','error','-show_entries','format=duration,size','-show_entries','stream=index,codec_name,width,height,sample_rate,channels','-of','json',str(path)],capture_output=True,text=True,check=True).stdout)
def main():
 kind=sys.argv[1] if len(sys.argv)>1 else '';c=CONFIGS.get(kind)
 if not c:raise SystemExit('usage: poll-render-job.py footage|final')
 sub=json.loads(c['submission'].read_text());job_id=sub['job_id'];canon=sub['source_canon_sha256']
 for _ in range(480):
  job=get(c['base']+c['path']+job_id)
  if job.get('status') in {'completed','failed','cancelled'}:break
  time.sleep(10)
 else:raise RuntimeError('Poll timeout; resume same job')
 if job.get('status')!='completed' or job.get('verification',{}).get('verified') is not True:raise RuntimeError(f'{kind} job ended {job.get("status")}: {job.get("error")}')
 output=c['output'];data=probe(output);streams=data.get('streams',[]);v=[x for x in streams if x.get('width')];a=[x for x in streams if x.get('sample_rate')]
 verified=len(v)==1 and len(a)==1 and v[0].get('codec_name')=='h264' and (v[0].get('width'),v[0].get('height'))==(1920,1080) and a[0].get('codec_name')=='aac'
 if kind=='footage':verified=verified and job['verification'].get('mirror_applied') is True and job['verification'].get('source_audio_discarded') is True
 receipt={'version':1,'verified':verified,'source_canon_sha256':canon,'job_id':job_id,'status':job['status'],'endpoint':c['base']+c['path']+job_id,'server_verification':job['verification'],'output':str(output.relative_to(PROJECT)),'output_sha256':sha(output),'probe':data,'checked_at':datetime.now(timezone.utc).isoformat()}
 c['receipt'].write_text(json.dumps(receipt,ensure_ascii=False,indent=2)+'\n');print(json.dumps({'kind':kind,'verified':verified,'job_id':job_id,'duration':data['format']['duration'],'bytes':data['format']['size']},ensure_ascii=False));return 0 if verified else 1
if __name__=='__main__':sys.exit(main())
