/**
 * SSE 流式响应解析与处理工具
 *
 * 从 use-ai-chat-stream hook 中抽取的纯函数，便于单独测试与复用。
 */

import type { AiChatMessage } from "../types"

/** SSE 事件类型 */
export type SseEvent =
  | { type: "token"; content: string }
  | { type: "error"; message: string }
  | { type: "filtered" }
  | { type: "socratic_warning"; message: string }

/**
 * 从 Response 中读取并解析 SSE 事件流
 *
 * @param response - fetch 返回的 Response 对象
 * @param onEvent - 每个解析出的事件回调
 */
export async function consumeSseStream(
  response: Response,
  onEvent: (event: SseEvent) => void
): Promise<void> {
  const reader = response.body?.getReader()
  if (!reader) return

  const decoder = new TextDecoder()
  let buffer = ""

  while (true) {
    const { done, value } = await reader.read()
    if (done) break

    buffer += decoder.decode(value, { stream: true })
    const lines = buffer.split("\n")
    buffer = lines.pop() ?? ""

    for (const line of lines) {
      if (!line.startsWith("data: ")) continue
      const data = line.slice(6).trim()
      if (data === "[DONE]") continue

      try {
        const parsed = JSON.parse(data) as {
          type: "token" | "error" | "filtered" | "socratic_warning"
          content?: string
          message?: string
        }

        if (parsed.type === "token" && parsed.content) {
          onEvent({ type: "token", content: parsed.content })
        } else if (parsed.type === "error") {
          onEvent({ type: "error", message: parsed.message ?? "Unknown error" })
        } else if (parsed.type === "filtered") {
          onEvent({ type: "filtered" })
        } else if (parsed.type === "socratic_warning") {
          onEvent({ type: "socratic_warning", message: parsed.message ?? "Socratic warning" })
        }
      } catch {
        // 忽略解析错误
      }
    }
  }
}

/** 流式错误对应的 i18n key（相对于 "ai" 命名空间） */
export type StreamErrorKey =
  | "safety.dailyLimit"
  | "error.unauthorized"
  | "safety.blocked"
  | "error.chatFailed"

/**
 * 根据 HTTP 状态码映射错误消息 i18n key
 *
 * 返回值用于 next-intl 的 t() 调用（相对于 "ai" 命名空间）。
 */
export function getStreamErrorKey(status: number): StreamErrorKey {
  if (status === 429) return "safety.dailyLimit"
  if (status === 403) return "error.unauthorized"
  if (status === 400) return "safety.blocked"
  return "error.chatFailed"
}

/**
 * 从错误响应体中提取错误消息
 */
export async function extractErrorMessage(
  response: Response,
  fallback: string
): Promise<string> {
  try {
    const errorText = await response.text()
    const errorData = JSON.parse(errorText) as { message?: string }
    return errorData.message ?? fallback
  } catch {
    return fallback
  }
}

/**
 * 移除消息列表末尾空的 assistant 消息
 *
 * 用于流式失败/中止时清理占位消息。
 */
export function removeTrailingEmptyAssistant(
  messages: AiChatMessage[]
): AiChatMessage[] {
  const filtered = [...messages]
  const last = filtered[filtered.length - 1]
  if (last && last.role === "assistant" && last.content === "") {
    filtered.pop()
  }
  return filtered
}

/**
 * 向消息列表末尾追加 token 到 assistant 消息
 */
export function appendTokenToLastAssistant(
  messages: AiChatMessage[],
  token: string
): AiChatMessage[] {
  const updated = [...messages]
  const last = updated[updated.length - 1]
  if (last && last.role === "assistant") {
    updated[updated.length - 1] = {
      ...last,
      content: last.content + token,
    }
  }
  return updated
}
