"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[]
  /** 视觉变体：card（默认卡片）/ widget（悬浮球内嵌，无边框，撑满容器） */
  variant?: "card" | "widget"
}

/**
 * AI 聊天面板
 *
 * 通用 AI 对话组件，可嵌入任何页面。
 * V2 增强：
 * - 流式响应（SSE）逐 token 渲染
 * - Markdown 渲染（代码块、表格、列表）
 * - 复制按钮
 * - 停止生成按钮
 * - 清除对话按钮
 * - 建议提示词
 * - aria-live 无障碍
 * - 对话历史持久化（localStorage，防抖写入）
 */
export function AiChatPanel({
  systemPrompt,
  contextMessage,
  placeholder,
  title,
  maxMessages = 50,
  suggestedPrompts,
  variant = "card",
}: 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 isWidget = variant === "widget"

  // 自动滚动到底部
  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

      // 上下文信息合并到 systemPrompt 发送给 AI，用户气泡只显示真实输入
      const fullSystemPrompt = contextMessage
        ? `${systemPrompt ?? ""}\n\n[Page Context]\n${contextMessage}`.trim()
        : systemPrompt

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

      setInput("")
      await send(requestMessages, { systemPrompt: fullSystemPrompt })
    },
    [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()
      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"),
  ]

  // widget 变体：无边框、撑满容器、消息区自适应高度
  if (isWidget) {
    return (
      <div className="flex h-full flex-col">
        {error ? (
          <div
            className="mx-3 mt-3 rounded-md border border-destructive/30 bg-destructive/5 p-3 text-sm text-destructive"
            role="alert"
          >
            {error}
          </div>
        ) : null}

        {messages.length > 0 ? (
          <div
            ref={scrollRef}
            className="flex-1 overflow-y-auto px-4 py-4"
            aria-live="polite"
            aria-relevant="additions text"
          >
            <div className="space-y-4">
              {messages.map((message, index) => (
                <div
                  key={index}
                  className={cn(
                    "flex gap-2.5",
                    message.role === "user" ? "justify-end" : "justify-start"
                  )}
                >
                  {message.role === "assistant" ? (
                    <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-primary to-primary/80 text-primary-foreground">
                      <Bot className="h-4 w-4" />
                    </span>
                  ) : (
                    <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground">
                      <User className="h-4 w-4" />
                    </span>
                  )}
                  <div
                    className={cn(
                      "rounded-2xl px-3.5 py-2 text-sm max-w-[80%]",
                      message.role === "user"
                        ? "bg-primary text-primary-foreground rounded-tr-sm"
                        : "bg-muted rounded-tl-sm"
                    )}
                  >
                    {message.role === "assistant" ? (
                      <AiMarkdownRenderer content={message.content} />
                    ) : (
                      <p className="whitespace-pre-wrap">{message.content}</p>
                    )}
                  </div>
                </div>
              ))}
              {streaming ? (
                <div className="flex gap-2.5 justify-start">
                  <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-gradient-to-br from-primary to-primary/80 text-primary-foreground">
                    <Bot className="h-4 w-4" />
                  </span>
                  <div className="rounded-2xl rounded-tl-sm px-3.5 py-2 text-sm bg-muted">
                    <span className="inline-flex gap-1">
                      <span className="h-1.5 w-1.5 animate-bounce rounded-full bg-muted-foreground/60 [animation-delay:-0.3s]" />
                      <span className="h-1.5 w-1.5 animate-bounce rounded-full bg-muted-foreground/60 [animation-delay:-0.15s]" />
                      <span className="h-1.5 w-1.5 animate-bounce rounded-full bg-muted-foreground/60" />
                    </span>
                  </div>
                </div>
              ) : null}
            </div>
          </div>
        ) : (
          <div className="flex flex-1 flex-col items-center justify-center px-6 py-8">
            <span className="flex h-14 w-14 items-center justify-center rounded-full bg-gradient-to-br from-primary to-primary/80 text-primary-foreground shadow-md mb-3">
              <Sparkles className="h-7 w-7" />
            </span>
            <p className="text-base font-medium mb-1">{t("widget.welcome")}</p>
            <p className="text-sm text-muted-foreground mb-4 text-center">{t("widget.welcomeDesc")}</p>
            <div className="flex flex-wrap gap-2 justify-center max-w-sm">
              {defaultSuggestedPrompts.map((prompt, index) => (
                <Button
                  key={index}
                  type="button"
                  variant="outline"
                  size="sm"
                  className="text-xs rounded-full"
                  onClick={() => handleSuggestedPrompt(prompt)}
                >
                  {prompt}
                </Button>
              ))}
            </div>
          </div>
        )}

        <div className="border-t p-3">
          <div className="flex items-end gap-2">
            <Textarea
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={handleKeyDown}
              placeholder={placeholder ?? t("chat.placeholder")}
              className="min-h-10 max-h-32 resize-none rounded-2xl"
              disabled={streaming || messages.length >= maxMessages}
              aria-label={t("chat.inputLabel")}
            />
            {streaming ? (
              <Button
                type="button"
                size="icon"
                variant="destructive"
                className="rounded-full shrink-0"
                onClick={stop}
                aria-label={t("chat.stopGeneration")}
              >
                <Square className="h-4 w-4" />
              </Button>
            ) : (
              <Button
                type="button"
                size="icon"
                className="rounded-full shrink-0"
                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 mt-2">
              {t("chat.maxReached")}
            </p>
          ) : null}
        </div>
      </div>
    )
  }

  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>
  )
}
