#!/usr/bin/env python3
# 光湖视频AI系统 · .hdlp剧本解析器
# 耳耳蛋 ICE-GL-EED · D181 · 解决管线①/②不兼容问题
"""
.hdlp格式 → 标准化剧本解析
输入: EP01-SCRIPT-LOCK.hdlp
输出: 
  parse → 结构化JSON (集→场→角色→台词→场景描述)
  characters → 角色列表
"""

import re
import json
import sys

def convert_hdlp_to_standard(text):
    """将.hdlp剧本转换为script-parser.js能识别的标准格式"""
    lines = text.split('\n')
    result = []
    in_meta = False
    
    for line in lines:
        stripped = line.strip()
        
        # 跳过元数据和锁标记
        if not stripped:
            result.append('')
            continue
        if stripped.startswith('> ⊢') or stripped.startswith('HLDP:'):
            continue
        if stripped.startswith('---'):
            continue
        if stripped.startswith('# '):
            result.append(stripped.replace('# ', ''))
            continue
        
        # ## 1-1 日/内 地点 → 添加「第1集」标记 + 标准化场景
        scene_match = re.match(r'^##\s+(\d+)-(\d+)\s+(日|夜|晨|暮)\s*/\s*(内|外)\s+(.+)$', stripped)
        if scene_match:
            ep_num = scene_match.group(1)
            scene_id = f"{scene_match.group(1)}-{scene_match.group(2)}"
            time = scene_match.group(3)
            loc = scene_match.group(4)
            name = scene_match.group(5)
            # 添加集标记（如果还没加过）
            if f'第{ep_num}集' not in '\n'.join(result[-5:]):
                result.append(f"第{ep_num}集")
            result.append(f"{scene_id} {time} {loc} {name}")
            continue
        
        # **人物**：林昊（描述）→ 人物：林昊（描述）
        char_match = re.match(r'^\*\*人物\*\*[：:]\s*(.+)$', stripped)
        if char_match:
            result.append(f"人物：{char_match.group(1)}")
            continue
        
        # **角色名（情绪）**：台词 → 角色名（情绪）：台词
        dialogue_bold = re.match(r'^\*\*(.+?)\*\*[：:]\s*(.+)$', stripped)
        if dialogue_bold:
            # 提取角色名和情绪
            inner = re.match(r'(.+?)[（(](.+?)[）)]', dialogue_bold.group(1))
            if inner:
                result.append(f"{inner.group(1)}（{inner.group(2)}）：{dialogue_bold.group(2)}")
            else:
                result.append(f"{dialogue_bold.group(1)}：{dialogue_bold.group(2)}")
            continue
        
        # VO标记
        vo_match = re.match(r'^\*\*(.+?)（VO）\*\*[：:]?\s*(.*)$', stripped)
        if vo_match:
            result.append(f"{vo_match.group(1)}（VO）：{vo_match.group(2)}")
            continue
        
        # 音效标记
        sfx_match = re.match(r'^\*\*音效\*\*[：:]?\s*(.+)$', stripped)
        if sfx_match:
            result.append(f"△ 特效：音效 - {sfx_match.group(1)}")
            continue
        
        # 【特写：xxx】→ 保留
        if stripped.startswith('【特写') or stripped.startswith('【特寫'):
            result.append(f"△ 特写：{stripped}")
            continue
        
        # △ → 保留
        if stripped.startswith('△'):
            result.append(stripped)
            continue
        
        # 其他行原样保留
        result.append(stripped)
    
    # 去掉结尾的元数据行
    while result and (result[-1].startswith('⊢') or result[-1].startswith('>') or result[-1] == '---'):
        result.pop()
    
    return '\n'.join(result)


def parse_hdlp(text):
    """解析.hdlp剧本为结构化数据"""
    standard = convert_hdlp_to_standard(text)
    lines = standard.split('\n')
    
    episodes = []
    current_ep = None
    current_scene = None
    
    for line in lines:
        line = line.strip()
        if not line: continue
        
        # 第N集
        ep_match = re.match(r'^第(\d+)集$', line)
        if ep_match:
            if current_scene and current_ep:
                current_ep['scenes'].append(current_scene)
                current_scene = None
            if current_ep:
                episodes.append(current_ep)
            current_ep = {'episode': int(ep_match.group(1)), 'scenes': []}
            continue
        
        # 场景头
        sm = re.match(r'^(\d+-\d+)\s+(日|夜|晨|暮)\s+(内|外)\s+(.+)$', line)
        if sm:
            if current_scene and current_ep:
                current_ep['scenes'].append(current_scene)
            current_scene = {'id': sm.group(1), 'time': sm.group(2), 'loc': sm.group(3),
                           'name': sm.group(4), 'characters': [], 'dialogues': [], 'descriptions': [], 'effects': []}
            continue
        
        if not current_scene or not current_ep:
            continue
        
        # 人物行: 用「)」而不是逗号做分割符
        cm = re.match(r'^人物[：:]\s*(.+)$', line)
        if cm:
            chars_raw = cm.group(1)
            # 先按「)」分割，再清理
            parts = []
            current = ''
            depth = 0
            for ch in chars_raw:
                if ch == '（' or ch == '(': depth += 1
                elif ch == '）' or ch == ')': depth -= 1
                if ch in ('，', ',', '、') and depth == 0:
                    if current.strip(): parts.append(current.strip())
                    current = ''
                else:
                    current += ch
            if current.strip(): parts.append(current.strip())
            
            for part in parts:
                inner = re.match(r'(.+?)[（(](.+?)[）)]', part)
                if inner:
                    current_scene['characters'].append({'name': inner.group(1).strip(), 'desc': inner.group(2).strip()})
                else:
                    current_scene['characters'].append({'name': part, 'desc': ''})
            continue
        
        # 对话(带情绪): 角色（情绪）：台词
        dm = re.match(r'^(.+?)[（(](.+?)[）)]\s*[：:]\s*(.+)$', line)
        if dm:
            current_scene['dialogues'].append({'character': dm.group(1).strip(), 'emotion': dm.group(2).strip(), 'line': dm.group(3).strip()})
            continue
        
        # 对话(无情绪): 角色：台词
        dm2 = re.match(r'^(.+?)[：:]\s*(.+)$', line)
        if dm2 and not dm2.group(1).startswith('△') and not dm2.group(1).startswith('#'):
            current_scene['dialogues'].append({'character': dm2.group(1).strip(), 'emotion': '', 'line': dm2.group(2).strip()})
            continue
        
        # △描述/特效/特写
        if line.startswith('△') or line.startswith('【'):
            desc = line.lstrip('△').lstrip('【').strip().rstrip('】')
            current_scene['descriptions'].append(desc)
            # 特写也记录为特效
            if '特写' in line or '特寫' in line:
                current_scene['effects'].append({'type': 'closeup', 'description': desc})
            continue
    
    # flush
    if current_scene and current_ep:
        current_ep['scenes'].append(current_scene)
    if current_ep:
        episodes.append(current_ep)
    
    # 统计
    all_chars = set()
    for ep in episodes:
        for sc in ep['scenes']:
            for c in sc['characters']:
                all_chars.add(c['name'])
            for d in sc['dialogues']:
                all_chars.add(d['character'])
    
    return {
        'episodes': episodes,
        'characters': sorted(all_chars),
        'stats': {
            'episodes': len(episodes),
            'scenes': sum(len(ep['scenes']) for ep in episodes),
            'dialogues': sum(len(sc['dialogues']) for ep in episodes for sc in ep['scenes']),
            'characters': len(all_chars),
        }
    }


if __name__ == '__main__':
    if len(sys.argv) < 2:
        print('Usage: python hdlp-parser.py <script.hdlp>')
        sys.exit(1)
    
    with open(sys.argv[1], 'r', encoding='utf-8') as f:
        text = f.read()
    
    result = parse_hdlp(text)
    print(json.dumps(result, ensure_ascii=False, indent=2))
