"use client"

import { useState, useRef, useEffect, useCallback } from "react"
import { useTranslations } from "next-intl"
import { Send, Bot, User, Square, Trash2, Sparkles } from "lucide-react"
import { toast } from "sonner"

import { cn } from "@/shared/lib/utils"
import { Button } from "@/shared/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card"
import { Textarea } from "@/shared/components/ui/textarea"
import { ScrollArea } from "@/shared/components/ui/scroll-area"
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/shared/components/ui/tooltip"
import { AiChatSkeleton } from "./ai-skeleton"
import { AiMarkdownRenderer } from "./ai-markdown-renderer"
import { useAiChatStream } from "../hooks/use-ai-chat-stream"
import type { AiChatMessage } from "../types"

type AiChatPanelProps = {
  /** 初始系统提示词 */
  systemPrompt?: string
  /** 上下文信息（注入到 user message 前面） */
  contextMessage?: string
  /** 占位提示文本 */
  placeholder?: string
  /** 标题 */
  title?: string
  /** 最大消息数 */
  maxMessages?: number
  /** 建议提示词列表（空状态展示） */
  suggestedPrompts?: string[]
}

/**
 * AI 聊天面板
 *
 * 通用 AI 对话组件，可嵌入任何页面。
 * V2 增强：
 * - 流式响应（SSE）逐 token 渲染
 * - Markdown 渲染（代码块、表格、列表）
 * - 复制按钮
 * - 停止生成按钮
 * - 清除对话按钮
 * - 建议提示词
 * - aria-live 无障碍
 * - 对话历史持久化（localStorage，防抖写入）
 */
export function AiChatPanel({
  systemPrompt,
  contextMessage,
  placeholder,
  title,
  maxMessages = 50,
  suggestedPrompts,
}: AiChatPanelProps): React.ReactNode {
  const t = useTranslations("ai")
  const { messages, streaming, error, send, stop, clear } = useAiChatStream()
  const [input, setInput] = useState("")
  const scrollRef = useRef<HTMLDivElement>(null)
  const storageKey = "ai-chat-history"
  const persistTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  // 持久化对话历史（防抖 500ms，避免流式过程中频繁写入）
  useEffect(() => {
    if (messages.length === 0) return
    // 流式过程中不写入，流结束后再写
    if (streaming) return

    if (persistTimerRef.current) {
      clearTimeout(persistTimerRef.current)
    }
    persistTimerRef.current = setTimeout(() => {
      try {
        localStorage.setItem(storageKey, JSON.stringify(messages.slice(-20)))
      } catch {
        // 忽略写入错误
      }
    }, 500)

    return () => {
      if (persistTimerRef.current) {
        clearTimeout(persistTimerRef.current)
      }
    }
  }, [messages, streaming])

  // 自动滚动到底部
  useEffect(() => {
    if (scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight
    }
  }, [messages])

  const handleSend = useCallback(
    async (content?: string): Promise<void> => {
      const trimmed = (content ?? input).trim()
      if (!trimmed || streaming || messages.length >= maxMessages) return

      const contextPrefix = contextMessage
        ? `Context:\n${contextMessage}\n\nUser question: ${trimmed}`
        : trimmed

      const requestMessages: AiChatMessage[] = [
        ...messages,
        { role: "user", content: contextPrefix },
      ]

      setInput("")
      await send(requestMessages, { systemPrompt })
    },
    [input, streaming, messages, maxMessages, systemPrompt, contextMessage, send]
  )

  const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>): void => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault()
      void handleSend()
    }
  }

  const handleClear = (): void => {
    if (window.confirm(t("chat.clearConfirm"))) {
      clear()
      try {
        localStorage.removeItem(storageKey)
      } catch {
        // 忽略
      }
      toast.success(t("chat.clear"))
    }
  }

  const handleSuggestedPrompt = (prompt: string): void => {
    void handleSend(prompt)
  }

  if (streaming && messages.length === 0) {
    return <AiChatSkeleton />
  }

  const defaultSuggestedPrompts = suggestedPrompts ?? [
    t("chat.suggestedPrompts.teacher.0"),
    t("chat.suggestedPrompts.teacher.1"),
    t("chat.suggestedPrompts.teacher.2"),
  ]

  return (
    <Card>
      <CardHeader>
        <div className="flex items-center justify-between">
          <CardTitle className="flex items-center gap-2">
            <Bot className="h-4 w-4 text-primary" />
            {title ?? t("chat.title")}
          </CardTitle>
          {messages.length > 0 ? (
            <TooltipProvider>
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    className="h-7 px-2 text-muted-foreground"
                    onClick={handleClear}
                    aria-label={t("chat.clear")}
                  >
                    <Trash2 className="h-3.5 w-3.5" />
                  </Button>
                </TooltipTrigger>
                <TooltipContent>{t("chat.clear")}</TooltipContent>
              </Tooltip>
            </TooltipProvider>
          ) : null}
        </div>
      </CardHeader>
      <CardContent className="space-y-3">
        {error ? (
          <div
            className="rounded-md border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive"
            role="alert"
          >
            {error}
          </div>
        ) : null}

        {messages.length > 0 ? (
          <ScrollArea
            className="h-72 w-full rounded-md border p-3"
            aria-live="polite"
            aria-relevant="additions text"
          >
            <div className="space-y-3" ref={scrollRef}>
              {messages.map((message, index) => (
                <div
                  key={index}
                  className={cn(
                    "flex gap-2",
                    message.role === "user" ? "justify-end" : "justify-start"
                  )}
                >
                  {message.role === "assistant" ? (
                    <Bot className="h-5 w-5 shrink-0 text-primary mt-0.5" />
                  ) : (
                    <User className="h-5 w-5 shrink-0 text-muted-foreground mt-0.5" />
                  )}
                  <div
                    className={cn(
                      // 任意值：聊天气泡需按容器宽度百分比限制，固定 max-w-* 无法适应不同面板宽度
                      "rounded-md px-3 py-2 text-sm max-w-[80%]",
                      message.role === "user"
                        ? "bg-primary text-primary-foreground"
                        : "bg-muted"
                    )}
                  >
                    {message.role === "assistant" ? (
                      <AiMarkdownRenderer content={message.content} />
                    ) : (
                      <p className="whitespace-pre-wrap">{message.content}</p>
                    )}
                  </div>
                </div>
              ))}
              {streaming ? (
                <div className="flex gap-2 justify-start">
                  <Bot className="h-5 w-5 shrink-0 text-primary mt-0.5" />
                  <div className="rounded-md px-3 py-2 text-sm bg-muted">
                    <span className="animate-pulse">{t("chat.streaming")}</span>
                    <span className="inline-block w-1 h-4 ml-1 bg-primary animate-pulse" />
                  </div>
                </div>
              ) : null}
            </div>
          </ScrollArea>
        ) : (
          <div className="space-y-3">
            <div className="rounded-md border border-dashed p-6 text-center">
              <Sparkles className="h-8 w-8 text-primary mx-auto mb-2" />
              <p className="text-sm text-muted-foreground mb-3">
                {t("chat.suggestedPrompts.title")}
              </p>
              <div className="flex flex-wrap gap-2 justify-center">
                {defaultSuggestedPrompts.map((prompt, index) => (
                  <Button
                    key={index}
                    type="button"
                    variant="outline"
                    size="sm"
                    className="text-xs"
                    onClick={() => handleSuggestedPrompt(prompt)}
                  >
                    {prompt}
                  </Button>
                ))}
              </div>
            </div>
          </div>
        )}

        <div className="flex gap-2">
          <Textarea
            value={input}
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={handleKeyDown}
            placeholder={placeholder ?? t("chat.placeholder")}
            className="min-h-16 resize-none"
            disabled={streaming || messages.length >= maxMessages}
            aria-label={t("chat.inputLabel")}
          />
          {streaming ? (
            <Button
              type="button"
              size="icon"
              variant="destructive"
              onClick={stop}
              aria-label={t("chat.stopGeneration")}
            >
              <Square className="h-4 w-4" />
            </Button>
          ) : (
            <Button
              type="button"
              size="icon"
              onClick={() => void handleSend()}
              disabled={!input.trim() || messages.length >= maxMessages}
              aria-label={t("chat.send")}
            >
              <Send className="h-4 w-4" />
            </Button>
          )}
        </div>
        {messages.length >= maxMessages ? (
          <p className="text-xs text-muted-foreground text-center">
            {t("chat.maxReached")}
          </p>
        ) : null}
      </CardContent>
    </Card>
  )
}
