/**
 * Pipeline 共享工具函数与路径常量
 *
 * 所有 phase/command 模块共用：配置加载、文件操作、路径计算、日志
 */

const fs = require('fs')
const path = require('path')

// 路径常量（基于 lib/ 的父目录 scripts/）
const SCRIPTS_DIR = path.join(__dirname, '..')
const SKILLS_DIR = path.join(SCRIPTS_DIR, '..')
const PROJECT_ROOT = path.join(SKILLS_DIR, '..', '..')
const CONFIG_PATH = path.join(SKILLS_DIR, 'config.json')
const ACCOUNTS_DIR = path.join(PROJECT_ROOT, '..', 'accounts')

// ============================================================================
// 配置 & Manifest
// ============================================================================

function loadConfig() {
  return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'))
}

function loadManifest(manifestPath) {
  return JSON.parse(fs.readFileSync(manifestPath, 'utf-8'))
}

function saveManifest(manifestPath, manifest) {
  const tmp = manifestPath + '.tmp'
  fs.writeFileSync(tmp, JSON.stringify(manifest, null, 2), 'utf-8')
  fs.renameSync(tmp, manifestPath)
}

function loadAccountConfig(accountId) {
  const accountPath = path.join(ACCOUNTS_DIR, accountId, 'account.json')
  if (!fs.existsSync(accountPath)) throw new Error(`账号不存在: ${accountPath}`)
  return JSON.parse(fs.readFileSync(accountPath, 'utf-8'))
}

// ============================================================================
// 参考图解析
// ============================================================================

async function getReferences(manifest, accountConfig) {
  const result = { localPaths: [], urls: [] }
  const accountId = accountConfig.id || manifest.account || ''

  // 自动上传本地文件到 OSS 的辅助函数
  const ensureUrl = async (localPath, label) => {
    try {
      const { uploadFile } = require('../oss-upload')
      const { url } = await uploadFile(localPath)
      result.urls.push(url)
      log('images', `参考图已自动上传 OSS: ${label}`)
      return url
    } catch (err) {
      log('images', `参考图上传 OSS 失败: ${label} (${err.message})，仅本地使用`)
      return null
    }
  }

  // 优先读 manifest.references（agent 创建时写入）
  const refs = manifest.references || []
  if (refs.length > 0) {
    for (const ref of refs) {
      if (ref.url) result.urls.push(ref.url)
      if (ref.file) {
        const localPath = path.isAbsolute(ref.file) ? ref.file : path.resolve(ref.file)
        if (fs.existsSync(localPath)) {
          result.localPaths.push(localPath)
          // 有本地文件但没有 OSS URL → 自动上传，杜绝 agent 只用本地路径
          if (!ref.url) {
            ref.url = await ensureUrl(localPath, path.basename(localPath))
          }
        } else {
          log('images', `参考图不存在: ${ref.file}`)
        }
      }
    }
    if (result.localPaths.length > 0 || result.urls.length > 0) return result
    log('images', 'manifest.references 全部无效，尝试 account fallback')
  }

  // Fallback 1: 从 account.json 的顶层 references 读取
  const topRefs = accountConfig.references || []
  for (const ref of topRefs) {
    if (ref.url) result.urls.push(ref.url)
    if (ref.file && accountId) {
      const localPath = path.join(ACCOUNTS_DIR, accountId, 'references', ref.file)
      if (fs.existsSync(localPath)) {
        result.localPaths.push(localPath)
        if (!ref.url) {
          ref.url = await ensureUrl(localPath, ref.file)
        }
      }
    }
  }
  if (result.localPaths.length > 0 || result.urls.length > 0) return result

  // Fallback 2: 扫描 account 的 references 目录（自动上传 OSS）
  if (accountId) {
    const refDir = path.join(ACCOUNTS_DIR, accountId, 'references')
    if (fs.existsSync(refDir)) {
      const files = fs.readdirSync(refDir).filter(f =>
        /\.(png|jpg|jpeg|webp)$/i.test(f)
      )
      for (const f of files) {
        const localPath = path.join(refDir, f)
        result.localPaths.push(localPath)
        await ensureUrl(localPath, f)
      }
      if (files.length > 0) {
        log('images', `从 references 目录兜底扫描到 ${files.length} 个参考图（已自动上传 OSS）`)
      }
    }
  }

  if (result.localPaths.length === 0 && result.urls.length === 0) {
    log('images', '无参考图，将使用纯文生图模式')
  }

  return result
}

// ============================================================================
// 文件操作
// ============================================================================

function ensureDir(dir) {
  fs.mkdirSync(dir, { recursive: true })
}

function slugify(text) {
  // 限制中文字符最多5个,其他字符(英文数字)最多10个
  let chineseChars = []
  let otherChars = []

  for (const char of text) {
    if (/\p{Script=Han}/u.test(char)) {
      // 中文字符
      if (chineseChars.length < 5) {
        chineseChars.push(char)
      }
    } else if (/\w/u.test(char)) {
      // 英文、数字
      if (otherChars.length < 10) {
        otherChars.push(char)
      }
    }
  }

  const result = chineseChars.concat(otherChars).join('')
  return result || 'untitled'
}

function renameGeneratedFile(oldRelPath, dir, seq, nameHint, suffix) {
  if (!oldRelPath) return oldRelPath
  const oldAbs = path.resolve(dir, oldRelPath)
  if (!fs.existsSync(oldAbs)) return oldRelPath
  const ext = path.extname(oldAbs)
  const slug = nameHint ? slugify(nameHint) : ''
  const tag = suffix ? `_${suffix}` : ''
  const newName = slug
    ? `scene_${String(seq).padStart(2, '0')}_${slug}${tag}${ext}`
    : `scene_${String(seq).padStart(2, '0')}${tag}${ext}`
  const newAbs = path.join(path.dirname(oldAbs), newName)
  if (oldAbs !== newAbs) {
    try { fs.renameSync(oldAbs, newAbs) } catch (_) { return oldRelPath }
  }
  return path.relative(dir, newAbs).replace(/\\/g, '/')
}

// ============================================================================
// 日志 & 路径
// ============================================================================

function log(phase, msg) {
  console.log(`[${phase}] ${msg}`)
}

function getManifestDir(manifestPath) {
  return path.dirname(path.resolve(manifestPath))
}

// ============================================================================
// 文本切分
// ============================================================================

function splitTextIntoSentences(text) {
  // 在句号、感叹号、分号、逗号处断句——它们是口播语音的天然呼吸点。
  const sentenceEnders = /[。！；，]/

  const sentences = []
  let current = ''

  for (const char of text) {
    current += char

    if (sentenceEnders.test(char)) {
      sentences.push(current.trim().replace(/[。！；，：？、——…]/g, ''))
      current = ''
    }
  }

  if (current.trim()) {
    sentences.push(current.trim().replace(/[。！；，：？、——…]/g, ''))
  }

  return sentences
}

// ============================================================================
// Exports
// ============================================================================

module.exports = {
  SCRIPTS_DIR,
  SKILLS_DIR,
  PROJECT_ROOT,
  CONFIG_PATH,
  ACCOUNTS_DIR,
  loadConfig,
  loadManifest,
  saveManifest,
  loadAccountConfig,
  getReferences,
  ensureDir,
  slugify,
  renameGeneratedFile,
  splitTextIntoSentences,
  log,
  getManifestDir,
}
