"use client"

import { useEffect, useMemo, useState } from "react"
import { Loader2, Sparkles, X, Database, AlertTriangle } from "lucide-react"
import { toast } from "sonner"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Textarea } from "@/components/ui/textarea"
import { Label } from "@/components/ui/label"
import { cn } from "@/lib/utils"
import { useAISettings } from "./ai-settings-provider"
import { PromptEditor } from "./prompt-editor"
import { AIResultPreview, type DraftRow } from "./ai-result-preview"
import { requestOpenAICompatible } from "@/lib/ai/client"
import { validateForRequest } from "@/lib/ai/settings"
import { BATCH_IMPORT_PROMPT } from "@/lib/ai/prompts"
import { safeParseAIJson } from "@/lib/ai/json"
import type { KnowledgeItem, KnowledgeItemInput } from "@/lib/types"

export function AIBatchImportDialog({
  open,
  onOpenChange,
  onInserted,
}: {
  open: boolean
  onOpenChange: (o: boolean) => void
  onInserted: (items: KnowledgeItem[]) => void
}) {
  const { settings } = useAISettings()
  const [rawInput, setRawInput] = useState("")
  const [customPrompt, setCustomPrompt] = useState(BATCH_IMPORT_PROMPT)
  const [loading, setLoading] = useState(false)
  const [inserting, setInserting] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const [rawResponse, setRawResponse] = useState<string | null>(null)
  const [rows, setRows] = useState<DraftRow[]>([])
  const [controller, setController] = useState<AbortController | null>(null)

  useEffect(() => {
    if (open) {
      setError(null)
      setRawResponse(null)
    }
  }, [open])

  const selectedCount = useMemo(() => rows.filter((r) => r._selected).length, [rows])

  async function handleGenerate() {
    const err = validateForRequest(settings)
    if (err) {
      toast.error(err)
      return
    }
    if (!rawInput.trim()) {
      toast.error("请先粘贴题目内容")
      return
    }
    setLoading(true)
    setError(null)
    setRawResponse(null)
    setRows([])
    const ac = new AbortController()
    setController(ac)
    try {
      const content = await requestOpenAICompatible({
        baseUrl: settings.baseUrl,
        apiKey: settings.apiKey,
        model: settings.model,
        systemPrompt: settings.systemPrompt,
        customPrompt,
        messages: [{ role: "user", content: rawInput }],
        temperature: settings.temperature,
        maxTokens: settings.maxTokens,
        signal: ac.signal,
      })
      const parsed = safeParseAIJson(content)
      if (!parsed.ok) {
        setError(parsed.error)
        setRawResponse(parsed.raw)
        return
      }
      setRows(
        parsed.items.map((it, i) => ({
          ...it,
          _id: `${Date.now()}-${i}`,
          _selected: true,
        })),
      )
      toast.success(`已生成 ${parsed.items.length} 条`)
    } catch (e) {
      if ((e as Error).name === "AbortError") {
        toast.message("已取消生成")
        return
      }
      setError((e as Error).message)
    } finally {
      setLoading(false)
      setController(null)
    }
  }

  function handleCancel() {
    controller?.abort()
  }

  async function handleInsert() {
    const selected = rows.filter((r) => r._selected)
    if (selected.length === 0) {
      toast.error("请至少勾选一条")
      return
    }
    setInserting(true)
    try {
      const { createItems } = await import("@/lib/knowledge")
      const inputs: KnowledgeItemInput[] = selected.map((r) => ({
        title: r.title,
        summary: r.summary,
        content: r.content,
        code_snippet: r.code_snippet,
        tags: r.tags,
        category: r.category,
        difficulty: r.difficulty,
        mastery: r.mastery,
        is_favorite: false,
        source_url: r.source_url,
        notes: r.notes,
      }))
      const created = await createItems(inputs)
      onInserted(created)
      toast.success(`成功插入 ${created.length} 条知识点`)
      // remove inserted rows from preview
      setRows((prev) => prev.filter((r) => !r._selected))
    } catch (e) {
      toast.error(`插入失败：${(e as Error).message}`)
      console.log("[v0] batch insert error:", e)
    } finally {
      setInserting(false)
    }
  }

  return (
    <Dialog open={open} onOpenChange={(o) => (loading ? null : onOpenChange(o))}>
      <DialogContent className="glass-panel flex max-h-[92vh] flex-col gap-0 overflow-hidden sm:max-w-3xl">
        <DialogHeader className="shrink-0">
          <DialogTitle className="flex items-center gap-2">
            <Sparkles className="size-5 text-primary" />
            AI 批量整理
          </DialogTitle>
          <DialogDescription>
            粘贴多个题目 / 面试题 / 知识点，AI 会整理成结构化数据。插入前可预览、编辑并勾选。
          </DialogDescription>
        </DialogHeader>

        <div className="grid min-w-0 flex-1 gap-4 overflow-y-auto py-3 pr-1">
          <div className="flex items-center gap-2 rounded-lg border border-border bg-muted/30 px-3 py-2 font-mono text-xs text-muted-foreground">
            <span className="text-primary">model</span> {settings.model || "—"}
            <span className="mx-1 opacity-40">|</span>
            <span className="text-primary">base</span>
            <span className="truncate">{settings.baseUrl || "—"}</span>
          </div>

          <div className="grid gap-1.5">
            <Label htmlFor="rawInput">题目内容</Label>
            <Textarea
              id="rawInput"
              value={rawInput}
              onChange={(e) => setRawInput(e.target.value)}
              placeholder={"1. 什么是闭包？\n2. Vue2 和 Vue3 的区别？\n3. Promise.all 和 Promise.race 的区别？\n4. 实现防抖函数"}
              className="min-h-28 bg-input/60 text-sm"
            />
          </div>

          <PromptEditor value={customPrompt} onChange={setCustomPrompt} rows={5} />

          <div className="flex gap-2">
            {loading ? (
              <Button variant="outline" onClick={handleCancel} className="gap-1.5">
                <X className="size-4" />
                取消生成
              </Button>
            ) : (
              <Button onClick={handleGenerate} disabled={!rawInput.trim()} className="ai-gradient gap-1.5">
                <Sparkles className="size-4" />
                生成
              </Button>
            )}
            {loading && (
              <span className="flex items-center gap-2 text-sm text-muted-foreground">
                <Loader2 className="size-4 animate-spin" />
                AI 整理中...
              </span>
            )}
          </div>

          {error && (
            <div className="neon-error grid gap-2 rounded-lg border px-3 py-2 text-sm">
              <div className="flex items-center gap-2 font-medium">
                <AlertTriangle className="size-4" />
                {error}
              </div>
              {rawResponse && (
                <div className="grid gap-1">
                  <span className="text-xs opacity-80">原始返回内容（可复制修复）：</span>
                  <Textarea readOnly value={rawResponse} className="min-h-24 bg-background/40 font-mono text-xs" />
                </div>
              )}
            </div>
          )}

          {rows.length > 0 && <AIResultPreview rows={rows} onChange={setRows} />}
        </div>

        <div className="flex shrink-0 items-center justify-between gap-2 border-t border-border pt-4">
          <p className="font-mono text-xs text-muted-foreground">所有内容确认后才会写入数据库</p>
          <div className="flex gap-2">
            <Button variant="ghost" onClick={() => onOpenChange(false)} disabled={loading || inserting}>
              关闭
            </Button>
            <Button
              onClick={handleInsert}
              disabled={selectedCount === 0 || inserting}
              className={cn("gap-1.5")}
            >
              {inserting ? <Loader2 className="size-4 animate-spin" /> : <Database className="size-4" />}
              插入选中 ({selectedCount})
            </Button>
          </div>
        </div>
      </DialogContent>
    </Dialog>
  )
}
