#!/usr/bin/env python3
from pathlib import Path
import json,hashlib,subprocess,sys,datetime
P='gacmai_20260717_184527';R=Path('/data/video-pipeline/GacMaiAudio/project')/P;A=R/'artifacts';S=A/'scripts';OUT=A/'story_package_candidate_rev4.json';OUTLINE='6648cdf5473d3bf72c759726357ecfcf480feea01424569e866fced1abb6e7e9';EXPECTED=['73feb92be9eae66d3726cfdf167deedb1aa8467405e981804aa149a89efd64e3',None,'f754a15a5484a340b18bb8a549679bf599d5b09f3bc110735883a6307278baeb'];PARENT_MIDDLE='61fdd4fd0fd5a664fd88cbc9879bf0db9257c70a4c58b6304629eccc33678e41'
if len(sys.argv)!=4:raise SystemExit('usage: assemble_story_rev4 B1 B2_REV1 B3')
if OUT.exists():raise SystemExit('rev1 already exists')
def sha(p):return hashlib.sha256(p.read_bytes()).hexdigest()
paths=[Path(x) for x in sys.argv[1:]];ranges=[(1,4),(5,8),(9,12)];sources=[];parts=[]
for idx,(p,(a,b)) in enumerate(zip(paths,ranges)):
 h=sha(p)
 if EXPECTED[idx] and h!=EXPECTED[idx]:raise SystemExit(f'protected batch changed {p}')
 d=json.loads(p.read_text());cp=subprocess.run(['python3',str(S/'validate_batch.py'),str(p),str(a),str(b)],capture_output=True,text=True);v=json.loads(cp.stdout)
 if cp.returncode or v.get('status')!='passed' or d.get('outline_sha256')!=OUTLINE:raise SystemExit(f'batch gate failed {p}: {v}')
 parts.extend(d['parts']);sources.append({'path':str(p),'sha256':h,'part_range':[a,b],'parent_sha256':PARENT_MIDDLE if idx==1 else None})
story={'project_id':P,'title':'Mùa Nở Không Có Tên','outline_sha256':OUTLINE,'pov':'Nguyễn Lam Chi','named_characters':['Nguyễn Lam Chi','Trần Vĩnh Phúc','Lê Thu Nguyệt','Phạm Hữu Tường','Đỗ Khánh An','Vũ Minh Triết'],'revision':4,'parent_story_sha256':'6b16fa65960168577873d8c4710275f5d7c400477cea40304389185ddd3b80e2','sources':sources,'parts':parts};OUT.write_text(json.dumps(story,ensure_ascii=False,indent=2)+'\n');h=sha(OUT);checks={}
cmds=[('validation',['python3',str(S/'validate_story.py'),str(OUT)]),('duplication',['python3',str(S/'audit_duplication.py'),str(OUT)]),('alignment',['python3',str(S/'audit_story_alignment.py'),str(OUT),str(A/'locked_outline_canonical.json')])]
for name,cmd in cmds:
 cp=subprocess.run(cmd,capture_output=True,text=True);checks[name]=json.loads(cp.stdout)
 if cp.returncode or checks[name].get('status')!='passed':
  rec={'status':'failed','story_sha256':h,'sources':sources,'checks':checks,'failed_gate':name};(A/'story_assembly_receipt_rev4.json').write_text(json.dumps(rec,ensure_ascii=False,indent=2)+'\n');print(json.dumps(rec,ensure_ascii=False));raise SystemExit(1)
rec={'status':'passed','story_sha256':h,'parent_story_sha256':story['parent_story_sha256'],'sources':sources,'checks':checks,'created_at':datetime.datetime.now(datetime.timezone.utc).isoformat()};(A/'story_assembly_receipt_rev4.json').write_text(json.dumps(rec,ensure_ascii=False,indent=2)+'\n');print(json.dumps(rec,ensure_ascii=False))
