#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""把定稿（v7-live.md → draft-latest.md）同步进提词器：
   .build/prompter.html / shootlist.html / 提词器-纯净口播版.md / 提词器-合并版.html
用法: python3 sync_prompter.py
"""
import re, os, html, subprocess
import gen_prompter as G

BASE = os.path.dirname(os.path.abspath(__file__))
fmt, esc = G.fmt, G.esc

# 旧清单卡片（14 张）→ 新节序（15 节）的对应关系
# 旧 1-10 对 新 1-10；旧 11 定时任务→新 12；旧 12 多智能体→新 11；
# 旧 13 微信→新 14；旧 14 结尾→新 15；新 13 综合作业是全新的，单独写
OLD2NEW = {i: i + 1 for i in range(10)}  # 旧卡下标(0基) → 新节号(1基)
OLD2NEW[10] = 12   # 旧第 11 张（定时任务）→ 新第 12 节
OLD2NEW[11] = 11   # 旧第 12 张（多智能体）→ 新第 11 节
OLD2NEW[12] = 14   # 旧第 13 张（微信）→ 新第 14 节（另写新卡）
OLD2NEW[13] = 15   # 旧第 14 张（结尾）→ 新第 15 节

NEW_CARD13 = '''<section class="card" id="c12">
  <div class="chead"><span class="num">13</span><h2>{title}</h2>
  <span class="tag">{t} · {n} 字</span></div>
  <div class="cols">
    <div class="col">
      <h4>▶ 录什么</h4><div class="txt">① 点左上【新建任务】→ 左下角选绑好 D:/Agent练习/ 的【工作空间】<br>② 右下角模型确认 0.00x（Deepseek-V4.1-Flash），权限【允许完全访问】<br>③ 确认【浏览器自动化】连接器开着<br>④ 输入框敲 / 选中 VibeCoding评论洞察 技能，丢一条新视频链接，回车<br>⑤ 十几秒后 D:/Agent练习/ 出 CSV + 三区报告 → 抽查无误 → 归档进【资料库】</div>
      <h4>◆ 画面怎么走</h4><div class="txt">整段一镜到底录屏，四步各压一个小标题字幕（选空间 / 连接器 / 技能 / 验货），不切镜头</div>
    </div>
    <div class="col">
      <h4>✂ 剪辑要点</h4><div class="txt">这是「观众自己能不能复现」的证明，真实跑完再剪，不许加速掩盖等待</div>
      <h4>◆ 动画</h4><div class="txt anim">本段纯录屏，不插动画（前面已铺满动画，这里要的是真实感）</div>
      <h4>⚠ 坑</h4><div class="txt trap">必须先新建空白任务、从空白对话框起步，不能拿现成窗口演示，否则「从 0 到 1」不成立</div>
    </div>
  </div>
</section>'''

NEW_CARD14 = '''<section class="card" id="c13">
  <div class="chead"><span class="num">14</span><h2>{title}</h2>
  <span class="tag">{t} · {n} 字</span></div>
  <div class="cols">
    <div class="col">
      <h4>▶ 录什么</h4><div class="txt">① 左下角小铃铛旁【连接移动端】→ 打开【保持唤醒状态，以便远程访问（允许锁屏运行）】，选「熄屏后保持唤醒」<br>② 【助理】顶部齿轮 → 选微信通道 → 手机扫码绑定<br>③ 手机 App 登录同一账号 → 设备连接授权 → 演示「虚拟鼠标点弹窗」「一键停止」<br>④ 压轴同框：左电脑右手机，微信丢链接，十几秒后手机收到报告</div>
      <h4>◆ 画面怎么走</h4><div class="txt">动画12 双轨对比（动嘴派活 / 伸手救场）→ 接真机同框</div>
    </div>
    <div class="col">
      <h4>✂ 剪辑要点</h4><div class="txt">同框那段一镜到底别剪断，这是全片最强一击；保持唤醒开关给特写，这是新手最容易漏的一步</div>
      <h4>◆ 动画</h4><div class="txt anim">动画12 助理双轨图</div>
      <h4>⚠ 坑</h4><div class="txt trap">别把「保持唤醒」讲成系统睡眠设置，口播讲的是软件里的开关；手机收到文件那一刻要有「叮咚」声</div>
    </div>
  </div>
</section>'''


def parse_secs():
    """用 gen_prompter 的解析，再去掉（画面…）整段分镜提示，重算字数与时长"""
    G.STRIP = []
    secs = G.parse()
    for s in secs:
        s['paras'] = [p for p in s['paras'] if not p.lstrip().startswith('（画面')]
        s['han'] = len(re.findall(r'[\u4e00-\u9fff]', ''.join(s['paras']).replace('\x00CUE', '')))
        s['sec'] = round(s['han'] / G.RATE)
    return secs


def gen_shootlist15(secs):
    p = os.path.join(BASE, 'shootlist.html')
    base = os.path.join(BASE, 'shootlist-base14.html')  # 固定模板：最初那 14 张手写卡
    old = open(base, encoding='utf-8').read()
    head = old[:old.index('<section class="card" id="c0">')]
    total_han = sum(s['han'] for s in secs)
    total_sec = round(total_han / G.RATE)
    head = re.sub(r'全文 \d+ 汉字', f'全文 {total_han} 汉字', head)
    head = re.sub(r'<div class="stat"><b>\d+</b><span>节</span></div>',
                  f'<div class="stat"><b>{len(secs)}</b><span>节</span></div>', head)
    head = re.sub(r'<div class="stat"><b>\d+</b><span>口播汉字</span></div>',
                  f'<div class="stat"><b>{total_han}</b><span>口播汉字</span></div>', head)
    head = re.sub(r'<div class="stat"><b>[\d:]+</b><span>纯念时长</span></div>',
                  f'<div class="stat"><b>{fmt(total_sec)}</b><span>纯念时长</span></div>', head)
    head = re.sub(r'<div class="stat"><b>约 \d+ 分</b><span>加停顿成片</span></div>',
                  f'<div class="stat"><b>约 {round(total_sec * 1.19 / 60)} 分</b><span>加停顿成片</span></div>', head)
    toc = '<div class="toc">' + ''.join(
        f'<a href="#c{k}">{k + 1}. {esc(s["title"])}</a>' for k, s in enumerate(secs)) + '</div>\n'
    head = re.sub(r'<div class="toc">.*?</div>\n', toc, head, flags=re.S)

    oldcards = re.findall(r'<section class="card" id="c\d+">.*?</section>', old, re.S)
    assert len(oldcards) == 14, len(oldcards)

    cards = []
    for k, s in enumerate(secs):          # k: 0-based 新节序
        num = k + 1
        if num == 13:
            c = NEW_CARD13.format(title=esc(s['title']), t=fmt(s['sec']), n=s['han'])
        elif num == 14:
            c = NEW_CARD14.format(title=esc(s['title']), t=fmt(s['sec']), n=s['han'])
        elif num == 1:
            c = G.CARD1.format(t=fmt(s['sec']), n=s['han'])
            c = re.sub(r'<h2>.*?</h2>', f'<h2>{esc(s["title"])}</h2>', c, count=1)
        else:
            src = [o for o, tgt in OLD2NEW.items() if tgt == num]
            c = oldcards[src[0]]
            c = re.sub(r'<h2>.*?</h2>', f'<h2>{esc(s["title"])}</h2>', c, count=1)
        # 统一重排：卡片 id、序号、tag
        c = re.sub(r'id="c\d+"', f'id="c{k}"', c, count=1)
        c = re.sub(r'<span class="num">\d+</span>', f'<span class="num">{num}</span>', c, count=1)
        c = re.sub(r'<span class="tag">[^<]*</span>',
                   f'<span class="tag">{fmt(s["sec"])} · {s["han"]} 字</span>', c, count=1)
        cards.append(c)

    tail = '</div></body></html>'
    open(p, 'w', encoding='utf-8').write(head + '\n'.join(cards) + '\n' + tail)
    print('shootlist.html 写好：', len(cards), '张卡')


if __name__ == '__main__':
    secs = parse_secs()
    total_han = sum(s['han'] for s in secs)
    total_sec = round(total_han / G.RATE)  # 与对比页同口径：按总字数算，不逐节累加
    G.gen_prompter(secs, total_han, total_sec)
    print('prompter.html 写好：', len(secs), '节', total_han, '字', fmt(total_sec))
    gen_shootlist15(secs)
    G.gen_clean_md(secs, total_han, total_sec)
    print('提词器-纯净口播版.md 写好')
    subprocess.run(['python3', os.path.join(BASE, 'gen_merged.py')], check=True)
