import type { Client, Message } from 'discord.js'
import { HTTPClient } from '@/http'
import { getDefaultAgentId } from '@/app/api/nova-config'
import { getConversationId, setConversationId } from './user-store'
import { sendMessageAndWaitResponse } from '@/remote-control/shared/nova-bridge'
import { uploadBotAttachments, type BotAttachment } from '@/remote-control/shared/file-uploader'
import { BotLogger } from '@/remote-control/shared/logger'

const oapiClient = new HTTPClient({
  baseURL: process.env.NOVA_BASE_URL,
  headers: {
    'Content-Type': 'application/json',
    'Tenant-Id': process.env.NOVA_TENANT_ID!,
    'Authorization': process.env.NOVA_ACCESS_KEY!,
  },
})

const userQueues = new Map<string, Promise<void>>()

function splitMessage(text: string, maxLength = 2000): string[] {
  if (text.length <= maxLength) return [text]
  const parts: string[] = []
  let remaining = text
  while (remaining.length > 0) {
    if (remaining.length <= maxLength) {
      parts.push(remaining)
      break
    }
    let splitIndex = remaining.lastIndexOf('\n', maxLength)
    if (splitIndex <= 0) {
      splitIndex = maxLength
    }
    parts.push(remaining.slice(0, splitIndex))
    remaining = remaining.slice(splitIndex).trimStart()
  }
  return parts
}

async function getOrCreateConversation(discordUserId: string): Promise<string> {
  const existing = getConversationId(discordUserId)
  if (existing) return existing

  const res = await oapiClient.post<{ conversation_id: string }>(
    '/v1/oapi/super_agent/chat/create_conversation',
    {
      agent_id: getDefaultAgentId(),
      title: `Discord User ${discordUserId}`,
    },
  )

  const conversationId = res.conversation_id
  setConversationId(discordUserId, conversationId)
  return conversationId
}

async function processMessage(message: Message, onMessage?: () => void): Promise<void> {
  const content = message.content
    .replace(/<@!?\d+>/g, '')
    .trim()

  // Extract attachments from Discord message
  const attachments: BotAttachment[] = Array.from(message.attachments.values()).map(att => ({
    url: att.url,
    fileName: att.name ?? `discord_file_${Date.now()}`,
    mimeType: att.contentType ?? undefined,
    size: att.size,
  }))

  if (!content && attachments.length === 0) return

  BotLogger.log({
    platform: 'discord',
    eventType: 'message_received',
    severity: 'info',
    message: `收到来自用户 ${message.author.username} 的消息 (${attachments.length} 附件)`,
    details: { userId: message.author.id, channelId: message.channelId },
  })

  let typingInterval: ReturnType<typeof setInterval> | null = null

  try {
    const channel = message.channel
    if ('sendTyping' in channel) {
      await channel.sendTyping()
    }
    typingInterval = setInterval(() => {
      if ('sendTyping' in channel) {
        channel.sendTyping().catch(() => {})
      }
    }, 8000)

    // Upload attachments if any
    let uploadFileIds: string[] | undefined
    if (attachments.length > 0) {
      uploadFileIds = await uploadBotAttachments(attachments)
      if (uploadFileIds.length === 0) uploadFileIds = undefined
    }

    const conversationId = await getOrCreateConversation(message.author.id)
    const response = await sendMessageAndWaitResponse(
      `discord:${message.author.id}`,
      conversationId,
      content || '',
      uploadFileIds,
    )

    if (!response) {
      await message.reply('没有收到回复，请稍后重试。')
      return
    }

    const parts = splitMessage(response)
    for (const part of parts) {
      await message.reply(part)
    }

    if (onMessage) onMessage()

    BotLogger.log({
      platform: 'discord',
      eventType: 'message_sent',
      severity: 'info',
      message: `已回复用户 ${message.author.username}`,
    })
  } catch (error) {
    const errMsg = error instanceof Error ? error.message : '未知错误'
    console.error('[Discord Bot] 处理消息失败:', errMsg)
    await message.reply(`处理消息时出错: ${errMsg}`).catch(() => {})
    BotLogger.log({
      platform: 'discord',
      eventType: 'error',
      severity: 'error',
      message: `处理消息失败: ${errMsg}`,
      details: { userId: message.author.id },
    })
  } finally {
    if (typingInterval) clearInterval(typingInterval)
  }
}

export function registerHandlers(client: Client, onMessage?: () => void): void {
  client.on('messageCreate', (message: Message) => {
    if (message.author.bot) return
    if (!client.user || !message.mentions.has(client.user)) return

    const userId = message.author.id

    const currentQueue = userQueues.get(userId) ?? Promise.resolve()
    const newQueue = currentQueue.then(() => processMessage(message, onMessage))
    userQueues.set(userId, newQueue)

    newQueue.finally(() => {
      if (userQueues.get(userId) === newQueue) {
        userQueues.delete(userId)
      }
    })
  })
}
