/**
 * Gemini Image Generator 图片生成工具
 *
 * 功能：
 * - 文生图（Text-to-Image）
 * - 图生图（Image-to-Image）
 * - 多种业务场景模板
 * - 批量生成
 * - 自定义输出目录
 *
 * 使用示例：
 *   node gemini-image-generator.js generate "A cute cat" -o ./output -r 16:9
 *   node gemini-image-generator.js edit "Add sunglasses" -i ./photo.jpg
 *   node gemini-image-generator.js template logo --text "MyBrand"
 *   node gemini-image-generator.js batch ./prompts.txt
 */

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

// ============================================================================
// 配置模块
// ============================================================================

function _loadConfig() {
  const configPath = path.join(__dirname, '..', '..', 'config.json')
  if (fs.existsSync(configPath)) {
    return JSON.parse(fs.readFileSync(configPath, 'utf-8'))
  }
  return {}
}

const _cfg = _loadConfig()

const Config = {
  api: {
    baseUrl: _cfg.geminiApiBaseUrl || 'https://yunwu.ai',
    model: _cfg.geminiModel || 'gemini-3.1-flash-image-preview',
    endpoint: _cfg.geminiEndpoint || `/v1beta/models/${_cfg.geminiModel || 'gemini-3.1-flash-image-preview'}:generateContent`,
    key: _cfg.geminiApiKey || ''
  },

  // 默认输出配置
  output: {
    defaultDir: './output',
    defaultFormat: 'png'
  },

  // 支持的宽高比
  aspectRatios: ['1:1', '2:3', '3:2', '3:4', '4:3', '4:5', '5:4', '9:16', '16:9', '21:9'],

  // 支持的分辨率
  imageSizes: ['512', '1K', '2K', '4K'],

  // 默认分辨率
  defaultImageSize: '2K',

  // 响应模式
  responseModalities: {
    textAndImage: ['TEXT', 'IMAGE'],
    imageOnly: ['IMAGE'],
    textOnly: ['TEXT']
  },

  // 超时设置（毫秒）
  timeout: {
    default: 180000,      // 默认2分钟
    max: 300000          // 最大5分钟
  }
}

// ============================================================================
// 文件处理模块
// ============================================================================

const FileUtils = {
  /**
   * 确保目录存在
   */
  ensureDir(dirPath) {
    if (!fs.existsSync(dirPath)) {
      fs.mkdirSync(dirPath, { recursive: true })
    }
    return dirPath
  },

  /**
   * 图片转Base64
   */
  imageToBase64(imagePath) {
    const buffer = fs.readFileSync(imagePath)
    const ext = path.extname(imagePath).toLowerCase()
    const mimeTypes = {
      '.png': 'image/png',
      '.jpg': 'image/jpeg',
      '.jpeg': 'image/jpeg',
      '.gif': 'image/gif',
      '.webp': 'image/webp'
    }
    return {
      mimeType: mimeTypes[ext] || 'image/png',
      data: buffer.toString('base64')
    }
  },

  /**
   * Base64保存为图片
   */
  base64ToImage(base64Data, outputPath) {
    const buffer = Buffer.from(base64Data, 'base64')
    fs.writeFileSync(outputPath, buffer)
    return outputPath
  },

  /**
   * 生成唯一文件名
   */
  generateFilename(prefix = 'image', ext = 'png') {
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
    const random = Math.random().toString(36).substring(2, 8)
    return `${prefix}_${timestamp}_${random}.${ext}`
  },

  /**
   * 读取提示词文件
   */
  readPromptsFile(filePath) {
    const content = fs.readFileSync(filePath, 'utf-8')
    return content.split('\n').filter(line => line.trim()).map(line => line.trim())
  }
}

// ============================================================================
// API调用模块
// ============================================================================

const GeminiAPI = {
  /**
   * 发送生成请求
   */
  async generateContent(contents, options = {}) {
    const {
      aspectRatio = '1:1',
      imageSize = Config.defaultImageSize,
      responseModalities = Config.responseModalities.textAndImage,
      timeout = Config.timeout.default
    } = options

    const url = `${Config.api.baseUrl}${Config.api.endpoint}?key=${Config.api.key}`

    const body = {
      contents: contents,
      generationConfig: {
        responseModalities: responseModalities,
        imageConfig: {
          aspectRatio: aspectRatio,
          imageSize: imageSize
        }
      }
    }

    console.log(`\n📡 API请求: ${Config.api.baseUrl}${Config.api.endpoint}`)
    console.log(`📋 模型: ${Config.api.model}`)
    console.log(`⏱️ 超时: ${timeout / 1000}秒`)

    // 使用 AbortController 实现超时
    const controller = new AbortController()
    const timeoutId = setTimeout(() => controller.abort(), timeout)

    try {
      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Authorization': `Bearer ${Config.api.key}`
        },
        body: JSON.stringify(body),
        signal: controller.signal
      })

      if (!response.ok) {
        const error = await response.text()
        throw new Error(`API请求失败: ${response.status} - ${error}`)
      }

      return await response.json()
    } finally {
      clearTimeout(timeoutId)
    }
  },

  /**
   * 解析响应，提取图片和文本
   */
  parseResponse(response) {
    const result = {
      text: '',
      images: []
    }

    if (!response.candidates || !response.candidates[0]) {
      return result
    }

    const parts = response.candidates[0].content?.parts || []

    for (const part of parts) {
      if (part.text) {
        result.text += part.text
      }
      if (part.inlineData) {
        result.images.push({
          mimeType: part.inlineData.mimeType,
          data: part.inlineData.data
        })
      }
    }

    return result
  }
}

// ============================================================================
// 业务场景模板模块
// ============================================================================

const Templates = {
  /**
   * 写实照片模板
   */
  photorealistic: {
    name: '写实照片',
    generate(subject, options = {}) {
      const {
        shotType = 'close-up portrait',
        lighting = 'soft, natural golden hour light',
        mood = 'serene',
        environment = '',
        cameraDetails = '85mm lens, shallow depth of field'
      } = options

      return `A photorealistic ${shotType} of ${subject}. ${environment ? `Set in ${environment}. ` : ''}The scene is illuminated by ${lighting}, creating a ${mood} atmosphere. Captured with ${cameraDetails}. Ultra-realistic, with sharp focus on key details.`
    }
  },

  /**
   * 贴纸/图标模板
   */
  sticker: {
    name: '贴纸/图标',
    generate(subject, options = {}) {
      const {
        style = 'kawaii',
        colorPalette = 'vibrant',
        background = 'white'
      } = options

      return `A ${style}-style sticker of ${subject}. The design features bold, clean outlines, simple cel-shading, and a ${colorPalette} color palette. The background must be ${background}.`
    }
  },

  /**
   * Logo设计模板
   */
  logo: {
    name: 'Logo设计',
    generate(text, options = {}) {
      const {
        style = 'modern, minimalist',
        colorScheme = 'black and white',
        shape = 'circle'
      } = options

      return `Create a ${style} logo${text ? ` with the text "${text}"` : ''}. The text should be in a clean, bold, sans-serif font. The color scheme is ${colorScheme}. Put the logo in a ${shape}.`
    }
  },

  /**
   * 产品图模板
   */
  product: {
    name: '产品图',
    generate(product, options = {}) {
      const {
        surface = 'polished concrete surface',
        lighting = 'three-point softbox setup',
        angle = 'slightly elevated 45-degree shot',
        background = 'minimalist'
      } = options

      return `A high-resolution, studio-lit product photograph of ${product}, presented on a ${surface}. The lighting is a ${lighting} designed to create soft, diffused highlights and eliminate harsh shadows. The camera angle is a ${angle} to showcase key features. Ultra-realistic. ${background} background.`
    }
  },

  /**
   * 极简设计模板
   */
  minimalist: {
    name: '极简设计',
    generate(subject, options = {}) {
      const {
        position = 'bottom-right',
        backgroundColor = 'off-white canvas',
        lighting = 'soft, diffused lighting from the top left'
      } = options

      return `A minimalist composition featuring a single, ${subject} positioned in the ${position} of the frame. The background is a vast, empty ${backgroundColor}, creating significant negative space for text. ${lighting}.`
    }
  },

  /**
   * 漫画/故事板模板
   */
  comic: {
    name: '漫画/故事板',
    generate(scene, options = {}) {
      const {
        style = 'gritty, noir',
        panels = 3
      } = options

      return `Make a ${panels} panel comic in a ${style} art style with high-contrast black and white inks. ${scene}`
    }
  },

  /**
   * 风格转换模板
   */
  styleTransfer: {
    name: '风格转换',
    generate(targetStyle, options = {}) {
      const {
        preserveElements = 'composition and key elements'
      } = options

      return `Transform the provided image into the artistic style of ${targetStyle}. Preserve the original ${preserveElements} but render with the new stylistic elements.`
    }
  },

  /**
   * 图像编辑模板
   */
  edit: {
    name: '图像编辑',
    generate(instruction, options = {}) {
      const {
        preserve = 'Keep everything else unchanged, preserving the original style, lighting, and composition'
      } = options

      return `${instruction}. ${preserve}.`
    }
  },

  /**
   * 图像合成模板
   */
  composite: {
    name: '图像合成',
    generate(description, options = {}) {
      return `Create a new image by combining the elements from the provided images. ${description} Generate a realistic result with proper lighting and shadows.`
    }
  }
}

// ============================================================================
// 核心生成器类
// ============================================================================

class GeminiImageGenerator {
  constructor(options = {}) {
    this.outputDir = options.outputDir || Config.output.defaultDir
    this.defaultAspectRatio = options.aspectRatio || '1:1'
    this.defaultImageSize = options.imageSize || Config.defaultImageSize

    if (!Config.api.key) {
      console.warn('警告: 未设置API密钥')
    }
  }

  /**
   * 文生图
   */
  async textToImage(prompt, options = {}) {
    const {
      aspectRatio = this.defaultAspectRatio,
      imageSize = this.defaultImageSize,
      outputDir = this.outputDir,
      filename = null
    } = options

    console.log(`\n🎨 生成图片: "${prompt.substring(0, 50)}..."`)
    console.log(`📐 宽高比: ${aspectRatio}`)
    console.log(`📏 分辨率: ${imageSize}`)

    const contents = [{
      role: 'user',
      parts: [{ text: prompt }]
    }]

    const response = await GeminiAPI.generateContent(contents, { aspectRatio, imageSize })
    const result = GeminiAPI.parseResponse(response)

    if (result.text) {
      console.log(`📝 模型回复: ${result.text}`)
    }

    const savedFiles = []
    FileUtils.ensureDir(outputDir)

    for (let i = 0; i < result.images.length; i++) {
      const img = result.images[i]
      const ext = img.mimeType.split('/')[1] || 'png'
      const outputFilename = filename || FileUtils.generateFilename('generated', ext)
      const outputPath = path.join(outputDir, outputFilename)

      FileUtils.base64ToImage(img.data, outputPath)
      savedFiles.push(outputPath)
      console.log(`✅ 已保存: ${outputPath}`)
    }

    return {
      text: result.text,
      images: result.images,
      savedFiles
    }
  }

  /**
   * 图生图（带参考图编辑）
   */
  async imageToImage(prompt, inputImages, options = {}) {
    const {
      aspectRatio = this.defaultAspectRatio,
      imageSize = this.defaultImageSize,
      outputDir = this.outputDir
    } = options

    console.log(`\n🖼️ 编辑图片: "${prompt.substring(0, 50)}..."`)
    console.log(`📁 输入图片: ${Array.isArray(inputImages) ? inputImages.length : 1} 张`)
    console.log(`📏 分辨率: ${imageSize}`)

    const parts = [{ text: prompt }]

    // 处理输入图片
    const images = Array.isArray(inputImages) ? inputImages : [inputImages]
    for (const imgPath of images) {
      const { mimeType, data } = FileUtils.imageToBase64(imgPath)
      parts.push({
        inlineData: {
          mime_type: mimeType,
          data: data
        }
      })
    }

    const contents = [{
      role: 'user',
      parts: parts
    }]

    const response = await GeminiAPI.generateContent(contents, { aspectRatio, imageSize })
    const result = GeminiAPI.parseResponse(response)

    if (result.text) {
      console.log(`📝 模型回复: ${result.text}`)
    }

    const savedFiles = []
    FileUtils.ensureDir(outputDir)

    for (let i = 0; i < result.images.length; i++) {
      const img = result.images[i]
      const ext = img.mimeType.split('/')[1] || 'png'
      const outputFilename = FileUtils.generateFilename('edited', ext)
      const outputPath = path.join(outputDir, outputFilename)

      FileUtils.base64ToImage(img.data, outputPath)
      savedFiles.push(outputPath)
      console.log(`✅ 已保存: ${outputPath}`)
    }

    return {
      text: result.text,
      images: result.images,
      savedFiles
    }
  }

  /**
   * 使用模板生成
   */
  async generateFromTemplate(templateName, ...args) {
    const template = Templates[templateName]
    if (!template) {
      throw new Error(`未知的模板: ${templateName}。可用模板: ${Object.keys(Templates).join(', ')}`)
    }

    const options = args[args.length - 1] || {}
    const prompt = template.generate(...args)

    console.log(`📋 使用模板: ${template.name}`)
    return this.textToImage(prompt, options)
  }

  /**
   * 批量生成
   */
  async batchGenerate(prompts, options = {}) {
    const results = []
    const total = prompts.length

    console.log(`\n🚀 开始批量生成，共 ${total} 个任务`)

    for (let i = 0; i < prompts.length; i++) {
      console.log(`\n[${i + 1}/${total}] 处理中...`)

      try {
        const result = await this.textToImage(prompts[i], {
          ...options,
          filename: `batch_${i + 1}.png`
        })
        results.push({ success: true, prompt: prompts[i], result })
      } catch (error) {
        console.error(`❌ 失败: ${error.message}`)
        results.push({ success: false, prompt: prompts[i], error: error.message })
      }
    }

    const successCount = results.filter(r => r.success).length
    console.log(`\n✨ 批量生成完成: ${successCount}/${total} 成功`)

    return results
  }

  /**
   * 多轮对话编辑
   */
  createChatSession(options = {}) {
    const history = []

    return {
      async send(message, inputImages = null) {
        const parts = [{ text: message }]

        // 如果有输入图片
        if (inputImages) {
          const images = Array.isArray(inputImages) ? inputImages : [inputImages]
          for (const imgPath of images) {
            const { mimeType, data } = FileUtils.imageToBase64(imgPath)
            parts.push({
              inlineData: {
                mime_type: mimeType,
                data: data
              }
            })
          }
        }

        // 添加用户消息到历史
        history.push({
          role: 'user',
          parts: parts
        })

        const response = await GeminiAPI.generateContent(history, options)
        const result = GeminiAPI.parseResponse(response)

        // 添加模型回复到历史（需要包含图片数据以便后续编辑）
        const modelParts = []
        if (result.text) {
          modelParts.push({ text: result.text })
        }
        for (const img of result.images) {
          modelParts.push({
            inlineData: {
              mime_type: img.mimeType,
              data: img.data
            }
          })
        }
        if (modelParts.length > 0) {
          history.push({
            role: 'model',
            parts: modelParts
          })
        }

        // 保存图片
        const savedFiles = []
        FileUtils.ensureDir(options.outputDir || this.outputDir)

        for (const img of result.images) {
          const ext = img.mimeType.split('/')[1] || 'png'
          const outputFilename = FileUtils.generateFilename('chat', ext)
          const outputPath = path.join(options.outputDir || this.outputDir, outputFilename)

          FileUtils.base64ToImage(img.data, outputPath)
          savedFiles.push(outputPath)
          console.log(`✅ 已保存: ${outputPath}`)
        }

        return {
          text: result.text,
          images: result.images,
          savedFiles
        }
      },

      getHistory() {
        return history
      }
    }
  }
}

// ============================================================================
// CLI接口模块
// ============================================================================

const CLI = {
  /**
   * 解析命令行参数
   */
  parseArgs(args) {
    const result = {
      command: '',
      params: [],
      options: {}
    }

    let i = 0
    while (i < args.length) {
      const arg = args[i]

      if (arg.startsWith('--')) {
        const key = arg.substring(2)
        const nextArg = args[i + 1]

        if (nextArg && !nextArg.startsWith('-')) {
          result.options[key] = nextArg
          i += 2
        } else {
          result.options[key] = true
          i++
        }
      } else if (arg.startsWith('-')) {
        const key = arg.substring(1)
        const shortOptions = {
          'o': 'output',
          'r': 'ratio',
          's': 'size',
          'i': 'input',
          't': 'template',
          'h': 'help'
        }

        const fullKey = shortOptions[key] || key
        const nextArg = args[i + 1]

        if (nextArg && !nextArg.startsWith('-')) {
          result.options[fullKey] = nextArg
          i += 2
        } else {
          result.options[fullKey] = true
          i++
        }
      } else if (!result.command) {
        result.command = arg
        i++
      } else {
        result.params.push(arg)
        i++
      }
    }

    return result
  },

  /**
   * 显示帮助信息
   */
  showHelp() {
    console.log(`
🎨 Gemini Image Generator - 云雾API图片生成工具
📦 模型: ${Config.api.model}

用法:
  node gemini-image-generator.js <command> [options]

命令:
  generate <prompt>         文生图
  edit <prompt>             图生图（需要 -i 指定输入图片）
  template <name>           使用模板生成
  batch <file>              批量生成（从文件读取提示词）
  list-templates            列出所有可用模板

选项:
  -o, --output <dir>        输出目录 (默认: ./output)
  -r, --ratio <ratio>       宽高比 (1:1, 16:9, 9:16, 3:2, 2:3 等)
  -s, --size <size>         分辨率 (512, 1K, 2K, 4K，默认: 2K)
  -i, --input <file>        输入图片路径（用于edit命令）
  -t, --template <name>     模板名称
  --text <text>             Logo文字（用于logo模板）
  --subject <subject>       主题内容
  --style <style>           风格
  -h, --help                显示帮助信息

示例:
  # 基础文生图 16:9 2K分辨率
  node gemini-image-generator.js generate "A cute cat wearing a hat" -o ./my-images -r 16:9 -s 2K

  # 高分辨率4K图片
  node gemini-image-generator.js generate "A landscape photo" -r 16:9 -s 4K

  # 图生图编辑
  node gemini-image-generator.js edit "Add sunglasses to this person" -i ./photo.jpg

  # 使用Logo模板
  node gemini-image-generator.js template logo --text "MyBrand" --style minimalist

  # 使用产品图模板
  node gemini-image-generator.js template product --subject "a minimalist ceramic coffee mug"

  # 批量生成
  node gemini-image-generator.js batch ./prompts.txt -o ./batch-output

可用宽高比:
  ${Config.aspectRatios.join(', ')}

可用分辨率:
  ${Config.imageSizes.join(', ')}

可用模板:
  ${Object.entries(Templates).map(([k, v]) => `${k} (${v.name})`).join('\n  ')}
`)
  },

  /**
   * 列出模板
   */
  listTemplates() {
    console.log('\n📋 可用模板:\n')
    for (const [key, template] of Object.entries(Templates)) {
      console.log(`  ${key.padEnd(15)} - ${template.name}`)
    }
    console.log('')
  },

  /**
   * 执行命令
   */
  async run(args) {
    const { command, params, options } = this.parseArgs(args)

    if (options.help || command === 'help' || !command) {
      this.showHelp()
      return
    }

    const generator = new GeminiImageGenerator({
      outputDir: options.output || Config.output.defaultDir,
      aspectRatio: options.ratio || '1:1',
      imageSize: options.size || Config.defaultImageSize
    })

    switch (command) {
      case 'generate': {
        const prompt = params.join(' ')
        if (!prompt) {
          console.error('❌ 请提供生成提示词')
          return
        }
        await generator.textToImage(prompt, {
          aspectRatio: options.ratio,
          imageSize: options.size,
          outputDir: options.output
        })
        break
      }

      case 'edit': {
        const prompt = params.join(' ')
        const inputImages = options.input?.split(',').map(p => p.trim())

        if (!prompt) {
          console.error('❌ 请提供编辑指令')
          return
        }
        if (!inputImages || inputImages.length === 0) {
          console.error('❌ 请使用 -i 指定输入图片')
          return
        }

        await generator.imageToImage(prompt, inputImages, {
          aspectRatio: options.ratio,
          imageSize: options.size,
          outputDir: options.output
        })
        break
      }

      case 'template': {
        const templateName = params[0] || options.template
        if (!templateName) {
          this.listTemplates()
          return
        }

        const template = Templates[templateName]
        if (!template) {
          console.error(`❌ 未知的模板: ${templateName}`)
          this.listTemplates()
          return
        }

        // 根据模板类型处理参数
        let templateOptions = { aspectRatio: options.ratio, outputDir: options.output }

        switch (templateName) {
          case 'logo':
            await generator.generateFromTemplate('logo', options.text || '', {
              style: options.style || 'modern, minimalist',
              colorScheme: 'black and white'
            }, templateOptions)
            break

          case 'product':
            await generator.generateFromTemplate('product', options.subject || params.slice(1).join(' ') || 'a product', {
              surface: 'polished concrete surface'
            }, templateOptions)
            break

          case 'photorealistic':
            await generator.generateFromTemplate('photorealistic', options.subject || params.slice(1).join(' ') || 'a person', {}, templateOptions)
            break

          case 'sticker':
            await generator.generateFromTemplate('sticker', options.subject || params.slice(1).join(' ') || 'a cute character', {}, templateOptions)
            break

          default:
            await generator.generateFromTemplate(templateName, params.slice(1).join(' ') || '', {}, templateOptions)
        }
        break
      }

      case 'batch': {
        const filePath = params[0]
        if (!filePath) {
          console.error('❌ 请提供提示词文件路径')
          return
        }

        const prompts = FileUtils.readPromptsFile(filePath)
        await generator.batchGenerate(prompts, {
          aspectRatio: options.ratio,
          outputDir: options.output
        })
        break
      }

      case 'list-templates': {
        this.listTemplates()
        break
      }

      default:
        console.error(`❌ 未知命令: ${command}`)
        this.showHelp()
    }
  }
}

// ============================================================================
// 导出模块
// ============================================================================

module.exports = {
  // 核心类
  GeminiImageGenerator,

  // 模块
  Config,
  FileUtils,
  GeminiAPI,
  Templates,
  CLI,

  // 便捷方法
  generate: async (prompt, options) => {
    const generator = new GeminiImageGenerator(options)
    return generator.textToImage(prompt, options)
  },

  edit: async (prompt, images, options) => {
    const generator = new GeminiImageGenerator(options)
    return generator.imageToImage(prompt, images, options)
  },

  fromTemplate: async (templateName, ...args) => {
    const generator = new GeminiImageGenerator(args[args.length - 1] || {})
    return generator.generateFromTemplate(templateName, ...args)
  }
}

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

// 如果直接运行此脚本
if (require.main === module) {
  const args = process.argv.slice(2)
  CLI.run(args).catch(error => {
    console.error(`\n❌ 错误: ${error.message}`)
    process.exit(1)
  })
}
