/**
 * 光湖视频AI · video-composer · 视频拼接+字幕引擎
 * D131 · 铸渊 ICE-GL-ZY001
 *
 * 功能:
 * 1. 将8个分镜视频按顺序拼接
 * 2. 从剧本提取台词生成SRT字幕
 * 3. 调用FFmpeg合成最终视频
 *
 * 用法:
 *   node video-composer.js --project qinshan --ep 1
 *
 * 环境要求:
 *   - FFmpeg (服务器上)
 *   - 8个分镜视频文件在 outputs/shots/ 下
 *   - 字幕数据从 project_subs 配置读取
 */

const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

// ==================== 项目字幕配置 ====================
// 每镜: { duration, text }。镜面无台词则 text 为空不烧字幕。

const project_subs = {
  qinshan: {
    title: '秦山号',
    ep: {
      1: [
        { shot: 1, duration: 5, text: '' },
        { shot: 2, duration: 5, text: '' },
        { shot: 3, duration: 5, text: '[警报声] 滴滴滴滴...' },
        { shot: 4, duration: 5, text: '' },
        { shot: 5, duration: 5, text: '' },
        { shot: 6, duration: 5, text: '林昊：不能坐以待毙！' },
        { shot: 7, duration: 5, text: '林昊：果然...' },
        { shot: 8, duration: 10, text: '[无声翕动] 救我...杀了我...' },
      ],
    },
  },
};

// ==================== SRT 生成 ====================

function generateSRT(subs) {
  const lines = [];
  let time = 0; // 累计秒数
  let idx = 1;

  for (const sub of subs) {
    if (!sub.text) {
      time += sub.duration;
      continue;
    }
    const start = formatTime(time);
    const end = formatTime(time + sub.duration);

    lines.push(String(idx));
    lines.push(`${start} --> ${end}`);
    lines.push(sub.text);
    lines.push('');

    time += sub.duration;
    idx++;
  }

  return lines.join('\n');
}

function formatTime(totalSec) {
  const h = Math.floor(totalSec / 3600);
  const m = Math.floor((totalSec % 3600) / 60);
  const s = Math.floor(totalSec % 60);
  const ms = Math.round((totalSec - Math.floor(totalSec)) * 1000);
  return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')},${String(ms).padStart(3, '0')}`;
}

// ==================== FFmpeg 拼接 ====================

function buildConcatFile(shotsDir, prefix, count) {
  const files = [];
  for (let i = 1; i <= count; i++) {
    const p = path.resolve(shotsDir, `${prefix}${i}.mp4`);
    if (fs.existsSync(p)) {
      files.push(`file '${p}'`);
    } else {
      console.error(`⚠️ 缺失: ${p}`);
    }
  }
  return files.join('\n');
}

function concatAndBurn(shotsDir, prefix, count, srtPath, outputPath) {
  const concatPath = path.join(path.dirname(outputPath), 'concat.txt');
  const concatContent = buildConcatFile(shotsDir, prefix, count);
  fs.writeFileSync(concatPath, concatContent);

  console.log(`拼接文件: ${concatPath}`);
  console.log(`字幕文件: ${srtPath}`);

  if (fs.existsSync(srtPath) && fs.statSync(srtPath).size > 0) {
    // 有字幕：拼接+烧字幕
    const cmd = `ffmpeg -y -f concat -safe 0 -i "${concatPath}" -vf "subtitles=${srtPath}:force_style='FontName=Noto Sans SC,FontSize=20,PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,Outline=1,Shadow=1'" -c:v libx264 -preset medium -crf 23 -c:a aac "${outputPath}"`;
    console.log(`执行: ${cmd.substring(0, 100)}...`);
    execSync(cmd, { stdio: 'inherit' });
  } else {
    // 无字幕：纯拼接
    const cmd = `ffmpeg -y -f concat -safe 0 -i "${concatPath}" -c copy "${outputPath}"`;
    console.log(`执行: ${cmd}`);
    execSync(cmd, { stdio: 'inherit' });
  }

  console.log(`✅ 成品: ${outputPath}`);
}

// ==================== 主入口 ====================

function main() {
  const args = process.argv.slice(2);
  const project = args.includes('--project') ? args[args.indexOf('--project') + 1] : 'qinshan';
  const epNum = args.includes('--ep') ? parseInt(args[args.indexOf('--ep') + 1], 10) : 1;

  const epSubs = project_subs[project]?.ep?.[epNum];
  if (!epSubs) {
    console.error(`❌ 未找到项目 ${project} 第${epNum}集的字幕配置`);
    process.exit(1);
  }

  // 查找视频文件
  const shotsDir = path.resolve(__dirname, '../outputs/shots');
  const prefix = `${project}-ep${String(epNum).padStart(2, '0')}-shot`;

  // 生成SRT
  const outputDir = path.resolve(__dirname, '../outputs/final');
  if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });

  const srtPath = path.join(outputDir, `${project}-ep${String(epNum).padStart(2, '0')}.srt`);
  const srtContent = generateSRT(epSubs);
  if (srtContent) {
    fs.writeFileSync(srtPath, srtContent);
    console.log(`📝 字幕: ${srtPath}`);
  }

  // 拼接+烧字幕
  const outputPath = path.join(outputDir, `${project}-ep${String(epNum).padStart(2, '0')}.mp4`);
  concatAndBurn(shotsDir, prefix, epSubs.length, srtContent ? srtPath : null, outputPath);

  console.log(`\n🎬 ${project_subs[project].title} 第${epNum}集完成！`);
  console.log(`   成品: ${outputPath}`);
}

main();
