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

PROJECT = Path('/data/video-pipeline/Youtube-Video-Maker/Project/001-La-Van-Cau')
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 'cánh tay' in low or 'bị thương' in low or 'chặt' in low:
        return 'La Văn Cầu bị thương nặng ở cánh tay bên hàng rào Đông Khê, vẫn ôm bộc phá bằng tay còn lại giữa khói lửa.'
    if 'bộc phá' in low or 'lô cốt' in low or 'hàng rào' in low or 'cửa mở' in low:
        return 'Tổ bộc phá Việt Minh áp sát lô cốt Đông Khê, dây thép gai, đất đá tung lên và cửa mở trong làn đạn.'
    if 'đông khê' in low or 'đường số 4' in low or 'biên giới' in low:
        return 'Cứ điểm Đông Khê trên đường số 4, núi rừng Cao Bằng, công sự Pháp và mũi tiến công Việt Minh năm 1950.'
    if 'cao bằng' in low or 'phong nặm' in low or 'trùng khánh' in low or 'dân tộc tày' in low:
        return 'Bản làng Tày ở Cao Bằng giữa núi đá, nương rẫy, suối lạnh và tuổi thơ La Văn Cầu dưới ách thực dân.'
    if 'quân đội' in low or 'trung đoàn 174' in low or 'người lính' in low:
        return 'Người lính trẻ La Văn Cầu trong quân phục Việt Minh, hành quân qua rừng núi, rèn luyện cùng Trung đoàn 174.'
    if 'chiến dịch biên giới' in low or 'thu đông 1950' in low:
        return 'Chiến dịch Biên giới Thu Đông 1950 mở màn, đội hình bộ đội và dân công vượt rừng núi hướng về Đông Khê.'
    if 'anh hùng' in low or '1952' in low or 'hậu thế' in low or 'đời thường' in low:
        return 'La Văn Cầu sau chiến tranh, người anh hùng cụt một tay giữa đời thường, trang sách lịch sử và ký ức thế hệ sau.'
    return 'Kháng chiến chống Pháp ở Việt Bắc, người lính Việt Minh giữa núi rừng, khói súng và ký ức lịch sử trên giấy cổ.'

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
            scenes.append({'scene_id': f'scene_{sid:03d}', 'type': 'heading', 'section': sec, 'text': txt, 'narration': txt, 'summary': txt, 'visual_beat': visual('', 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 >= 46 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, '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']
                    scenes[-1]['visual_beat'] = visual(scenes[-1]['text'], sec)
                    scenes[-1]['summary'] = scenes[-1]['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, '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':'La Văn Cầu người lính trẻ','role':'Main hero, Tày Vietnamese soldier in Trung đoàn 174 during the First Indochina War','estimated_age':'17-19','appearance':'young Tày man from Cao Bằng, lean mountain build, sun-darkened face, determined eyes, modest and resilient','costume':'Viet Minh infantry uniform 1948-1950, simple green-brown clothes, cloth cap, canvas belt, field pack','temperament':'quiet, brave, disciplined, enduring','historical_cultural_context':'Cao Bằng and Border Campaign 1950, Vietnamese resistance against French colonial rule','visual_keywords':['La Van Cau','Viet Minh infantry','Cao Bang','Tay ethnic'], 'negative_notes':'no modern gear, no American Vietnam War uniform, no fantasy, no glossy heroic armor'},
    {'name':'La Văn Cầu ôm bộc phá','role':'Main hero during the Đông Khê assault carrying explosive charge after severe arm wound','estimated_age':'19','appearance':'wounded but resolute young Vietnamese soldier, dirt, smoke, restrained pain and urgency, one arm disabled','costume':'battle-worn Viet Minh infantry clothing, ammunition belt, bộc phá charge, cloth cap','temperament':'fearless, sacrificial, mission-focused','historical_cultural_context':'Battle of Đông Khê, Border Campaign, 16 September 1950','visual_keywords':['explosive charge','Dong Khe','arm wound','bunker assault'], 'negative_notes':'no gore spectacle, no superhero pose, no modern weapons, no fantasy effects'},
    {'name':'Tổ bộc phá Trung đoàn 174','role':'Viet Minh assault engineers opening wire and bunker obstacles at Đông Khê','estimated_age':'young adult soldiers','appearance':'Vietnamese soldiers crawling and rushing through smoke, tense faces, teamwork under fire','costume':'1950 Viet Minh field uniforms, cloth caps, sandals, satchels, explosive charges','temperament':'coordinated, tense, courageous','historical_cultural_context':'Infantry assault on French fortified posts in the First Indochina War','visual_keywords':['Viet Minh sappers','barbed wire','bunker','explosives'], 'negative_notes':'no modern body armor, no American war gear, no fantasy'},
    {'name':'Đồng đội và dân công Cao Bằng','role':'Comrades and support people in the Border Campaign and Cao Bằng mountain homeland','estimated_age':'varied adults','appearance':'Vietnamese Tày/Nùng/Kinh soldiers and civilians, rugged mountain faces, carrying supplies through forest','costume':'rural northern mountain clothing, nón lá, shoulder poles, Viet Minh simple uniforms','temperament':'resilient, communal, supportive','historical_cultural_context':'Cao Bằng border region, Việt Bắc base area, logistics of 1950 campaign','visual_keywords':['Cao Bang','dan cong','Viet Bac forest'], 'negative_notes':'no contemporary clothing, no modern vehicles as focus'},
    {'name':'Quân Pháp tại Đông Khê','role':'Opposing French colonial troops inside fortified bunkers on Route 4','estimated_age':'adult soldiers','appearance':'French Union soldiers in bunkers and trenches, silhouettes behind sandbags and barbed wire','costume':'1950 French colonial uniforms, helmets, bunker equipment','temperament':'entrenched, defensive, alarmed','historical_cultural_context':'French fortified point at Đông Khê on Route 4, 1950','visual_keywords':['French bunker','Route 4','barbed wire'], 'negative_notes':'no Nazi styling, no modern NATO gear'}
]

def main():
    cleaned = clean(SRC.read_text(encoding='utf-8'))
    (PROJECT/'script/cleaned_story.txt').write_text(cleaned, encoding='utf-8')
    scenes = build(cleaned)
    for sc in scenes:
        prompt = ('16:9 horizontal historical storytelling image, ink-wash narrative window on warm antique cream paper, painted content only 65-70% of frame with clean parchment negative space. ' +
                  f"Scene: {sc['visual_beat']} Narration beat: {sc['narration']} Historical grounding: Cao Bằng, Việt Bắc, First Indochina War, Battle of Đông Khê 1950, Viet Minh infantry and sappers, French colonial bunkers, Route 4, barbed wire, explosive charges. Negative: no modern objects, no American Vietnam War gear, no fantasy armor, no gore spectacle, no 3D game art, no full-frame glossy poster, no text labels or watermark.")
        sc['visual_prompt'] = prompt
    (PROJECT/'script/scenes.json').write_text(json.dumps({'project_id': PROJECT.name, 'target_beat_seconds':'14-22', 'split_rule':'Headings standalone; grouped 14-22s visual beats.', 'total_scenes':len(scenes), 'scenes':scenes}, ensure_ascii=False, indent=2), encoding='utf-8')
    validation = {'project_id':PROJECT.name,'total_scenes':len(scenes),'metadata_removed_from_scenes':True,'headings_standalone':True,'each_scene_has_visual_beat':True,'required_characters_present':True,'status':'passed'}
    (PROJECT/'script/scenes_validation.json').write_text(json.dumps(validation, ensure_ascii=False, indent=2), encoding='utf-8')
    bible = {'project_id':PROJECT.name,'visual_style_global':'16:9 horizontal historical storytelling image, Cao Bằng and Đông Khê 1950, ink-wash window centered on warm antique paper, muted sepia brown charcoal olive watercolor, no modern/fantasy drift.','consistency_rules':['Use La Văn Cầu người lính trẻ for childhood, enlistment, training and general campaign scenes.','Use La Văn Cầu ôm bộc phá for the decisive wounded assault at Đông Khê.','Keep Viet Minh 1950 uniforms, Cao Bằng mountain villages, Route 4 bunkers and French colonial equipment historically grounded.'],'characters':chars}
    (PROJECT/'script/character_bible.json').write_text(json.dumps(bible, ensure_ascii=False, indent=2), encoding='utf-8')
    (PROJECT/'script/dense_scene_plan.json').write_text(json.dumps({'project_id':PROJECT.name,'approved_for_next_step':True,'total_scenes':len(scenes),'scenes':scenes}, ensure_ascii=False, indent=2), encoding='utf-8')
    for step,name in [(2,'Clean Story And Split Scenes'),(3,'Character Bible'),(4,'Validate Scene Plan')]:
        (PROJECT/f'logs/step{step:02d}_manifest.json').write_text(json.dumps({'project_id':PROJECT.name,'step':step,'name':name,'status':'completed','total_scenes':len(scenes),'timestamp':time.strftime('%Y-%m-%dT%H:%M:%S')}, ensure_ascii=False, indent=2), encoding='utf-8')
    check=json.loads((PROJECT/'checklist_19_steps.json').read_text(encoding='utf-8'))
    names={2:'Clean Story And Split Scenes',3:'Character Bible',4:'Validate Scene Plan'}
    for s in check['steps']:
        if s['step'] in names:
            s['name']=names[s['step']]; s['status']='completed'; s['completed_at']=time.strftime('%Y-%m-%dT%H:%M:%S')
    (PROJECT/'checklist_19_steps.json').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 s['status']=='completed' else ' '}] Step {s['step']:02d}: {s['name']} - {s['status']}" for s in check['steps'])+'\n',encoding='utf-8')
    print(json.dumps({'project':str(PROJECT),'total_scenes':len(scenes)}, ensure_ascii=False))
if __name__ == '__main__':
    main()
