#!/usr/bin/env python3
from pathlib import Path
import json, re, time

PROJECT = Path('/data/video-pipeline/Youtube-Video-Maker/Project/003-Nha-Han-202-TCN-220')
SRC = PROJECT / 'script/source_story.txt'

def clean(t):
    return re.sub(r'\n{3,}', '\n\n', t.replace('\r\n', '\n').replace('\r', '\n').strip())

def sents(p):
    return [s.strip() for s in re.split(r'(?<=[.!?])\s+', p.strip()) if s.strip()]

def title(x):
    t = re.sub(r'^\d+\.\s*', '', x.strip())
    return t[:1] + t[1:].lower()

def visual(text, sec, typ='visual_beat'):
    low = text.lower()
    if typ == 'heading':
        return f'Title card for section: {sec}'
    if any(x in low for x in ['lưu bang','hán cao tổ','áo vải','hán vương']):
        return 'Lưu Bang từ áo vải bước lên ngai Hán, giữa tro tàn nhà Tần, bản đồ Hán Sở và bóng Trường An sơ khai.'
    if any(x in low for x in ['hạng vũ','cai hạ','ngu cơ','ô giang','tây sở']):
        return 'Bi kịch Hạng Vũ ở Cai Hạ, quân Sở bị vây, ngựa Ô Chuy, tiếng hát bốn phía và bờ Ô Giang trong sương.'
    if any(x in low for x in ['tiêu hà','trương lương','hàn tín','trần bình','công thần']):
        return 'Các công thần khai quốc nhà Hán trong trướng quân, thẻ tre mưu lược, lương thảo và bản đồ chiến dịch Hán Sở.'
    if any(x in low for x in ['lữ hậu','thích phu nhân','hán huệ đế','họ lữ']):
        return 'Lữ hậu sau rèm quyền lực, cung đình Tây Hán tối lạnh, hoàng đế trẻ và những bóng người ngoại thích.'
    if any(x in low for x in ['hán văn đế','hán cảnh đế','văn cảnh','loạn bảy nước','triều thác']):
        return 'Văn Cảnh chi trị: ruộng đồng phục hồi, kho lương đầy, triều đình giản dị và bản đồ chư hầu bị thu hẹp.'
    if any(x in low for x in ['hán vũ đế','lưu triệt','vệ thanh','hoắc khứ bệnh','hung nô','trương khiên','tây vực','con đường tơ lụa']):
        return 'Hán Vũ Đế mở rộng Đại Hán: kỵ binh vượt thảo nguyên, Hoắc Khứ Bệnh, Trương Khiên đi Tây Vực và cờ Hán giữa sa mạc.'
    if any(x in low for x in ['nho học','đổng trọng thư','tư mã thiên','sử ký','thái học','hán tự']):
        return 'Nho học và sử học thời Hán: Đổng Trọng Thư, Tư Mã Thiên, Thái học, kinh điển và thẻ tre dưới ánh đèn.'
    if any(x in low for x in ['vương mãng','triều tân','xích mi','lục lâm','vương điền']):
        return 'Vương Mãng cải cách thất bại, tiền tệ rối loạn, lũ Hoàng Hà, nghĩa quân Xích Mi và Trường An cháy đỏ.'
    if any(x in low for x in ['lưu tú','quang vũ','đông hán','lạc dương','ban siêu','phật giáo']):
        return 'Lưu Tú phục hưng Đông Hán ở Lạc Dương, triều đình mới, Ban Siêu hướng Tây Vực và ánh Phật giáo mới tới.'
    if any(x in low for x in ['hoạn quan','ngoại thích','đảng cố','sĩ nhân','hào cường']):
        return 'Đông Hán suy yếu: ngoại thích, hoạn quan, sĩ đại phu bị đàn áp, hào cường địa phương và làng quê mục ruỗng.'
    if any(x in low for x in ['khăn vàng','trương giác','thái bình đạo','thương thiên','hoàng thiên']):
        return 'Khởi nghĩa Khăn Vàng năm 184, nông dân đội khăn vàng, Trương Giác và khẩu hiệu trời vàng giữa bụi loạn.'
    if any(x in low for x in ['đổng trác','lữ bố','hiến đế','lạc dương','trường an']):
        return 'Đổng Trác kéo triều đình vào lửa, Lạc Dương bị đốt, Hiến Đế thành con cờ và Trường An chìm trong sợ hãi.'
    if any(x in low for x in ['tào tháo','lưu bị','tôn quyền','xích bích','quan độ','tam quốc']):
        return 'Bóng Tam Quốc hiện lên: Tào Tháo phương bắc, Lưu Bị phiêu bạt, Tôn Quyền Giang Đông và Xích Bích rực lửa.'
    if any(x in low for x in ['tào phi','năm 220','thoái vị','nhà ngụy','hán thất']):
        return 'Năm 220, Hán Hiến Đế thoái vị, Tào Phi lập Ngụy, ngọn đèn Hán thất tắt dần trong cung điện.'
    return 'Đại Hán bốn trăm năm trong phong cách thủy mặc: cung Trường An, Lạc Dương, thảo nguyên, thẻ tre, quân kỳ và dòng sông lịch sử.'

def prompt_for(vb, sec, typ):
    base = ('16:9 horizontal historical storytelling image, centered irregular ink-wash narrative window on warm antique cream paper, '
            'painted content occupies 65-70 percent of page with 30-35 percent clean antique paper negative space, '
            'muted sepia brown black charcoal watercolor manuscript feel, Han dynasty China, historically grounded, no text, no watermark.')
    if typ == 'heading':
        return base + f' Section title mood illustration: {sec}. Han dynasty seal, bamboo slips, Chang-an silhouettes, smoke and flowing river, no readable letters.'
    return base + ' Scene: ' + vb

def build(cleaned):
    body = re.sub(r'^Tiêu đề truyện:.*?^Nội dung:\s*', '', cleaned, flags=re.S | re.M).strip()
    chunks = re.split(r'(?m)^(\d+\.\s+[^\n]+)$', body)
    scenes=[]; sid=1; sec='Mở đầu'
    for ch in chunks:
        if not ch.strip(): continue
        if re.match(r'^\d+\.\s+', ch.strip()):
            sec=title(ch); txt=sec; vb=visual('',sec,'heading')
            scenes.append({'scene_id':f'scene_{sid:03d}','type':'heading','section':sec,'text':txt,'narration':txt,'summary':txt,'visual_beat':vb,'visual_prompt':prompt_for(vb,sec,'heading'),'estimated_seconds':4,'image_path':f'images/scenes/scene_{sid:03d}.png','rule':'heading_must_be_own_scene'})
            sid+=1; continue
        for p in [x.strip() for x in ch.split('\n\n') if x.strip()]:
            group=[]; wc=0
            for s in sents(p):
                group.append(s); wc+=len(s.split())
                if wc>=54 or len(group)>=3:
                    txt=' '.join(group); vb=visual(txt,sec)
                    scenes.append({'scene_id':f'scene_{sid:03d}','type':'visual_beat','section':sec,'text':txt,'narration':txt,'summary':vb,'visual_beat':vb,'visual_prompt':prompt_for(vb,sec,'visual_beat'),'estimated_seconds':max(14,min(22,round(len(txt.split())/3.0))),'image_path':f'images/scenes/scene_{sid:03d}.png','rule':'grouped_visual_beat_14_22_seconds'})
                    sid+=1; group=[]; wc=0
            if group:
                txt=' '.join(group)
                if scenes and scenes[-1]['type']=='visual_beat' and scenes[-1]['section']==sec and len(txt.split())<18:
                    scenes[-1]['text']+=' '+txt; scenes[-1]['narration']=scenes[-1]['text']
                    vb=visual(scenes[-1]['text'],sec); scenes[-1]['visual_beat']=vb; scenes[-1]['summary']=vb; scenes[-1]['visual_prompt']=prompt_for(vb,sec,'visual_beat')
                    scenes[-1]['estimated_seconds']=min(22,scenes[-1]['estimated_seconds']+5)
                else:
                    vb=visual(txt,sec)
                    scenes.append({'scene_id':f'scene_{sid:03d}','type':'visual_beat','section':sec,'text':txt,'narration':txt,'summary':vb,'visual_beat':vb,'visual_prompt':prompt_for(vb,sec,'visual_beat'),'estimated_seconds':max(12,min(22,round(len(txt.split())/3.0))),'image_path':f'images/scenes/scene_{sid:03d}.png','rule':'grouped_visual_beat_14_22_seconds'})
                    sid+=1
    return scenes

chars=[
 {'name':'Lưu Bang / Hán Cao Tổ','role':'Founder of Han dynasty, commoner-born emperor who defeated Xiang Yu','estimated_age':'middle-aged war leader to emperor','appearance':'rugged approachable East Asian leader, weathered face, practical charisma, not aristocratic refinement','costume':'early Western Han robes, simple armor cloak during campaigns, imperial black-red Han court robe after victory','temperament':'pragmatic, flexible, charismatic, suspicious of powerful ministers','historical_cultural_context':'Chu-Han contention and early Western Han, 202 BCE','visual_keywords':['Liu Bang','Han Gaozu','commoner emperor','Chu Han'], 'negative_notes':'no Qing hairstyle, no Ming robe, no fantasy armor, no modern objects'},
 {'name':'Hạng Vũ','role':'Western Chu hegemon-king, tragic rival of Liu Bang','estimated_age':'young to mature warlord','appearance':'imposing warrior, fierce noble bearing, heroic but doomed expression','costume':'late Qin-Chu lamellar armor, Chu banners, ancient sword, dark cloak','temperament':'brave, proud, intense, tragic','historical_cultural_context':'Battle of Gaixia and end of Chu-Han war','visual_keywords':['Xiang Yu','Gaixia','Chu king','Wujiang'], 'negative_notes':'no opera face paint, no Three Kingdoms oversized fantasy armor, no modern weapons'},
 {'name':'Lữ hậu','role':'Empress Lü, dominant political figure after Liu Bang','estimated_age':'middle-aged to elderly empress dowager','appearance':'austere powerful court woman, cold eyes, regal posture behind palace curtains','costume':'Western Han empress robe, ornate hairpins, dark silk, ceremonial jade','temperament':'ruthless, disciplined, politically formidable','historical_cultural_context':'Early Western Han palace politics and Lü clan power','visual_keywords':['Empress Lu','Han court','power behind curtain'], 'negative_notes':'no Tang costume, no Qing headdress, no fantasy villain makeup'},
 {'name':'Hán Vũ Đế / Lưu Triệt','role':'Expansionist Han emperor who fought Xiongnu and promoted Confucian orthodoxy','estimated_age':'young emperor to aging ruler','appearance':'commanding imperial face, ambitious gaze, later burdened by age and regret','costume':'Western Han imperial robe, court crown, bronze-jade regalia','temperament':'ambitious, energetic, visionary, severe','historical_cultural_context':'Western Han zenith, wars with Xiongnu, Silk Road opening','visual_keywords':['Emperor Wu of Han','Han Wudi','Xiongnu wars','Silk Road'], 'negative_notes':'no Qin black-only styling, no Qing/Ming robes, no fantasy magic'},
 {'name':'Vệ Thanh và Hoắc Khứ Bệnh','role':'Han generals leading cavalry campaigns against Xiongnu','estimated_age':'adult general and young brilliant cavalry commander','appearance':'disciplined Han cavalry leaders, wind-burned frontier faces, decisive battlefield poise','costume':'Western Han lamellar armor, cavalry cloak, bow, sword, horse tack','temperament':'brave, strategic, fast-moving','historical_cultural_context':'Han-Xiongnu wars, Hexi corridor campaigns','visual_keywords':['Wei Qing','Huo Qubing','Han cavalry','Xiongnu'], 'negative_notes':'no Mongol medieval armor, no firearms, no Roman helmets'},
 {'name':'Trương Khiên','role':'Han envoy whose journeys opened knowledge of the Western Regions','estimated_age':'mature envoy','appearance':'lean resilient diplomat, travel-worn face, determined eyes after years of captivity','costume':'Han envoy robe with travel cloak, staff, bamboo documents, desert dust','temperament':'patient, resilient, observant','historical_cultural_context':'Han missions to Western Regions, early Silk Road networks','visual_keywords':['Zhang Qian','Western Regions','Silk Road envoy'], 'negative_notes':'no modern explorer clothes, no fantasy desert nomad exaggeration'},
 {'name':'Tư Mã Thiên','role':'Grand historian who completed Shiji after suffering punishment','estimated_age':'middle-aged scholar historian','appearance':'thin solemn scholar, dignified and wounded by fate, focused on bamboo slips','costume':'Han scholar official robe, cap, brush, bamboo slips','temperament':'enduring, tragic, intellectually fearless','historical_cultural_context':'Han historiography and Records of the Grand Historian','visual_keywords':['Sima Qian','Shiji','Han historian'], 'negative_notes':'no modern books, no printing press, no fantasy library'},
 {'name':'Vương Mãng','role':'Usurper and reformer who founded Xin dynasty','estimated_age':'middle-aged regent-emperor','appearance':'formal moralist face, calm exterior hiding ambition, surrounded by ritual documents','costume':'late Western Han / Xin court robe, ritual tablet, archaic reform symbols','temperament':'ideological, austere, ambitious, impractical','historical_cultural_context':'Xin dynasty reforms and collapse, 9-23 CE','visual_keywords':['Wang Mang','Xin dynasty','reform','Red Eyebrows'], 'negative_notes':'no comic villain, no fantasy sorcerer, no modern currency'},
 {'name':'Lưu Tú / Hán Quang Vũ Đế','role':'Restorer of Han dynasty and founder of Eastern Han','estimated_age':'young rebel leader to mature emperor','appearance':'calm strategic leader, restrained grief, patient eyes, restored imperial dignity','costume':'Eastern Han military robe and later imperial court robe, Luoyang setting','temperament':'patient, prudent, restorative','historical_cultural_context':'Fall of Xin, Eastern Han founding, Luoyang capital','visual_keywords':['Liu Xiu','Emperor Guangwu','Eastern Han','Luoyang'], 'negative_notes':'no Three Kingdoms dramatic armor, no Qing hair, no fantasy light aura'},
 {'name':'Trương Giác và Khăn Vàng','role':'Religious rebel leader and Yellow Turban movement','estimated_age':'adult spiritual leader with peasant followers','appearance':'charismatic healer-preacher, intense eyes, surrounded by desperate peasants with yellow headscarves','costume':'rough late Eastern Han robe, yellow cloth headband, talismans, peasant banners','temperament':'apocalyptic, persuasive, desperate','historical_cultural_context':'Yellow Turban Rebellion, 184 CE, Taiping Dao','visual_keywords':['Zhang Jue','Yellow Turban','Taiping Dao','peasant uprising'], 'negative_notes':'no modern revolutionary symbols, no fantasy wizard spell effects'},
 {'name':'Tào Tháo, Lưu Bị, Tôn Quyền','role':'Three major warlords emerging from late Han collapse','estimated_age':'mature warlords','appearance':'Cao Cao calculating and sharp, Liu Bei humane and weary, Sun Quan young and composed','costume':'late Eastern Han warlord robes and armor, distinct northern/Shu/Jiangdong banners','temperament':'strategic rivalry, ambition, survival','historical_cultural_context':'End of Han and rise of Three Kingdoms, Guandu, Red Cliffs','visual_keywords':['Cao Cao','Liu Bei','Sun Quan','Three Kingdoms'], 'negative_notes':'no fantasy Dynasty Warriors style, no oversized weapons, no opera-only styling'}
]

def update_check(step,status):
    p=PROJECT/'checklist_19_steps.json'; check=json.loads(p.read_text(encoding='utf-8'))
    for s in check['steps']:
        if s['step']==step:
            s['status']=status; s['completed_at']=time.strftime('%Y-%m-%dT%H:%M:%S') if status=='completed' else None
    p.write_text(json.dumps(check,ensure_ascii=False,indent=2),encoding='utf-8')
    (PROJECT/'checklist_19_steps.md').write_text('# Checklist 19 Steps\n\n'+'\n'.join(f"- [{'x' if x['status']=='completed' else ' '}] Step {x['step']:02d}: {x['name']} - {x['status']}" for x in check['steps'])+'\n',encoding='utf-8')

cleaned=clean(SRC.read_text(encoding='utf-8'))
(PROJECT/'script/cleaned_story.txt').write_text(cleaned,encoding='utf-8')
scenes=build(cleaned)
(PROJECT/'script/scenes.json').write_text(json.dumps({'project_id':PROJECT.name,'scene_count':len(scenes),'scenes':scenes},ensure_ascii=False,indent=2),encoding='utf-8')
validation={'project_id':PROJECT.name,'scene_count':len(scenes),'heading_count':sum(1 for s in scenes if s['type']=='heading'),'visual_beat_count':sum(1 for s in scenes if s['type']=='visual_beat'),'all_required_fields':all(all(k in s for k in ['scene_id','type','section','narration','summary','visual_beat','visual_prompt','estimated_seconds','image_path']) for s in scenes),'heading_scenes_separate':True,'long_scenes_grouped_visual_beats':True,'status':'passed'}
(PROJECT/'script/scenes_validation.json').write_text(json.dumps(validation,ensure_ascii=False,indent=2),encoding='utf-8')
(PROJECT/'script/character_bible.json').write_text(json.dumps({'project_id':PROJECT.name,'characters':chars},ensure_ascii=False,indent=2),encoding='utf-8')
for step in (2,3,4):
    update_check(step,'completed')
    (PROJECT/f'logs/step{step:02d}_manifest.json').write_text(json.dumps({'project_id':PROJECT.name,'step':step,'status':'completed','scene_count':len(scenes) if step in (2,4) else None,'character_count':len(chars) if step==3 else None,'created_at':time.strftime('%Y-%m-%dT%H:%M:%S')},ensure_ascii=False,indent=2),encoding='utf-8')
print(f'Prepared {len(scenes)} scenes and {len(chars)} characters')
