#!/usr/bin/env python3
from pathlib import Path
import hashlib,json,os
ROOT=Path('/data/video-pipeline/HaTramAudio/project/022-Tiem-Giat-Mo-Cua-Luc-Bon-Gio-Muoi-Bay');PROJECT_ID=ROOT.name;RUN_ID='run-20260721T172022Z-9462493a';OWNER='Levy';WORK=ROOT/'work/artwork'/RUN_ID
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 guard():
 d=json.loads((ROOT/'.ownership-lock.json').read_text());assert d['project_id']==PROJECT_ID and d['run_id']==RUN_ID and d['owner']==OWNER
def main():
 guard();manifest=json.loads((ROOT/'script/project-manifest.json').read_text());canon=manifest.get('canon_sha256')
 story=manifest.get('gate_events',{}).get('story',{})
 if manifest.get('steps',{}).get('story')!='completed' or story.get('verified') is not True or story.get('canon_sha256')!=canon:raise RuntimeError('Story Gate is not committed/current')
 authority={k:ROOT/k for k in ['story/story-canon.txt','script/story-brief.json','script/ledger.json','script/outline.json','script/promotion-report.json']}
 if not all(p.is_file() for p in authority.values()):raise RuntimeError('committed Story Gate authority files are missing')
 promo=json.loads(authority['script/promotion-report.json'].read_text());assert promo['verified'] and promo['canon_sha256']==canon and sha(authority['story/story-canon.txt'])==canon
 brief=json.loads(authority['script/story-brief.json'].read_text());TITLE=brief['canonical_title']
 shared=f'''Thông tin nhân vật nội bộ, chỉ để giữ nhất quán, tuyệt đối không render thành chữ: Giang Vãn Đường là nữ chủ tiệm sửa áo cưới hai mươi chín tuổi, người châu Á hư cấu, tóc đen ngang vai, áo sơ mi màu kem và tạp dề may đo xanh rêu, ánh mắt thông minh nhưng mất ngủ. Tạ Hoài Chu là nam đầu bếp nhà ăn cộng đồng ba mươi hai tuổi, người châu Á hư cấu, tóc đen gọn, áo sơ mi trắng và tạp dề xám, vẻ điềm tĩnh và tôn trọng ranh giới. Tên chính thức: "{TITLE}". Thể loại: ngôn tình đô thị high-concept, drama cảm xúc, kỳ ảo có luật. Bối cảnh công khai: ngõ cũ Thành Đô trong mưa lúc 4:17 sáng, tiệm giặt hẹp lát gạch xanh chỉ hiện sau lần điện chớp. Motif công khai: chiếc áo sơ mi trắng, phiếu giặt bốn ô với ba dấu trừu tượng không chữ, ba món vải xám và cửa máy giặt tròn. Giới hạn tiết lộ: không thể hiện Vãn Đường dừng máy, ô thứ tư để trống, việc xây lại quan hệ hoặc coda một năm sau.
Phong cách key art phim điện ảnh cao cấp, digital illustration bán hiện thực, tối giản, một focal point rõ, low-key lighting, tương phản mạnh có kiểm soát, depth foreground-midground-background, không collage, không card, không slide, không mockup, không mô phỏng người thật.
Mọi phiếu giặt, ảnh, đồng hồ, đồ nội thất và nhãn trong cảnh phải trơn hoặc chỉ có đường nét không tạo ký tự đọc được. Không logo, watermark, số, pseudo-text hoặc chữ môi trường ngoài các khối chữ bắt buộc. Provider tạo hoàn chỉnh hình và typography trong cùng raster; cấm background no-text, text layer riêng hoặc chừa chỗ hậu kỳ.
'''
 poster=shared+f'''Tạo poster ngang tỷ lệ 16:9, master 1920x1080 cho intro và thumbnail. Giang Vãn Đường là focal point trước cửa tiệm giặt gạch xanh, cầm chiếc áo sơ mi trắng còn khô; Tạ Hoài Chu đứng lớp sau dưới biển đèn lúc 4:17, giữa họ là cửa máy giặt tròn và ba mảnh vải xám. Mưa, ánh xanh ngọc và đèn hổ phách tạo cảm giác kỳ ảo gần gũi, căng thẳng cảm xúc nhưng không kinh dị. Không lộ kết thúc. Provider tự quyết font, vị trí, kích thước, xuống dòng, khoảng cách và phân cấp.
RENDER CHÍNH XÁC BA KHỐI CHỮ TIẾNG VIỆT SAU TRỰC TIẾP TRONG CÙNG ẢNH, KHÔNG THÊM CHỮ KHÁC:
"Hạ Trâm Audio"
"{TITLE}"
"Truyện được phát độc quyền tại Hạ Trâm Audio, nghiêm cấm sao chép dưới mọi hình thức"
Giữ nguyên từng chữ, dấu tiếng Việt và dấu phẩy; chữ dễ đọc, không cắt hoặc che.
'''
 right=shared+f'''Tạo key art dọc tỷ lệ chính xác 656:1080, master 1080x1778 dùng nguyên raster làm panel phải. Giang Vãn Đường là focal point cầm chiếc áo sơ mi trắng trước cửa máy giặt tròn; Tạ Hoài Chu đứng lớp sau ngoài cửa kính mưa, giữ khoảng cách tôn trọng. Ba món vải xám và đồng hồ trừu tượng không số là motif; không có giấy tờ hoặc chữ môi trường đọc được. Bố cục dọc tối giản, không crop chủ thể quan trọng. Provider tự quyết toàn bộ typography.
RENDER CHÍNH XÁC BA KHỐI CHỮ TIẾNG VIỆT SAU TRỰC TIẾP TRONG CÙNG ẢNH, KHÔNG THÊM CHỮ KHÁC:
"Hạ Trâm Audio"
"{TITLE}"
"Truyện được phát độc quyền tại Hạ Trâm Audio, nghiêm cấm sao chép dưới mọi hình thức"
Giữ nguyên từng chữ, dấu tiếng Việt và dấu phẩy; chữ dễ đọc, không cắt hoặc che.
'''
 left=shared+'''Tạo branding panel điện ảnh dọc tỷ lệ chính xác 656:1080, master 1080x1778 cho cạnh trái layout. Cùng color grade với poster: gạch men xanh ngọc, mưa trên kính, ánh đèn hổ phách và các vòng cửa máy giặt trừu tượng; không nhân vật, không tên truyện, không dòng độc quyền. Cạnh phải có transition texture nhẹ, không aperture, khung màn hình hoặc layout giả. Provider tự quyết typography.
RENDER CHÍNH XÁC HAI KHỐI CHỮ TIẾNG VIỆT SAU TRỰC TIẾP TRONG CÙNG ẢNH, KHÔNG THÊM CHỮ KHÁC:
"Hạ Trâm Audio"
"Like • Chia sẻ • Đăng ký"
Giữ nguyên chính tả và dấu tiếng Việt; chữ dễ đọc, không cắt hoặc che.
'''
 WORK.mkdir(parents=True,exist_ok=True);items={}
 for key,prompt in {'intro_poster':poster,'right_panel':right,'left_panel':left}.items():
  p=WORK/f'{key}.prompt.txt';p.write_text(prompt);items[key]={'prompt_path':str(p),'prompt_sha256':sha(p)}
 manifest={'schema_version':1,'project_id':PROJECT_ID,'run_id':RUN_ID,'status':'locked','verified':True,'source_canon_sha256':canon,'authority_sha256':{k:sha(p) for k,p in authority.items()},'canonical_title':TITLE,'provider_skill':'tao-anh','provider_model':'cx/gpt-5.5-image','provider_only_typography':True,'text_postprocessing_allowed':False,'items':items}
 p=ROOT/'script/image-prompts.json';tmp=p.with_name('.image-prompts.json.tmp');tmp.write_text(json.dumps(manifest,ensure_ascii=False,indent=2)+'\n');os.replace(tmp,p);print(json.dumps({'status':'locked','verified':True,'source_canon_sha256':canon,'items':items},ensure_ascii=False))
if __name__=='__main__':main()
