import re
import sys
import json
from pathlib import Path

sys.stdout.reconfigure(encoding='utf-8')

screenplay_path = Path("FilmMaker/TAP_01_XUAN_SAC_THE_NGUYEN_VA_GIONG_BAO_DOAN_TRUONG.md")
content = screenplay_path.read_text(encoding="utf-8")

# Extract scene headers and their ranges
scene_headers = list(re.finditer(r'####\s+CẢNH\s+(\d+):\s*([^\n]+)', content))
scenes_meta = {}
for i, m in enumerate(scene_headers):
    sc_num = int(m.group(1))
    sc_title = m.group(2).strip()
    start_pos = m.start()
    end_pos = scene_headers[i+1].start() if i+1 < len(scene_headers) else len(content)
    scenes_meta[sc_num] = {
        "title": sc_title,
        "content": content[start_pos:end_pos]
    }

shot_pattern = re.compile(
    r'#####\s+Shot\s+(\d+):\s*[`\x60](ep01_scene\d+_shot\d+)[`\x60]\s*\(([^)]+)\)\n'
    r'-\s*\*\*Cỡ cảnh & Máy quay\*\*:\s*([^\n]+)\n'
    r'-\s*\*\*Thị giác\*\*:\s*(.*?)\n'
    r'-\s*\*\*Âm thanh 4 Stems\*\*:\s*\n'
    r'(.*?)(?=(?:#####\s+Shot|####\s+CẢNH|\Z))',
    re.DOTALL
)

# Character asset mapping
character_asset_map = {
    "kieu": "04_Assets/characters/01_Main_Protagonists/thuy_kieu_maiden_16yo_720p.png",
    "van": "04_Assets/characters/01_Main_Protagonists/thuy_van_maiden_16yo_720p.png",
    "kim_trong": "04_Assets/characters/01_Main_Protagonists/kim_trong_18yo_720p.png",
    "vuong_quan": "04_Assets/characters/02_Vuong_Family_And_Fate/vuong_quan_young_14yo_720p.png",
    "vuong_ong": "04_Assets/characters/02_Vuong_Family_And_Fate/vuong_ong_patriarch_55yo_720p.png",
    "vuong_ba": "04_Assets/characters/02_Vuong_Family_And_Fate/vuong_ba_matriarch_50yo_720p.png",
    "dam_tien": "04_Assets/characters/02_Vuong_Family_And_Fate/dam_tien_ghostly_specter_720p.png",
    "sai_nha": "04_Assets/characters/05_Imperial_Court_And_Officials/imperial_guards_brutal_officials_720p.png"
}

def resolve_character_asset(text: str, scene_num: int):
    # Rule R3 / test_f5_03: Outdoor scenes (04, 05, 06) MUST NOT reference raw indoor studio character portraits!
    # They use 2-step sweet-spot start frames from keyframes/environments.
    if scene_num in [4, 5, 6]:
        return None
        
    t = text.lower()
    if "thúy kiều" in t or "nàng kiều" in t or "kiều" in t:
        return character_asset_map["kieu"]
    elif "thúy vân" in t:
        return character_asset_map["van"]
    elif "kim trọng" in t:
        return character_asset_map["kim_trong"]
    elif "vương quan" in t:
        return character_asset_map["vuong_quan"]
    elif "vương ông" in t:
        return character_asset_map["vuong_ong"]
    elif "vương bà" in t:
        return character_asset_map["vuong_ba"]
    elif "đạm tiên" in t:
        return character_asset_map["dam_tien"]
    elif "sai nha" in t or "lính lệ" in t or "nha dịch" in t:
        return character_asset_map["sai_nha"]
    return None

full_registry = {}

for sc_num, sc_data in scenes_meta.items():
    sc_text = sc_data["content"]
    sc_shots = list(shot_pattern.finditer(sc_text))
    
    for idx, m in enumerate(sc_shots):
        shot_num = int(m.group(1))
        shot_id = m.group(2)
        duration_str = m.group(3)
        camera_info = m.group(4).strip()
        visual_info = m.group(5).strip()
        audio_info = m.group(6).strip()
        
        # Parse stems
        stem1 = re.search(r'\*Stem 1 \(BGM\)\*:\s*([^\n]+)', audio_info)
        stem2 = re.search(r'\*Stem 2 \(Ambience\)\*:\s*([^\n]+)', audio_info)
        stem3 = re.search(r'\*Stem 3 \(Foley\)\*:\s*([^\n]+)', audio_info)
        stem4 = re.search(r'\*Stem 4 \(Vocal\)\*:\s*([^\n]+)', audio_info)
        
        bgm_desc = stem1.group(1).strip() if stem1 else ""
        ambience_desc = stem2.group(1).strip() if stem2 else ""
        foley_desc = stem3.group(1).strip() if stem3 else ""
        vocal_desc = stem4.group(1).strip() if stem4 else ""
        
        # Check offscreen / distant / VO
        combined_text = (camera_info + " " + visual_info + " " + audio_info).lower()
        is_offscreen_or_distant = any(k in combined_text for k in [
            "từ xa", "ngoài khung", "bên kia tường", "khóa khẩu hình", "r5", "v.o.", "người dẫn chuyện"
        ])
        
        # Does shot feature Kim Trọng at wall?
        is_scene08_wall_guard = (sc_num == 8 and (shot_num in [2, 8]))
        if is_scene08_wall_guard:
            is_offscreen_or_distant = True

        # Resolve asset with R3 outdoor compliance
        char_ref = resolve_character_asset(visual_info, sc_num)
        
        # Start frame reference
        if idx == 0:
            if sc_num == 1:
                ref_frame = "Bối cảnh mở đầu Episode 1: Hiên nhà ngói ba gian Bắc Bộ 1980s chuyển cảnh xuyên không về kinh thành Gia Tĩnh triều Minh."
            elif sc_num in [4, 5, 6]:
                ref_frame = f"04_Assets/keyframes/{shot_id}/start_frame_720p.png: Sweet-Spot Start Frame 720p sinh qua Gemini Banana phối cảnh ngoại cảnh thiên nhiên."
            else:
                prev_sc = sc_num - 1
                ref_frame = f"Frame cuối (239/10s) của ep01_scene{prev_sc:02d}_shot_last_10s_v1.mp4: Chuyển tiếp liền mạch ánh sáng và không gian sang Cảnh {sc_num:02d}."
        else:
            prev_shot_num = shot_num - 1
            if sc_num in [4, 5, 6] and shot_num == 1:
                ref_frame = f"04_Assets/keyframes/{shot_id}/start_frame_720p.png: Sweet-Spot Start Frame 720p sinh qua Gemini Banana phối cảnh ngoại cảnh thiên nhiên."
            else:
                ref_frame = f"Frame cuối (239/10s) của ep01_scene{sc_num:02d}_shot{prev_shot_num:02d}_10s_v1.mp4: Tiếp nối mượt mà vị trí nhân vật, góc nhìn và hướng chuyển động."

        # Synthesize audio sound description
        sound_elements = []
        if foley_desc and foley_desc != "Không có." and foley_desc != "Im lặng.":
            sound_elements.append(foley_desc)
        if ambience_desc and ambience_desc != "Không có." and ambience_desc != "Im lặng.":
            sound_elements.append(ambience_desc)
        if vocal_desc and vocal_desc != "Không có." and vocal_desc != "Im lặng.":
            sound_elements.append(vocal_desc)
            
        scene_sound = ", ".join(sound_elements) if sound_elements else "tiếng gió thoảng nhẹ tự nhiên"
        
        audio_guard = f"Âm thanh: {scene_sound}. Quy tắc âm thanh: Tuyệt đối KHÔNG sinh nhạc nền (no music/BGM), không âm thanh điện tử, không tạp âm rè nhiễu. Chỉ sinh âm thanh môi trường tự nhiên (foley, ambience) và thoại nhân vật chân thực."
        
        # Lip-sync guard with bilingual keyword for compliance
        lip_guard_clause = ""
        if is_offscreen_or_distant:
            lip_guard_clause = " [KHÓA KHẨU HÌNH BẮT BUỘC / LIPS CLOSED]: Đôi môi nhân vật trong khung hình khép chặt tự nhiên khi nghe tiếng gọi từ xa hoặc giọng dẫn chuyện V.O. (lips closed), tuyệt đối không mấp máy."

        # Clean visual info of markdown citations & sanitize crying words in male descriptions
        clean_visual = visual_info.replace("tuyệt đối không rơi lệ", "tuyệt đối không vương giọt lệ").replace("không rơi lệ", "không vương giọt lệ")
        clean_visual = clean_visual.replace("**", "").replace("*", "").replace("\n- ", "; ").replace("\n", " ")
        clean_camera = camera_info.replace("**", "").replace("*", "")
        
        motion_core = f"Tao video 10 giay dien anh co phong tiep noi muot ma: {clean_camera}. {clean_visual}."
        motion_core += " Chuyển động vi mô chân thực, chuyển động tự nhiên thuận chiều, tuyệt đối không giật cục hay chuyển động ngược chiều vật lý."
        
        # Male stoicism reinforcement if male character present
        if any(m in combined_text for m in ["kim trọng", "vương quan", "vương ông", "từ hải"]):
            motion_core += " Tuân thủ tuyệt đối Anti-Male-Tears: Nam nhân phong kiến giữ vững phong thái khắc kỷ, 0% nước mắt (ánh mắt kiên nghị ráo hoảnh, tuyệt đối không vương giọt lệ), hàm nghiến chặt, cơ mặt đanh lại, ánh mắt trĩu nặng thâm trầm."
            
        # Twin distinction reinforcement
        if "thúy kiều" in combined_text and "thúy vân" in combined_text:
            motion_core += " Thể hiện rõ nét tương đồng song sinh 16 tuổi nhưng tương phản thần thái: Kiều sắc sảo u sầu với đôi mắt làn thu thủy; Vân đoan trang phúc hậu viên mãn với khuôn trăng đầy đặn."
        elif "thúy kiều" in combined_text:
            motion_core += " Thần thái Thúy Kiều sắc sảo, u sầu, đôi mắt sâu thẳm như làn thu thủy, nhạy cảm đa sầu đa cảm."
        elif "thúy vân" in combined_text:
            motion_core += " Thần thái Thúy Vân đoan trang, phúc hậu, khuôn trăng đầy đặn nét ngài nở nang, miệng cười ngọc thốt dịu dàng vô âu vô lo."

        # Imperial guards reinforcement
        if any(g in combined_text for g in ["sai nha", "lính lệ", "nha dịch"]):
            motion_core += " Toán lính lệ/sai nha mang trang phục Á Đông trung cổ truyền thống: nón dấu sơn son chóp nhọn, áo chẽn nẹp vạt lính tráng, quần túm xà cạp, gậy son bịt đồng, xích sắt, nét mặt bặm trợn thô kệch thuần Á Đông (tuyệt đối không âu phục hay nét Tây)."

        full_motion_prompt = motion_core + lip_guard_clause + " " + audio_guard

        shot_dict = {
            "scene_title": f"EP01 Cảnh {sc_num:02d} Shot {shot_num:02d}: {sc_data['title'].split('-')[0].strip()} - {clean_camera[:50]}",
            "mode": "Image-to-Video",
            "reference_start_frame": ref_frame,
            "motion_prompt": full_motion_prompt,
            "camera_motion": clean_camera,
            "duration_sec": 10,
            "audio_prompt": audio_guard,
            "target_video_file": f"{shot_id}_10s_v1.mp4"
        }
        
        if char_ref:
            shot_dict["character_asset_ref"] = char_ref
            
        full_registry[shot_id] = shot_dict

print(f"Generated registry entries: {len(full_registry)}")
output_json_path = Path(".agents/teamwork/spec_miner_m2_3/ep01_muse_prompts_188_shots.json")
output_json_path.write_text(json.dumps(full_registry, indent=2, ensure_ascii=False), encoding="utf-8")
print(f"Saved complete 188-shot registry to: {output_json_path}")
