"use client"

import { useEffect, useRef, useState } from "react"
import type { UseFormReturn } from "react-hook-form"
import { toast } from "sonner"
import PQueue from "p-queue"
import { createId } from "@paralleldrive/cuid2"

import { previewAiExamAction, regenerateAiQuestionAction, type AiPreviewData, type AiRewriteQuestionData } from "../actions"
import type { ExamNode } from "../components/assembly/selected-question-list"
import {
  type ExamFormValues,
  type PreviewSnapshotMeta,
  type PreviewBackgroundTask,
  previewTaskStorageKey,
} from "../components/exam-form-types"
import {
  buildPreviewNodes,
  parseEditableContent,
  flattenPreviewQuestions,
  findPreviewQuestionNode,
  updatePreviewQuestionNodeInList,
  buildPreviewSignature,
  buildPreviewPayload,
  buildPreviewRequestData,
} from "../components/exam-preview-utils"

export function useExamPreview(form: UseFormReturn<ExamFormValues>) {
  const [previewOpen, setPreviewOpen] = useState(false)
  const [previewLoading, setPreviewLoading] = useState(false)
  const [previewNodes, setPreviewNodes] = useState<ExamNode[]>([])
  const [previewTitle, setPreviewTitle] = useState("")
  const [previewRawOutput, setPreviewRawOutput] = useState("")
  const [previewSignature, setPreviewSignature] = useState("")
  const [previewMeta, setPreviewMeta] = useState<PreviewSnapshotMeta | null>(null)
  const [previewTasks, setPreviewTasks] = useState<PreviewBackgroundTask[]>([])
  const [selectedQuestionId, setSelectedQuestionId] = useState<string>("")
  const [rewriteInstruction, setRewriteInstruction] = useState("")
  const [rewritingQuestion, setRewritingQuestion] = useState(false)

  const previewQueueRef = useRef<PQueue | null>(null)
  if (!previewQueueRef.current) {
    previewQueueRef.current = new PQueue({ concurrency: 3 })
  }
  const previewQueue = previewQueueRef.current

  const persistPreviewTasks = (tasks: PreviewBackgroundTask[]) => {
    try {
      window.localStorage.setItem(previewTaskStorageKey, JSON.stringify(tasks.slice(0, 20)))
    } catch (error) {
      console.error(error)
    }
  }

  useEffect(() => {
    try {
      const raw = window.localStorage.getItem(previewTaskStorageKey)
      if (!raw) return
      const parsed = JSON.parse(raw) as PreviewBackgroundTask[]
      if (!Array.isArray(parsed)) return
      const restoredTasks = parsed
        .filter((task) => task && typeof task.id === "string")
        .map((task) => {
          if (task.status === "queued" || task.status === "running") {
            return {
              ...task,
              status: "failed" as const,
              message: "页面刷新后任务已中断，请重新生成",
            }
          }
          return task
        })
      setPreviewTasks(restoredTasks)
      if (restoredTasks.length > 0) {
        form.setValue("mode", "ai")
      }
    } catch (error) {
      console.error(error)
      setPreviewTasks([])
    }
  }, [form])

  useEffect(() => {
    return () => {
      previewQueue.clear()
    }
  }, [previewQueue])

  useEffect(() => {
    persistPreviewTasks(previewTasks)
  }, [previewTasks])

  const updatePreviewQuestionNode = (questionId: string, updater: (node: ExamNode) => ExamNode) => {
    setPreviewNodes((prev) => updatePreviewQuestionNodeInList(questionId, prev, updater))
  }

  const updateSelectedQuestionFromAi = (questionId: string, data: AiRewriteQuestionData) => {
    updatePreviewQuestionNode(questionId, (node) => {
      if (!node.question) return node
      return {
        ...node,
        score: data.score,
        question: {
          ...node.question,
          type: data.type,
          difficulty: data.difficulty,
          content: data.content,
          updatedAt: new Date(),
        },
      }
    })
  }

  const applyPreviewResult = (input: { data: AiPreviewData; signature: string; meta: PreviewSnapshotMeta }) => {
    setPreviewTitle(input.data.title)
    const nextNodes = buildPreviewNodes(input.data)
    setPreviewNodes(nextNodes)
    const firstQuestion = flattenPreviewQuestions(nextNodes)[0]
    setSelectedQuestionId(firstQuestion?.node.questionId ?? "")
    setPreviewRawOutput(input.data.rawOutput ?? "")
    setPreviewSignature(input.signature)
    setPreviewMeta(input.meta)
    setRewriteInstruction("")
    setPreviewOpen(true)
  }

  const handlePreview = async () => {
    const values = form.getValues()
    const requestData = buildPreviewRequestData(values)
    if (!requestData) {
      toast.error("Please paste the full exam text first")
      return
    }

    setPreviewOpen(false)
    setPreviewLoading(true)
    setPreviewNodes([])
    setPreviewRawOutput("")
    setPreviewSignature("")
    setSelectedQuestionId("")
    setRewriteInstruction("")
    try {
      const result = await previewAiExamAction(null, requestData.formData)
      if (result.success && result.data) {
        applyPreviewResult({
          data: result.data,
          signature: requestData.signature,
          meta: requestData.meta,
        })
      } else {
        toast.error(result.message || "Failed to generate preview")
      }
    } catch {
      toast.error("Failed to generate preview")
    } finally {
      setPreviewLoading(false)
    }
  }

  const handleBackgroundPreview = () => {
    const values = form.getValues()
    const requestData = buildPreviewRequestData(values)
    if (!requestData) {
      toast.error("Please paste the full exam text first")
      return
    }
    const taskId = createId()
    const taskTitle = values.title?.trim() || "未命名试卷"
    setPreviewTasks((prev) => {
      const next = [{ id: taskId, createdAt: Date.now(), status: "queued" as const, title: taskTitle, signature: requestData.signature }, ...prev]
      persistPreviewTasks(next)
      return next
    })
    toast.success("已加入后台队列，可继续编辑页面")
    void previewQueue.add(async () => {
      setPreviewTasks((prev) => prev.map((task) => task.id === taskId
        ? { ...task, status: "running" }
        : task))
      try {
        const result = await previewAiExamAction(null, requestData.formData)
        const data = result.data
        if (result.success && data) {
          const nextNodes = buildPreviewNodes(data)
          setPreviewTasks((prev) => prev.map((task) => task.id === taskId
            ? {
              ...task,
              status: "success",
              result: {
                title: data.title,
                nodes: nextNodes,
                rawOutput: data.rawOutput ?? "",
                meta: requestData.meta,
                formValues: { title: values.title, subject: values.subject, grade: values.grade, difficulty: values.difficulty, totalScore: values.totalScore, durationMin: values.durationMin, aiSourceText: values.aiSourceText, aiQuestionCount: values.aiQuestionCount, aiProviderId: values.aiProviderId },
              },
            }
            : task))
          toast.success(`后台生成完成：${taskTitle}`)
          return
        }
        setPreviewTasks((prev) => prev.map((task) => task.id === taskId
          ? { ...task, status: "failed", message: result.message || "Failed to generate preview" }
          : task))
        toast.error(`后台生成失败：${taskTitle}`)
      } catch {
        setPreviewTasks((prev) => prev.map((task) => task.id === taskId
          ? { ...task, status: "failed", message: "Failed to generate preview" }
          : task))
        toast.error(`后台生成失败：${taskTitle}`)
      }
    })
  }

  const handleOpenPreviewTask = (taskId: string) => {
    const task = previewTasks.find((item) => item.id === taskId)
    if (!task || task.status !== "success" || !task.result) return
    const tv = task.result.formValues
    const fields = ["title", "subject", "grade", "difficulty", "totalScore", "durationMin", "aiSourceText", "aiQuestionCount", "aiProviderId"] as const
    fields.forEach((key) => {
      if (typeof tv[key] !== "undefined") form.setValue(key, tv[key])
    })
    setPreviewTitle(task.result.title)
    setPreviewNodes(task.result.nodes)
    setPreviewRawOutput(task.result.rawOutput)
    setPreviewSignature(task.signature)
    setPreviewMeta(task.result.meta)
    const firstQuestion = flattenPreviewQuestions(task.result.nodes)[0]
    setSelectedQuestionId(firstQuestion?.node.questionId ?? "")
    setRewriteInstruction("")
    setPreviewOpen(true)
  }

  const handleRewriteSelectedQuestion = async () => {
    if (!selectedQuestionId) {
      toast.error("请先选择一个题目")
      return
    }
    const selected = findPreviewQuestionNode(previewNodes, selectedQuestionId)
    if (!selected?.question) {
      toast.error("未找到选中的题目")
      return
    }
    const instruction = rewriteInstruction.trim()
    if (!instruction) {
      toast.error("请输入重写指令")
      return
    }
    setRewritingQuestion(true)
    try {
      const content = parseEditableContent(selected.question.content)
      const questionPayload = {
        type: selected.question.type,
        difficulty: selected.question.difficulty ?? 3,
        score: selected.score ?? 0,
        content: {
          text: content.text,
          options: content.options.map((opt) => ({
            id: opt.id, text: opt.text, isCorrect: opt.isCorrect,
          })),
          subQuestions: content.subQuestions.map((item) => ({
            id: item.id, text: item.text, answer: item.answer, score: item.score,
          })),
        },
      }
      const formData = new FormData()
      formData.append("instruction", instruction)
      formData.append("questionJson", JSON.stringify(questionPayload))
      const providerId = form.getValues("aiProviderId")
      const sourceText = form.getValues("aiSourceText")
      if (providerId) formData.append("aiProviderId", providerId)
      if (sourceText) formData.append("sourceText", sourceText)
      const result = await regenerateAiQuestionAction(null, formData)
      if (!result.success || !result.data) {
        toast.error(result.message || "AI 重写失败")
        return
      }
      updateSelectedQuestionFromAi(selectedQuestionId, result.data)
      setRewriteInstruction("")
      toast.success("题目已按指令重写")
    } catch {
      toast.error("AI 重写失败")
    } finally {
      setRewritingQuestion(false)
    }
  }

  return {
    previewOpen, setPreviewOpen, previewLoading, previewNodes, setPreviewNodes,
    previewTitle, previewRawOutput, previewSignature, previewMeta, previewTasks,
    selectedQuestionId, setSelectedQuestionId, rewriteInstruction, setRewriteInstruction,
    rewritingQuestion, buildPreviewNodes, parseEditableContent, flattenPreviewQuestions,
    findPreviewQuestionNode, updatePreviewQuestionNode, buildPreviewPayload,
    buildPreviewRequestData, buildPreviewSignature, handlePreview, handleBackgroundPreview,
    handleOpenPreviewTask, handleRewriteSelectedQuestion,
  }
}
