#!/usr/bin/env node

/**
 * 图片本地化处理脚本
 * 在静态站点生成后运行，将API返回的图片下载到本地
 */

import fs from 'fs'
import path from 'path'
import { createHash } from 'crypto'
import { fileURLToPath } from 'url'

// 获取当前文件的目录
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const PROJECT_ROOT = path.resolve(__dirname, '..')

/**
 * 下载并本地化图片
 * @param imageUrl 原始图片URL
 * @param basePath 保存图片的基础路径
 * @returns 本地化后的图片路径
 */
async function localizeImage(imageUrl, basePath = 'public/images/remote') {
  // 检查URL是否有效
  if (!imageUrl || !imageUrl.startsWith('http')) {
    return imageUrl
  }

  try {
    // 创建保存目录
    const fullBasePath = path.resolve(PROJECT_ROOT, basePath)
    if (!fs.existsSync(fullBasePath)) {
      fs.mkdirSync(fullBasePath, { recursive: true })
    }

    // 生成唯一文件名（使用URL的MD5哈希）
    const urlHash = createHash('md5').update(imageUrl).digest('hex')
    const fileExt = path.extname(new URL(imageUrl).pathname) || '.jpg'
    const fileName = `${urlHash}${fileExt}`
    const filePath = path.join(fullBasePath, fileName)
    
    // 如果文件已存在，直接返回路径
    if (fs.existsSync(filePath)) {
      return `/images/remote/${fileName}`
    }
    
    // 下载图片
    const response = await fetch(imageUrl)
    if (!response.ok) {
      throw new Error(`下载图片失败: ${response.status} ${response.statusText}`)
    }
    
    const buffer = Buffer.from(await response.arrayBuffer())
    fs.writeFileSync(filePath, buffer)
    
    console.log(`✅ 下载图片成功: ${imageUrl} -> /images/remote/${fileName}`)
    
    // 返回本地URL（相对于public目录）
    return `/images/remote/${fileName}`
  } catch (error) {
    console.error(`❌ 本地化图片失败 ${imageUrl}:`, error)
    return imageUrl // 失败时返回原始URL
  }
}

/**
 * 递归处理对象中的所有图片URL
 * @param data 需要处理的数据对象或数组
 * @param imageFields 指定哪些字段包含图片URL
 * @returns 处理后的数据
 */
async function localizeImages(
  data, 
  imageFields = ['image', 'imageUrl', 'thumbnail', 'cover', 'avatar', 'photo', 'src']
) {
  if (!data) return data
  
  // 处理数组
  if (Array.isArray(data)) {
    return Promise.all(data.map(item => localizeImages(item, imageFields)))
  }
  
  // 处理对象
  if (typeof data === 'object') {
    const result = { ...data }
    
    // 处理所有键
    for (const [key, value] of Object.entries(result)) {
      // 如果是图片字段且值是字符串，本地化图片
      if (imageFields.includes(key) && typeof value === 'string') {
        result[key] = await localizeImage(value)
      } 
      // 递归处理嵌套对象或数组
      else if (typeof value === 'object' && value !== null) {
        result[key] = await localizeImages(value, imageFields)
      }
    }
    
    return result
  }
  
  return data
}

/**
 * 从JSON文件提取图片URL并下载到本地
 * @param jsonFilePath JSON文件路径
 * @param imageFields 包含图片URL的字段名称数组
 */
async function extractAndDownloadImages(
  jsonFilePath, 
  imageFields = ['image', 'imageUrl', 'thumbnail', 'cover', 'avatar', 'photo', 'src']
) {
  // 检查文件是否存在
  if (!fs.existsSync(jsonFilePath)) {
    console.error(`文件不存在: ${jsonFilePath}`)
    return
  }

  try {
    // 读取JSON文件
    const jsonData = JSON.parse(fs.readFileSync(jsonFilePath, 'utf-8'))
    
    // 递归查找所有图片URL
    const imageUrls = new Set()
    
    // 递归函数查找所有图片URL
    function findImageUrls(obj) {
      if (!obj) return
      
      if (Array.isArray(obj)) {
        obj.forEach(item => findImageUrls(item))
        return
      }
      
      if (typeof obj === 'object') {
        for (const [key, value] of Object.entries(obj)) {
          if (imageFields.includes(key) && typeof value === 'string' && value.startsWith('http')) {
            imageUrls.add(value)
          } else if (typeof value === 'object' && value !== null) {
            findImageUrls(value)
          }
        }
      }
    }
    
    findImageUrls(jsonData)
    
    // 下载所有图片
    console.log(`📋 在 ${jsonFilePath} 中找到 ${imageUrls.size} 个图片URL`)
    
    let downloadedCount = 0
    for (const url of imageUrls) {
      try {
        const localUrl = await localizeImage(url)
        if (localUrl !== url) {
          downloadedCount++
        }
      } catch (error) {
        console.error(`❌ 下载失败 ${url}:`, error)
      }
    }
    
    console.log(`📊 成功下载 ${downloadedCount}/${imageUrls.size} 个图片`)
    
    // 将本地化的图片URL写回到JSON文件
    try {
      const localizedData = await localizeImages(jsonData)
      fs.writeFileSync(jsonFilePath, JSON.stringify(localizedData, null, 2))
      console.log(`💾 已更新图片URL至本地路径: ${jsonFilePath}`)
    } catch (error) {
      console.error(`❌ 无法更新JSON文件 ${jsonFilePath}:`, error)
    }
  } catch (error) {
    console.error(`❌ 处理文件 ${jsonFilePath} 时出错:`, error)
  }
}

/**
 * 处理API响应文件中的图片
 * @param outputDir 输出目录路径（通常是.output目录）
 */
async function processApiResponseImages(outputDir = '.output') {
  console.log('🚀 开始处理API响应文件中的图片...')
  
  // 检查输出目录是否存在
  if (!fs.existsSync(outputDir)) {
    console.error(`❌ 输出目录不存在: ${outputDir}`)
    return
  }
  
  const serverDir = path.join(outputDir, 'server/api')
  
  if (!fs.existsSync(serverDir)) {
    console.error(`❌ 服务器API目录不存在: ${serverDir}`)
    return
  }
  
  console.log(`🔍 扫描API响应文件: ${serverDir}`)
  
  // 递归函数查找所有JSON文件
  async function processDirectory(dir) {
    const entries = fs.readdirSync(dir, { withFileTypes: true })
    
    for (const entry of entries) {
      const fullPath = path.join(dir, entry.name)
      
      if (entry.isDirectory()) {
        await processDirectory(fullPath)
      } else if (entry.name.endsWith('.json')) {
        console.log(`📄 处理JSON文件: ${fullPath}`)
        await extractAndDownloadImages(fullPath)
      }
    }
  }
  
  await processDirectory(serverDir)
  console.log('✅ 所有API响应文件处理完成')
}

// 确保脚本能单独运行
async function main() {
  console.log('===== 🖼️ 开始图片本地化处理 =====')
  
  try {
    // 默认的输出目录是.output
    const outputDir = process.argv[2] || '.output'
    await processApiResponseImages(outputDir)
    console.log('===== ✅ 图片本地化处理完成 =====')
    process.exit(0)
  } catch (error) {
    console.error('❌ 图片本地化处理失败:', error)
    process.exit(1)
  }
}

main() 