/**
 * Command: init — 从 account.json + AI 创意内容生成规范 manifest.json
 *
 * 校验 items → 继承账号配置 → 创建输出目录 → 写出 manifest
 */

const fs = require('fs')
const path = require('path')
const { loadAccountConfig, saveManifest, ensureDir, slugify, ACCOUNTS_DIR, SKILLS_DIR } = require('./pipeline-utils')

function initManifest(options) {
  const { account: accountId, mode, items: itemsJson, itemsFile } = options

  if (!accountId) {
    console.error('错误: 必须指定 --account <账号ID>')
    process.exit(1)
  }

  const accountConfig = loadAccountConfig(accountId)

  // 解析 items
  let rawItems
  if (itemsFile) {
    const filePath = path.resolve(itemsFile)
    if (!fs.existsSync(filePath)) {
      console.error(`错误: items 文件不存在: ${filePath}`)
      process.exit(1)
    }
    rawItems = JSON.parse(fs.readFileSync(filePath, 'utf-8'))
    console.log(`  已读取并清理临时文件: ${path.basename(filePath)}`)
    fs.unlinkSync(filePath)
  } else if (itemsJson) {
    rawItems = JSON.parse(itemsJson)
  } else {
    console.error('错误: 必须指定 --items <JSON> 或 --items-file <path>')
    process.exit(1)
  }

  if (!Array.isArray(rawItems) || rawItems.length === 0) {
    console.error('错误: items 必须是非空数组')
    process.exit(1)
  }

  // 校验必填字段
  const requiredFields = ['shotDesc', 'script']
  const optionalFields = ['imagePrompt', 'videoPrompt', 'lastFramePrompt']
  const resolvedMode = mode || 'single'

  for (let i = 0; i < rawItems.length; i++) {
    const item = rawItems[i]
    for (const f of requiredFields) {
      if (!(f in item) || item[f] == null) {
        console.error(`错误: items[${i}] 缺少必填字段 "${f}"`)
        process.exit(1)
      }
    }
    if (resolvedMode === 'framePair' && !item.lastFramePrompt) {
      delete item.lastFramePrompt  // 首尾帧模式 Step 2-A 补充
    }
  }

  // 从 account.json 继承参考图（顶层 references），仅使用带签名 OSS URL 的条目
  const accountRefs = accountConfig.references || []
  const references = accountRefs.map(ref => {
    const entry = {}
    if (ref.file) entry.file = path.join(ACCOUNTS_DIR, accountId, 'references', ref.file)
    if (ref.url) entry.url = ref.url
    return entry
  })
  const refsWithoutUrl = references.filter(r => !r.url)
  if (refsWithoutUrl.length > 0) {
    console.log(`  ⚠ ${refsWithoutUrl.length} 个参考图缺少 OSS URL，images 阶段会自动上传`)
  }

  // 从 videoModel 推算固定时长（秒）
  const videoModelFixedDurations = {
    'kling': 6,
    'kling-v2-5-turbo': 6,
    'veo3-fast': 8,
    'veo3-fast-frames': 8,
    'grok-video-3': 6,
  }
  const estimatedVideoDuration = videoModelFixedDurations[options.videoModel || accountConfig.videoModel] || 6

  // 校验时长约束
  for (let i = 0; i < rawItems.length; i++) {
    const item = rawItems[i]
    const dur = Number(item.duration) || 5
    if (dur > estimatedVideoDuration) {
      console.error(`错误: items[${i}] 的 TTS 估算 duration=${dur}s > videoModel 固定时长 ${estimatedVideoDuration}s`)
      console.error(`       必须先拆分 shot 再执行 init！`)
      console.error(`       script: "${item.script}"`)
      process.exit(1)
    }
  }

  // 构建 items
  const items = rawItems.map((raw, i) => {
    const slug = slugify(raw.shotDesc || raw.script || `scene_${i + 1}`)
    const item = {
      id: i + 1,
      status: 'pending',
      file: `images/scene_${String(i + 1).padStart(2, '0')}_${slug}.jpeg`,
      shotDesc: raw.shotDesc || '',
      script: raw.script || '',
      duration: Number(raw.duration) || 5,
      estimatedVideoDuration,
      imagePrompt: raw.imagePrompt,
      confirmed: false,
    }
    if (raw.directorRef) item.directorRef = raw.directorRef
    if (raw.videoPrompt) item.videoPrompt = raw.videoPrompt
    if (raw.keyword) item.keyword = raw.keyword
    if (resolvedMode === 'framePair') item.lastFramePrompt = raw.lastFramePrompt
    return item
  })

  // 组装 manifest
  const manifest = {
    account: accountId,
    imageModel: options.imageModel || accountConfig.imageModel || 'gemini',
    videoModel: options.videoModel || accountConfig.videoModel || 'veo3-fast-frames',
    format: options.format || accountConfig.defaultFormat || '9:16',
    mode: resolvedMode,
    references,
    ...(accountConfig.ttsVoice ? { ttsVoice: accountConfig.ttsVoice } : {}),
    ...(accountConfig.ttsInstruction ? { ttsInstruction: accountConfig.ttsInstruction } : {}),
    // 铁律：ttsRate 写死 1.15x，不允许配置覆盖（除非显式传入）
    ttsRate: options.ttsRate || 1.15,
    items,
    estimatedVideoDuration,  // 顶层冗余，便于 assemble 直接读取
  }

  // 创建输出目录（自增序号）
  const date = new Date()
  const dateStr = [
    date.getFullYear(),
    String(date.getMonth() + 1).padStart(2, '0'),
    String(date.getDate()).padStart(2, '0'),
  ].join('')
  const prefix = `${accountConfig.name}_${dateStr}`
  const outputBase = path.join(SKILLS_DIR, '..', '..', '..', 'output')
  ensureDir(outputBase)

  let seq = 1
  while (fs.existsSync(path.join(outputBase, `${prefix}_${String(seq).padStart(3, '0')}`))) {
    seq++
  }
  const dirName = `${prefix}_${String(seq).padStart(3, '0')}`
  const outputDir = path.join(outputBase, dirName)
  ensureDir(outputDir)
  ensureDir(path.join(outputDir, 'images'))
  ensureDir(path.join(outputDir, 'videos'))
  ensureDir(path.join(outputDir, 'audio'))

  const manifestPath = path.join(outputDir, 'manifest.json')
  saveManifest(manifestPath, manifest)

  console.log(`\nManifest 已创建: ${manifestPath}`)
  console.log(`  账号: ${accountId} (${accountConfig.name})`)
  console.log(`  模型: ${manifest.imageModel} + ${manifest.videoModel}`)
  console.log(`  画幅: ${manifest.format}, 模式: ${manifest.mode}`)
  console.log(`  Items: ${items.length}`)
  console.log(`  参考图: ${references.length}`)
  if (items.some(it => !it.imagePrompt)) {
    console.log(`  ⚠ ${items.filter(it => !it.imagePrompt).length} 个 item 缺少 imagePrompt，请运行 Step 2-A（图片提示词）补充`)
  }
  if (resolvedMode === 'framePair' && items.some(it => !it.lastFramePrompt)) {
    console.log(`  ⚠ ${items.filter(it => !it.lastFramePrompt).length} 个 item 缺少 lastFramePrompt，请运行 Step 2-A 补充`)
  }
  if (items.some(it => !it.videoPrompt && resolvedMode !== 'framePair')) {
    console.log(`  ⚠ ${items.filter(it => !it.videoPrompt).length} 个 item 缺少 videoPrompt，生视频阶段将跳过`)
  }
  console.log()

  return manifestPath
}

module.exports = { initManifest }
