"use client"

import { useEffect, useRef, useState } from "react"
import { Send, Loader2, Copy, RefreshCw, Trash2, Plus, MessageSquare, X, Sparkles } from "lucide-react"
import { toast } from "sonner"
import { Button } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea"
import { cn } from "@/lib/utils"
import { useAISettings } from "./ai-settings-provider"
import { Markdown } from "./markdown"
import { requestOpenAICompatible } from "@/lib/ai/client"
import { validateForRequest } from "@/lib/ai/settings"
import { buildChatSystemPrompt } from "@/lib/ai/prompts"
import {
  addMessage,
  clearMessages,
  createConversation,
  deleteLastAssistantMessage,
  fetchMessages,
  getLatestConversation,
  type AIConversation,
} from "@/lib/ai/conversations"
import type { ChatMessage } from "@/lib/ai/types"
import type { KnowledgeItem } from "@/lib/types"

type UIMessage = { role: "user" | "assistant"; content: string }

export function AIChatPanel({ item }: { item: KnowledgeItem }) {
  const { settings } = useAISettings()
  const [conversation, setConversation] = useState<AIConversation | null>(null)
  const [messages, setMessages] = useState<UIMessage[]>([])
  const [input, setInput] = useState("")
  const [loading, setLoading] = useState(false)
  const [booting, setBooting] = useState(true)
  const controllerRef = useRef<AbortController | null>(null)
  const scrollRef = useRef<HTMLDivElement>(null)

  // load latest conversation + messages on mount / item change
  useEffect(() => {
    let active = true
    setBooting(true)
    setMessages([])
    setConversation(null)
    ;(async () => {
      try {
        const conv = await getLatestConversation(item.id)
        if (!active) return
        if (conv) {
          setConversation(conv)
          const rows = await fetchMessages(conv.id)
          if (!active) return
          setMessages(rows.filter((r) => r.role !== "system").map((r) => ({ role: r.role as "user" | "assistant", content: r.content })))
        }
      } catch (e) {
        console.log("[v0] load conversation error:", e)
      } finally {
        if (active) setBooting(false)
      }
    })()
    return () => {
      active = false
      controllerRef.current?.abort()
    }
  }, [item.id])

  useEffect(() => {
    scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight, behavior: "smooth" })
  }, [messages, loading])

  async function ensureConversation(): Promise<AIConversation> {
    if (conversation) return conversation
    const conv = await createConversation(item.id, item.title)
    setConversation(conv)
    return conv
  }

  async function runCompletion(history: UIMessage[]): Promise<string> {
    const chatMessages: ChatMessage[] = history.map((m) => ({ role: m.role, content: m.content }))
    const ac = new AbortController()
    controllerRef.current = ac
    return requestOpenAICompatible({
      baseUrl: settings.baseUrl,
      apiKey: settings.apiKey,
      model: settings.model,
      systemPrompt: buildChatSystemPrompt(item),
      messages: chatMessages,
      temperature: settings.temperature,
      maxTokens: settings.maxTokens,
      signal: ac.signal,
    })
  }

  async function handleSend() {
    const err = validateForRequest(settings)
    if (err) {
      toast.error(err)
      return
    }
    const text = input.trim()
    if (!text || loading) return

    const userMsg: UIMessage = { role: "user", content: text }
    const next = [...messages, userMsg]
    setMessages(next)
    setInput("")
    setLoading(true)
    try {
      const conv = await ensureConversation()
      await addMessage(conv.id, "user", text)
      const reply = await runCompletion(next)
      setMessages((prev) => [...prev, { role: "assistant", content: reply }])
      await addMessage(conv.id, "assistant", reply)
    } catch (e) {
      if ((e as Error).name === "AbortError") {
        toast.message("已取消回复")
        setMessages((prev) => prev.slice(0, -1)) // remove the user msg we optimistically added? keep it instead
        return
      }
      toast.error((e as Error).message)
      setMessages((prev) => [...prev, { role: "assistant", content: `[出错] ${(e as Error).message}` }])
    } finally {
      setLoading(false)
      controllerRef.current = null
    }
  }

  async function handleRegenerate() {
    if (loading) return
    // find last user message
    const lastUserIdx = [...messages].reverse().findIndex((m) => m.role === "user")
    if (lastUserIdx === -1) return
    const historyEnd = messages.length - lastUserIdx // index just after last user message
    const history = messages.slice(0, historyEnd)
    setMessages(history)
    setLoading(true)
    try {
      const conv = await ensureConversation()
      await deleteLastAssistantMessage(conv.id)
      const reply = await runCompletion(history)
      setMessages((prev) => [...prev, { role: "assistant", content: reply }])
      await addMessage(conv.id, "assistant", reply)
    } catch (e) {
      if ((e as Error).name === "AbortError") return
      toast.error((e as Error).message)
    } finally {
      setLoading(false)
      controllerRef.current = null
    }
  }

  async function handleNewConversation() {
    controllerRef.current?.abort()
    try {
      const conv = await createConversation(item.id, item.title)
      setConversation(conv)
      setMessages([])
      toast.success("已新建会话")
    } catch (e) {
      toast.error("新建会话失败")
      console.log("[v0] new conversation error:", e)
    }
  }

  async function handleClear() {
    if (!conversation) {
      setMessages([])
      return
    }
    try {
      await clearMessages(conversation.id)
      setMessages([])
      toast.success("已清空当前会话")
    } catch (e) {
      toast.error("清空失败")
      console.log("[v0] clear error:", e)
    }
  }

  function copyMessage(content: string) {
    navigator.clipboard.writeText(content)
    toast.success("已复制")
  }

  const hasAssistant = messages.some((m) => m.role === "assistant")

  return (
    <div className="flex flex-col gap-3 rounded-xl border border-border bg-card/40 p-3">
      <div className="flex items-center justify-between">
        <h4 className="flex items-center gap-1.5 font-mono text-xs uppercase tracking-wide text-muted-foreground">
          <Sparkles className="size-3.5 text-primary" />
          AI 追问
        </h4>
        <div className="flex gap-1">
          <Button variant="ghost" size="sm" onClick={handleNewConversation} className="h-7 gap-1 px-2 text-xs">
            <Plus className="size-3.5" />
            新建
          </Button>
          <Button
            variant="ghost"
            size="sm"
            onClick={handleClear}
            disabled={messages.length === 0}
            className="h-7 gap-1 px-2 text-xs"
          >
            <Trash2 className="size-3.5" />
            清空
          </Button>
        </div>
      </div>

      <div ref={scrollRef} className="flex max-h-72 flex-col gap-3 overflow-y-auto">
        {booting ? (
          <div className="flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground">
            <Loader2 className="size-4 animate-spin" />
            加载会话...
          </div>
        ) : messages.length === 0 ? (
          <div className="flex flex-col items-center justify-center gap-2 py-6 text-center text-sm text-muted-foreground">
            <MessageSquare className="size-6" />
            针对「{item.title}」向 AI 提问，开始复习对话
          </div>
        ) : (
          messages.map((m, i) => (
            <div key={i} className={cn("flex", m.role === "user" ? "justify-end" : "justify-start")}>
              <div
                className={cn(
                  "group relative max-w-[85%] rounded-lg px-3 py-2 text-sm leading-relaxed",
                  m.role === "user"
                    ? "bg-primary/15 text-foreground"
                    : "border border-border bg-secondary/50 text-foreground",
                )}
              >
                {m.role === "assistant" ? (
                  <Markdown content={m.content} />
                ) : (
                  <p className="whitespace-pre-wrap break-words">{m.content}</p>
                )}
                {m.role === "assistant" && (
                  <button
                    type="button"
                    onClick={() => copyMessage(m.content)}
                    aria-label="复制回复"
                    className="absolute -right-2 -top-2 hidden rounded-md border border-border bg-background p-1 text-muted-foreground hover:text-foreground group-hover:block"
                  >
                    <Copy className="size-3" />
                  </button>
                )}
              </div>
            </div>
          ))
        )}
        {loading && (
          <div className="flex justify-start">
            <div className="flex items-center gap-2 rounded-lg border border-border bg-secondary/50 px-3 py-2 text-sm text-muted-foreground">
              <Loader2 className="size-4 animate-spin" />
              AI 正在思考...
            </div>
          </div>
        )}
      </div>

      {hasAssistant && !loading && (
        <div>
          <Button variant="ghost" size="sm" onClick={handleRegenerate} className="h-7 gap-1 px-2 text-xs">
            <RefreshCw className="size-3.5" />
            重新生成
          </Button>
        </div>
      )}

      <div className="flex items-end gap-2">
        <Textarea
          value={input}
          onChange={(e) => setInput(e.target.value)}
          onKeyDown={(e) => {
            if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
              e.preventDefault()
              handleSend()
            }
          }}
          placeholder="输入你的问题... (Ctrl/Cmd + Enter 发送)"
          className="min-h-10 flex-1 bg-input/60 text-sm"
        />
        {loading ? (
          <Button variant="outline" size="icon" onClick={() => controllerRef.current?.abort()} aria-label="取消">
            <X className="size-4" />
          </Button>
        ) : (
          <Button size="icon" onClick={handleSend} disabled={!input.trim()} aria-label="发送">
            <Send className="size-4" />
          </Button>
        )}
      </div>
    </div>
  )
}
