const express = require('express')
const router = express.Router()
const logger = require('../utils/logger')
const { authenticateApiKey } = require('../middleware/auth')
const geminiAccountService = require('../services/geminiAccountService')
const unifiedGeminiScheduler = require('../services/unifiedGeminiScheduler')
const { getAvailableModels } = require('../services/geminiRelayService')
const crypto = require('crypto')

// 生成会话哈希
function generateSessionHash(req) {
  const authSource =
    req.headers['authorization'] || req.headers['x-api-key'] || req.headers['x-goog-api-key']

  const sessionData = [req.headers['user-agent'], req.ip, authSource?.substring(0, 20)]
    .filter(Boolean)
    .join(':')

  return crypto.createHash('sha256').update(sessionData).digest('hex')
}

// 检查 API Key 权限
function checkPermissions(apiKeyData, requiredPermission = 'gemini') {
  const permissions = apiKeyData.permissions || 'all'
  return permissions === 'all' || permissions === requiredPermission
}

// 转换 OpenAI 消息格式到 Gemini 格式
function convertMessagesToGemini(messages) {
  const contents = []
  let systemInstruction = ''

  // 辅助函数：提取文本内容
  function extractTextContent(content) {
    // 处理 null 或 undefined
    if (content === null || content === undefined) {
      return ''
    }

    // 处理字符串
    if (typeof content === 'string') {
      return content
    }

    // 处理数组格式的内容
    if (Array.isArray(content)) {
      return content
        .map((item) => {
          if (item === null || item === undefined) {
            return ''
          }
          if (typeof item === 'string') {
            return item
          }
          if (typeof item === 'object') {
            // 处理 {type: 'text', text: '...'} 格式
            if (item.type === 'text' && item.text) {
              return item.text
            }
            // 处理 {text: '...'} 格式
            if (item.text) {
              return item.text
            }
            // 处理嵌套的对象或数组
            if (item.content) {
              return extractTextContent(item.content)
            }
          }
          return ''
        })
        .join('')
    }

    // 处理对象格式的内容
    if (typeof content === 'object') {
      // 处理 {text: '...'} 格式
      if (content.text) {
        return content.text
      }
      // 处理 {content: '...'} 格式
      if (content.content) {
        return extractTextContent(content.content)
      }
      // 处理 {parts: [{text: '...'}]} 格式
      if (content.parts && Array.isArray(content.parts)) {
        return content.parts
          .map((part) => {
            if (part && part.text) {
              return part.text
            }
            return ''
          })
          .join('')
      }
    }

    // 最后的后备选项：只有在内容确实不为空且有意义时才转换为字符串
    if (
      content !== undefined &&
      content !== null &&
      content !== '' &&
      typeof content !== 'object'
    ) {
      return String(content)
    }

    return ''
  }

  for (const message of messages) {
    const textContent = extractTextContent(message.content)

    if (message.role === 'system') {
      systemInstruction += (systemInstruction ? '\n\n' : '') + textContent
    } else if (message.role === 'user') {
      contents.push({
        role: 'user',
        parts: [{ text: textContent }]
      })
    } else if (message.role === 'assistant') {
      contents.push({
        role: 'model',
        parts: [{ text: textContent }]
      })
    }
  }

  return { contents, systemInstruction }
}

// 转换 Gemini 响应到 OpenAI 格式
function convertGeminiResponseToOpenAI(geminiResponse, model, stream = false) {
  if (stream) {
    // 处理流式响应 - 原样返回 SSE 数据
    return geminiResponse
  } else {
    // 非流式响应转换
    // 处理嵌套的 response 结构
    const actualResponse = geminiResponse.response || geminiResponse

    if (actualResponse.candidates && actualResponse.candidates.length > 0) {
      const candidate = actualResponse.candidates[0]
      const content = candidate.content?.parts?.[0]?.text || ''
      const finishReason = candidate.finishReason?.toLowerCase() || 'stop'

      // 计算 token 使用量
      const usage = actualResponse.usageMetadata || {
        promptTokenCount: 0,
        candidatesTokenCount: 0,
        totalTokenCount: 0
      }

      return {
        id: `chatcmpl-${Date.now()}`,
        object: 'chat.completion',
        created: Math.floor(Date.now() / 1000),
        model,
        choices: [
          {
            index: 0,
            message: {
              role: 'assistant',
              content
            },
            finish_reason: finishReason
          }
        ],
        usage: {
          prompt_tokens: usage.promptTokenCount,
          completion_tokens: usage.candidatesTokenCount,
          total_tokens: usage.totalTokenCount
        }
      }
    } else {
      throw new Error('No response from Gemini')
    }
  }
}

// OpenAI 兼容的聊天完成端点
router.post('/v1/chat/completions', authenticateApiKey, async (req, res) => {
  const startTime = Date.now()
  let abortController = null
  let account = null // Declare account outside try block for error handling
  let accountSelection = null // Declare accountSelection for error handling
  let sessionHash = null // Declare sessionHash for error handling

  try {
    const apiKeyData = req.apiKey

    // 检查权限
    if (!checkPermissions(apiKeyData, 'gemini')) {
      return res.status(403).json({
        error: {
          message: 'This API key does not have permission to access Gemini',
          type: 'permission_denied',
          code: 'permission_denied'
        }
      })
    }
    // 处理请求体结构 - 支持多种格式
    let requestBody = req.body

    // 如果请求体被包装在 body 字段中，解包它
    if (req.body.body && typeof req.body.body === 'object') {
      requestBody = req.body.body
    }

    // 从 URL 路径中提取模型信息（如果存在）
    let urlModel = null
    const urlPath = req.body?.config?.url || req.originalUrl || req.url
    const modelMatch = urlPath.match(/\/([^/]+):(?:stream)?[Gg]enerateContent/)
    if (modelMatch) {
      urlModel = modelMatch[1]
      logger.debug(`Extracted model from URL: ${urlModel}`)
    }

    // 提取请求参数
    const {
      messages: requestMessages,
      contents: requestContents,
      model: bodyModel = 'gemini-2.0-flash-exp',
      temperature = 0.7,
      max_tokens = 4096,
      stream = false
    } = requestBody

    // 检查URL中是否包含stream标识
    const isStreamFromUrl = urlPath && urlPath.includes('streamGenerateContent')
    const actualStream = stream || isStreamFromUrl

    // 优先使用 URL 中的模型，其次是请求体中的模型
    const model = urlModel || bodyModel

    // 支持两种格式: OpenAI 的 messages 或 Gemini 的 contents
    let messages = requestMessages
    if (requestContents && Array.isArray(requestContents)) {
      messages = requestContents
    }

    // 验证必需参数
    if (!messages || !Array.isArray(messages) || messages.length === 0) {
      return res.status(400).json({
        error: {
          message: 'Messages array is required',
          type: 'invalid_request_error',
          code: 'invalid_request'
        }
      })
    }

    // 检查模型限制
    if (apiKeyData.enableModelRestriction && apiKeyData.restrictedModels.length > 0) {
      if (!apiKeyData.restrictedModels.includes(model)) {
        return res.status(403).json({
          error: {
            message: `Model ${model} is not allowed for this API key`,
            type: 'invalid_request_error',
            code: 'model_not_allowed'
          }
        })
      }
    }

    // 转换消息格式
    const { contents: geminiContents, systemInstruction } = convertMessagesToGemini(messages)

    // 构建 Gemini 请求体
    const geminiRequestBody = {
      contents: geminiContents,
      generationConfig: {
        temperature,
        maxOutputTokens: max_tokens,
        candidateCount: 1
      }
    }

    if (systemInstruction) {
      geminiRequestBody.systemInstruction = { parts: [{ text: systemInstruction }] }
    }

    // 生成会话哈希用于粘性会话
    sessionHash = generateSessionHash(req)

    // 选择可用的 Gemini 账户
    try {
      accountSelection = await unifiedGeminiScheduler.selectAccountForApiKey(
        apiKeyData,
        sessionHash,
        model
      )
      account = await geminiAccountService.getAccount(accountSelection.accountId)
    } catch (error) {
      logger.error('Failed to select Gemini account:', error)
      account = null
    }

    if (!account) {
      return res.status(503).json({
        error: {
          message: 'No available Gemini accounts',
          type: 'service_unavailable',
          code: 'service_unavailable'
        }
      })
    }

    logger.info(`Using Gemini account: ${account.id} for API key: ${apiKeyData.id}`)

    // 标记账户被使用
    await geminiAccountService.markAccountUsed(account.id)

    // 解析账户的代理配置
    let proxyConfig = null
    if (account.proxy) {
      try {
        proxyConfig = typeof account.proxy === 'string' ? JSON.parse(account.proxy) : account.proxy
      } catch (e) {
        logger.warn('Failed to parse proxy configuration:', e)
      }
    }

    // 创建中止控制器
    abortController = new AbortController()

    // 处理客户端断开连接
    req.on('close', () => {
      if (abortController && !abortController.signal.aborted) {
        logger.info('Client disconnected, aborting Gemini request')
        abortController.abort()
      }
    })

    // 获取OAuth客户端
    const client = await geminiAccountService.getOauthClient(
      account.accessToken,
      account.refreshToken,
      proxyConfig
    )
    if (actualStream) {
      // 流式响应
      logger.info('StreamGenerateContent request', {
        model,
        projectId: account.projectId,
        apiKeyId: apiKeyData.id
      })

      const streamResponse = await geminiAccountService.generateContentStream(
        client,
        { model, request: geminiRequestBody },
        null, // user_prompt_id
        account.projectId, // 使用有权限的项目ID
        apiKeyData.id, // 使用 API Key ID 作为 session ID
        abortController.signal, // 传递中止信号
        proxyConfig // 传递代理配置
      )

      // 设置流式响应头
      res.setHeader('Content-Type', 'text/event-stream')
      res.setHeader('Cache-Control', 'no-cache')
      res.setHeader('Connection', 'keep-alive')
      res.setHeader('X-Accel-Buffering', 'no')

      // 处理流式响应，转换为 OpenAI 格式
      let buffer = ''

      // 发送初始的空消息，符合 OpenAI 流式格式
      const initialChunk = {
        id: `chatcmpl-${Date.now()}`,
        object: 'chat.completion.chunk',
        created: Math.floor(Date.now() / 1000),
        model,
        choices: [
          {
            index: 0,
            delta: { role: 'assistant' },
            finish_reason: null
          }
        ]
      }
      res.write(`data: ${JSON.stringify(initialChunk)}\n\n`)

      // 用于收集usage数据
      let totalUsage = {
        promptTokenCount: 0,
        candidatesTokenCount: 0,
        totalTokenCount: 0
      }
      const usageReported = false

      streamResponse.on('data', (chunk) => {
        try {
          const chunkStr = chunk.toString()

          if (!chunkStr.trim()) {
            return
          }

          buffer += chunkStr
          const lines = buffer.split('\n')
          buffer = lines.pop() || '' // 保留最后一个不完整的行

          for (const line of lines) {
            if (!line.trim()) {
              continue
            }

            // 处理 SSE 格式
            let jsonData = line
            if (line.startsWith('data: ')) {
              jsonData = line.substring(6).trim()
            }

            if (!jsonData || jsonData === '[DONE]') {
              continue
            }

            try {
              const data = JSON.parse(jsonData)

              // 捕获usage数据
              if (data.response?.usageMetadata) {
                totalUsage = data.response.usageMetadata
                logger.debug('📊 Captured Gemini usage data:', totalUsage)
              }

              // 转换为 OpenAI 流式格式
              if (data.response?.candidates && data.response.candidates.length > 0) {
                const candidate = data.response.candidates[0]
                const content = candidate.content?.parts?.[0]?.text || ''
                const { finishReason } = candidate

                // 只有当有内容或者是结束标记时才发送数据
                if (content || finishReason === 'STOP') {
                  const openaiChunk = {
                    id: `chatcmpl-${Date.now()}`,
                    object: 'chat.completion.chunk',
                    created: Math.floor(Date.now() / 1000),
                    model,
                    choices: [
                      {
                        index: 0,
                        delta: content ? { content } : {},
                        finish_reason: finishReason === 'STOP' ? 'stop' : null
                      }
                    ]
                  }

                  res.write(`data: ${JSON.stringify(openaiChunk)}\n\n`)

                  // 如果结束了，添加 usage 信息并发送最终的 [DONE]
                  if (finishReason === 'STOP') {
                    // 如果有 usage 数据，添加到最后一个 chunk
                    if (data.response.usageMetadata) {
                      const usageChunk = {
                        id: `chatcmpl-${Date.now()}`,
                        object: 'chat.completion.chunk',
                        created: Math.floor(Date.now() / 1000),
                        model,
                        choices: [
                          {
                            index: 0,
                            delta: {},
                            finish_reason: 'stop'
                          }
                        ],
                        usage: {
                          prompt_tokens: data.response.usageMetadata.promptTokenCount || 0,
                          completion_tokens: data.response.usageMetadata.candidatesTokenCount || 0,
                          total_tokens: data.response.usageMetadata.totalTokenCount || 0
                        }
                      }
                      res.write(`data: ${JSON.stringify(usageChunk)}\n\n`)
                    }
                    res.write('data: [DONE]\n\n')
                  }
                }
              }
            } catch (e) {
              logger.debug('Error parsing JSON line:', e.message)
            }
          }
        } catch (error) {
          logger.error('Stream processing error:', error)
          if (!res.headersSent) {
            res.status(500).json({
              error: {
                message: error.message || 'Stream error',
                type: 'api_error'
              }
            })
          }
        }
      })

      streamResponse.on('end', async () => {
        logger.info('Stream completed successfully')

        // 记录使用统计
        if (!usageReported && totalUsage.totalTokenCount > 0) {
          try {
            const apiKeyService = require('../services/apiKeyService')
            await apiKeyService.recordUsage(
              apiKeyData.id,
              totalUsage.promptTokenCount || 0,
              totalUsage.candidatesTokenCount || 0,
              0, // cacheCreateTokens
              0, // cacheReadTokens
              model,
              account.id
            )
            logger.info(
              `📊 Recorded Gemini stream usage - Input: ${totalUsage.promptTokenCount}, Output: ${totalUsage.candidatesTokenCount}, Total: ${totalUsage.totalTokenCount}`
            )
          } catch (error) {
            logger.error('Failed to record Gemini usage:', error)
          }
        }

        if (!res.headersSent) {
          res.write('data: [DONE]\n\n')
        }
        res.end()
      })

      streamResponse.on('error', (error) => {
        logger.error('Stream error:', error)
        if (!res.headersSent) {
          res.status(500).json({
            error: {
              message: error.message || 'Stream error',
              type: 'api_error'
            }
          })
        } else {
          // 如果已经开始发送流数据，发送错误事件
          res.write(`data: {"error": {"message": "${error.message || 'Stream error'}"}}\n\n`)
          res.write('data: [DONE]\n\n')
          res.end()
        }
      })
    } else {
      // 非流式响应
      logger.info('GenerateContent request', {
        model,
        projectId: account.projectId,
        apiKeyId: apiKeyData.id
      })

      const response = await geminiAccountService.generateContent(
        client,
        { model, request: geminiRequestBody },
        null, // user_prompt_id
        account.projectId, // 使用有权限的项目ID
        apiKeyData.id, // 使用 API Key ID 作为 session ID
        proxyConfig // 传递代理配置
      )

      // 转换为 OpenAI 格式并返回
      const openaiResponse = convertGeminiResponseToOpenAI(response, model, false)

      // 记录使用统计
      if (openaiResponse.usage) {
        try {
          const apiKeyService = require('../services/apiKeyService')
          await apiKeyService.recordUsage(
            apiKeyData.id,
            openaiResponse.usage.prompt_tokens || 0,
            openaiResponse.usage.completion_tokens || 0,
            0, // cacheCreateTokens
            0, // cacheReadTokens
            model,
            account.id
          )
          logger.info(
            `📊 Recorded Gemini usage - Input: ${openaiResponse.usage.prompt_tokens}, Output: ${openaiResponse.usage.completion_tokens}, Total: ${openaiResponse.usage.total_tokens}`
          )
        } catch (error) {
          logger.error('Failed to record Gemini usage:', error)
        }
      }

      res.json(openaiResponse)
    }

    const duration = Date.now() - startTime
    logger.info(`OpenAI-Gemini request completed in ${duration}ms`)
  } catch (error) {
    logger.error('OpenAI-Gemini request error:', error)

    // 处理速率限制
    if (error.status === 429) {
      if (req.apiKey && account && accountSelection) {
        await unifiedGeminiScheduler.markAccountRateLimited(account.id, 'gemini', sessionHash)
      }
    }

    // 返回 OpenAI 格式的错误响应
    const status = error.status || 500
    const errorResponse = {
      error: error.error || {
        message: error.message || 'Internal server error',
        type: 'server_error',
        code: 'internal_error'
      }
    }

    res.status(status).json(errorResponse)
  } finally {
    // 清理资源
    if (abortController) {
      abortController = null
    }
  }
  return undefined
})

// OpenAI 兼容的模型列表端点
router.get('/v1/models', authenticateApiKey, async (req, res) => {
  try {
    const apiKeyData = req.apiKey

    // 检查权限
    if (!checkPermissions(apiKeyData, 'gemini')) {
      return res.status(403).json({
        error: {
          message: 'This API key does not have permission to access Gemini',
          type: 'permission_denied',
          code: 'permission_denied'
        }
      })
    }

    // 选择账户获取模型列表
    let account = null
    try {
      const accountSelection = await unifiedGeminiScheduler.selectAccountForApiKey(
        apiKeyData,
        null,
        null
      )
      account = await geminiAccountService.getAccount(accountSelection.accountId)
    } catch (error) {
      logger.warn('Failed to select Gemini account for models endpoint:', error)
    }

    let models = []

    if (account) {
      // 获取实际的模型列表
      models = await getAvailableModels(account.accessToken, account.proxy)
    } else {
      // 返回默认模型列表
      models = [
        {
          id: 'gemini-2.0-flash-exp',
          object: 'model',
          created: Math.floor(Date.now() / 1000),
          owned_by: 'google'
        }
      ]
    }

    // 如果启用了模型限制，过滤模型列表
    if (apiKeyData.enableModelRestriction && apiKeyData.restrictedModels.length > 0) {
      models = models.filter((model) => apiKeyData.restrictedModels.includes(model.id))
    }

    res.json({
      object: 'list',
      data: models
    })
  } catch (error) {
    logger.error('Failed to get OpenAI-Gemini models:', error)
    res.status(500).json({
      error: {
        message: 'Failed to retrieve models',
        type: 'server_error',
        code: 'internal_error'
      }
    })
  }
  return undefined
})

// OpenAI 兼容的模型详情端点
router.get('/v1/models/:model', authenticateApiKey, async (req, res) => {
  try {
    const apiKeyData = req.apiKey
    const modelId = req.params.model

    // 检查权限
    if (!checkPermissions(apiKeyData, 'gemini')) {
      return res.status(403).json({
        error: {
          message: 'This API key does not have permission to access Gemini',
          type: 'permission_denied',
          code: 'permission_denied'
        }
      })
    }

    // 检查模型限制
    if (apiKeyData.enableModelRestriction && apiKeyData.restrictedModels.length > 0) {
      if (!apiKeyData.restrictedModels.includes(modelId)) {
        return res.status(404).json({
          error: {
            message: `Model '${modelId}' not found`,
            type: 'invalid_request_error',
            code: 'model_not_found'
          }
        })
      }
    }

    // 返回模型信息
    res.json({
      id: modelId,
      object: 'model',
      created: Math.floor(Date.now() / 1000),
      owned_by: 'google',
      permission: [],
      root: modelId,
      parent: null
    })
  } catch (error) {
    logger.error('Failed to get model details:', error)
    res.status(500).json({
      error: {
        message: 'Failed to retrieve model details',
        type: 'server_error',
        code: 'internal_error'
      }
    })
  }
  return undefined
})

module.exports = router
