"use client"

import { useState, useCallback, useRef } from "react"
import { useTranslations } from "next-intl"
import type { AiChatMessage } from "../types"
import {
  consumeSseStream,
  getStreamErrorKey,
  extractErrorMessage,
  removeTrailingEmptyAssistant,
  appendTokenToLastAssistant,
} from "./stream-utils"

/**
 * AI 流式聊天 Hook
 *
 * 通过 SSE 端点消费流式 AI 回复。
 * 支持：逐 token 渲染、停止生成（AbortController）、错误处理。
 */
type UseAiChatStreamReturn = {
  messages: AiChatMessage[]
  streaming: boolean
  error: string | null
  send: (messages: AiChatMessage[], options?: { systemPrompt?: string; providerId?: string }) => Promise<void>
  stop: () => void
  clear: () => void
}

export function useAiChatStream(): UseAiChatStreamReturn {
  const t = useTranslations("ai")
  const [messages, setMessages] = useState<AiChatMessage[]>([])
  const [streaming, setStreaming] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const abortControllerRef = useRef<AbortController | null>(null)

  const send = useCallback(
    async (
      inputMessages: AiChatMessage[],
      options?: { systemPrompt?: string; providerId?: string }
    ): Promise<void> => {
      if (streaming) return
      setStreaming(true)
      setError(null)

      const userMessage = inputMessages[inputMessages.length - 1]
      if (userMessage && userMessage.role === "user") {
        setMessages((prev) => [...prev, userMessage])
      }
      setMessages((prev) => [...prev, { role: "assistant", content: "" }])

      const controller = new AbortController()
      abortControllerRef.current = controller

      try {
        const response = await fetch("/api/ai/chat/stream", {
          method: "POST",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({
            messages: inputMessages,
            systemPrompt: options?.systemPrompt,
            providerId: options?.providerId,
          }),
          signal: controller.signal,
        })

        if (!response.ok) {
          const fallback = t(getStreamErrorKey(response.status))
          const errorMessage = await extractErrorMessage(response, fallback)
          setError(errorMessage)
          setMessages((prev) => removeTrailingEmptyAssistant(prev))
          return
        }

        await consumeSseStream(response, (event) => {
          if (event.type === "token") {
            setMessages((prev) => appendTokenToLastAssistant(prev, event.content))
          } else if (event.type === "error") {
            setError(event.message)
            setMessages((prev) => removeTrailingEmptyAssistant(prev))
          } else if (event.type === "filtered") {
            setError(t("safety.contentFiltered"))
          } else if (event.type === "socratic_warning") {
            // 苏格拉底式辅导警告：不阻断，仅提示
            // 可通过 toast 或 UI 标记展示，此处暂存 error 供组件判断
            setError(event.message)
          }
        })
      } catch (err) {
        if (!(err instanceof DOMException && err.name === "AbortError")) {
          setError(err instanceof Error ? err.message : String(err))
        }
      } finally {
        setStreaming(false)
        abortControllerRef.current = null
        setMessages((prev) => removeTrailingEmptyAssistant(prev))
      }
    },
    [streaming, t]
  )

  const stop = useCallback((): void => {
    abortControllerRef.current?.abort()
  }, [])

  const clear = useCallback((): void => {
    setMessages([])
    setError(null)
  }, [])

  return { messages, streaming, error, send, stop, clear }
}
