#!/usr/bin/env python3
import hashlib,json,subprocess,sys
from datetime import datetime,timezone
from pathlib import Path
P=Path(__file__).resolve().parents[1]
def load(rel):
 p=P/rel
 return json.loads(p.read_text()) if p.is_file() else {}
def sha(p):
 h=hashlib.sha256()
 with p.open('rb') as f:
  for b in iter(lambda:f.read(8*1024*1024),b''):h.update(b)
 return h.hexdigest()
def main():
 checks={}
 for name,script in [('family','validate-family-causal.py'),('story','validate-story.py'),('originality','validate-originality.py')]:checks[name]=subprocess.run([sys.executable,str(P/'script'/script)],cwd=P,stdout=subprocess.DEVNULL).returncode==0
 checks['workflow_copy']=subprocess.run([sys.executable,str(P/'script/validate-workflow-copy.py'),'full'],cwd=P,stdout=subprocess.DEVNULL).returncode==0
 promo=load('story/promotion.json');canon=promo.get('spoken_narration_sha256');checks['promotion']=promo.get('verified') is True and canon==sha(P/'story/story-canon.txt')
 specs={'tts':'log/tts-verification.json','image':'log/image-generation.json','image_qa':'log/image-visual-qa.json','layout':'image/layout-manifest-r2.json','intro':'log/intro-render.json','footage':'log/footage-job.json','final':'log/final-render.json','transcode':'log/upload-transcode.json','metadata':'log/metadata-verification.json'}
 rows={k:load(v) for k,v in specs.items()}
 for k,r in rows.items():checks[k]=r.get('verified') is True and r.get('source_canon_sha256')==canon
 checks['layout']=checks['layout'] and rows['layout'].get('status')=='completed' and rows['layout'].get('visual_qa',{}).get('verified') is True
 checks['intro']=checks['intro'] and rows['intro'].get('output_sha256')==sha(P/'output/intro/intro.mp4')
 checks['footage']=checks['footage'] and rows['footage'].get('output_sha256')==sha(P/'output/footage/footage.mp4') and rows['footage'].get('server_verification',{}).get('mirror_applied') is True and rows['footage'].get('server_verification',{}).get('source_audio_discarded') is True
 checks['final']=checks['final'] and rows['final'].get('output_sha256')==sha(P/'output/final.mp4')
 checks['transcode']=checks['transcode'] and rows['transcode'].get('output_sha256')==sha(P/'output/final-upload.mp4') and (P/'output/final-upload.mp4').stat().st_size<1_000_000_000 and rows['transcode'].get('server_verification',{}).get('under_one_gb') is True
 checks['metadata']=checks['metadata'] and rows['metadata'].get('info_sha256')==sha(P/'output/info.txt')
 checks['pronunciation']=load('log/tts-pronunciation.json').get('verified') is True and load('log/tts-pronunciation.json').get('reverse_verified') is True
 checks['intro_pronunciation']=load('log/intro-tts-pronunciation.json').get('verified') is True and load('log/intro-tts-pronunciation.json').get('reverse_verified') is True
 checks['intro_voice']=load('log/intro-voice.json').get('verified') is True and load('log/intro-voice.json').get('output_sha256')==sha(P/'audio/intro-voice.wav')
 issues=[k for k,v in checks.items() if not v];report={'version':1,'verified':not issues,'status':'passed' if not issues else 'failed','source_canon_sha256':canon,'checks':checks,'issues':issues,'checked_at':datetime.now(timezone.utc).isoformat()};(P/'log/production-verification.json').write_text(json.dumps(report,ensure_ascii=False,indent=2)+'\n');print(json.dumps({'verified':report['verified'],'passed':sum(checks.values()),'total':len(checks),'issues':issues},ensure_ascii=False));return 0 if report['verified'] else 1
if __name__=='__main__':sys.exit(main())
