"use client"

import { useState, useEffect } from "react"
import { useForm, type SubmitHandler } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
import { Plus, Trash2, GripVertical } from "lucide-react"
import { useRouter } from "next/navigation"

import { Button } from "@/shared/components/ui/button"
import { Checkbox } from "@/shared/components/ui/checkbox"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/shared/components/ui/dialog"
import {
  Form,
  FormLabel,
} from "@/shared/components/ui/form"
import { Input } from "@/shared/components/ui/input"
import { ScrollArea } from "@/shared/components/ui/scroll-area"
import { SelectField } from "@/shared/components/form-fields/select-field"
import { TextareaField } from "@/shared/components/form-fields/textarea-field"
import { BaseQuestionSchema } from "../schema"
import { createQuestionAction, getKnowledgePointOptionsAction, updateQuestionAction } from "../actions"
import { toast } from "sonner"
import { Question } from "../types"
import { useActionQuery } from "@/shared/hooks/use-action-query"

const QuestionFormSchema = BaseQuestionSchema.extend({
  difficulty: z.number().min(1).max(5),
  content: z.string().min(1, "Question content is required"),
  options: z
    .array(
      z.object({
        label: z.string(),
        value: z.string(),
        isCorrect: z.boolean().default(false),
      })
    )
    .optional(),
})

type QuestionFormValues = z.input<typeof QuestionFormSchema>

interface CreateQuestionDialogProps {
  open: boolean
  onOpenChange: (open: boolean) => void
  initialData?: Question | null
  defaultKnowledgePointIds?: string[]
  defaultContent?: string
  defaultType?: "single_choice" | "multiple_choice" | "text" | "judgment" | "composite"
}

function getInitialTextFromContent(content: unknown) {
  if (typeof content === "string") return content
  if (content && typeof content === "object") {
    const text = (content as { text?: unknown }).text
    if (typeof text === "string") return text
  }
  if (content == null) return ""
  return JSON.stringify(content)
}

function getInitialOptionsFromContent(content: unknown) {
  if (!content || typeof content !== "object") return undefined
  const rawOptions = (content as { options?: unknown }).options
  if (!Array.isArray(rawOptions)) return undefined

  const mapped = rawOptions
    .map((opt) => {
      if (!opt || typeof opt !== "object") return null
      const id =
        (opt as { id?: unknown; value?: unknown }).id ?? (opt as { value?: unknown }).value
      const text =
        (opt as { text?: unknown; label?: unknown }).text ??
        (opt as { label?: unknown }).label
      const isCorrect = (opt as { isCorrect?: unknown }).isCorrect
      return {
        value: typeof id === "string" ? id : "",
        label: typeof text === "string" ? text : "",
        isCorrect: typeof isCorrect === "boolean" ? isCorrect : false,
      }
    })
    .filter((v): v is NonNullable<typeof v> => Boolean(v && v.value && v.label))

  return mapped.length > 0 ? mapped : undefined
}

export function CreateQuestionDialog({ 
  open, 
  onOpenChange, 
  initialData,
  defaultKnowledgePointIds = [],
  defaultContent = "",
  defaultType = "single_choice"
}: CreateQuestionDialogProps) {
  const router = useRouter()
  const [isPending, setIsPending] = useState(false)
  const isEdit = !!initialData
  const [knowledgePointQuery, setKnowledgePointQuery] = useState("")
  const [selectedKnowledgePointIds, setSelectedKnowledgePointIds] = useState<string[]>([])

  const { data: knowledgePointOptionsData, loading: isLoadingKnowledgePoints } = useActionQuery(
    () => getKnowledgePointOptionsAction(),
    { deps: [open], enabled: open, errorMessage: "Failed to load knowledge points" }
  )
  const knowledgePointOptions = knowledgePointOptionsData ?? []

  const form = useForm<QuestionFormValues>({
    resolver: zodResolver(QuestionFormSchema),
    defaultValues: {
      type: initialData?.type || defaultType,
      difficulty: initialData?.difficulty || 1,
      content: getInitialTextFromContent(initialData?.content) || defaultContent,
      options:
        getInitialOptionsFromContent(initialData?.content) ?? [
          { label: "Option A", value: "A", isCorrect: true },
          { label: "Option B", value: "B", isCorrect: false },
        ],
    },
  })

  useEffect(() => {
    if (initialData) {
      form.reset({
        type: initialData.type,
        difficulty: initialData.difficulty,
        content: getInitialTextFromContent(initialData.content),
        options:
          getInitialOptionsFromContent(initialData.content) ?? [
            { label: "Option A", value: "A", isCorrect: true },
            { label: "Option B", value: "B", isCorrect: false },
          ],
      })
    } else {
      form.reset({
        type: defaultType,
        difficulty: 1,
        content: defaultContent,
        options: [
          { label: "Option A", value: "A", isCorrect: true },
          { label: "Option B", value: "B", isCorrect: false },
        ],
      })
    }
  }, [initialData, form, open, defaultContent, defaultType])

  useEffect(() => {
    if (!open) return
    if (initialData) {
      const nextIds = initialData.knowledgePoints.map((kp) => kp.id)
      setSelectedKnowledgePointIds((prev) => {
        if (prev.length === nextIds.length && prev.every((id, idx) => id === nextIds[idx])) {
          return prev
        }
        return nextIds
      })
      return
    }
    setSelectedKnowledgePointIds((prev) => {
      if (
        prev.length === defaultKnowledgePointIds.length &&
        prev.every((id, idx) => id === defaultKnowledgePointIds[idx])
      ) {
        return prev
      }
      return defaultKnowledgePointIds
    })
  }, [open, initialData, defaultKnowledgePointIds])

  const questionType = form.watch("type")
  const filteredKnowledgePoints = knowledgePointOptions.filter((kp) => {
    const query = knowledgePointQuery.trim().toLowerCase()
    if (!query) return true
    const fullLabel = [
      kp.textbookTitle,
      kp.chapterTitle,
      kp.name,
      kp.subject,
      kp.grade,
    ]
      .filter(Boolean)
      .join(" ")
      .toLowerCase()
    return fullLabel.includes(query)
  })

  const buildContent = (data: QuestionFormValues) => {
    const text = data.content.trim()
    if (data.type === "single_choice" || data.type === "multiple_choice") {
      const rawOptions = (data.options ?? []).filter((o) => o.label.trim().length > 0)
      const base = rawOptions.map((o) => ({
        id: o.value,
        text: o.label.trim(),
        isCorrect: o.isCorrect,
      }))

      if (base.length === 0) return { text }

      if (data.type === "single_choice") {
        let selectedIndex = base.findIndex((o) => o.isCorrect)
        if (selectedIndex === -1) selectedIndex = 0
        return {
          text,
          options: base.map((o, idx) => ({ ...o, isCorrect: idx === selectedIndex })),
        }
      }

      const hasCorrect = base.some((o) => o.isCorrect)
      const options = hasCorrect ? base : [{ ...base[0], isCorrect: true }, ...base.slice(1)]
      return { text, options }
    }

    return { text }
  }

  const onSubmit: SubmitHandler<QuestionFormValues> = async (data) => {
    setIsPending(true)
    try {
      if (isEdit && !initialData?.id) {
        toast.error("Missing question id")
        return
      }
      const payload = {
        ...(isEdit && initialData ? { id: initialData.id } : {}),
        type: data.type,
        difficulty: data.difficulty,
        content: buildContent(data),
        knowledgePointIds: selectedKnowledgePointIds,
      }
      const fd = new FormData()
      fd.set("json", JSON.stringify(payload))
      const res = isEdit
        ? await updateQuestionAction(undefined, fd)
        : await createQuestionAction(undefined, fd)
      if (res.success) {
        toast.success(isEdit ? "Updated question" : "Created question")
        onOpenChange(false)
        router.refresh()
        if (!isEdit) {
          form.reset()
        }
      } else {
        toast.error(res.message || "Operation failed")
      }
    } catch (e) {
      console.error("Failed to submit question", e)
      toast.error("Unexpected error")
    } finally {
      setIsPending(false)
    }
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[600px] max-h-[90vh] overflow-y-auto">
        <DialogHeader>
          <DialogTitle>{isEdit ? "Edit Question" : "Create New Question"}</DialogTitle>
          <DialogDescription>
            {isEdit ? "Update question details." : "Add a new question to the bank. Fill in the details below."}
          </DialogDescription>
        </DialogHeader>
        
        <Form {...form}>
          <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
            <div className="grid grid-cols-2 gap-4">
              <SelectField
                control={form.control}
                name="type"
                label="Question Type"
                placeholder="Select type"
                options={[
                  { value: "single_choice", label: "Single Choice" },
                  { value: "multiple_choice", label: "Multiple Choice" },
                  { value: "judgment", label: "True/False" },
                  { value: "text", label: "Short Answer" },
                  { value: "composite", label: "Composite" },
                ]}
              />
              <SelectField
                control={form.control}
                name="difficulty"
                label="Difficulty (1-5)"
                placeholder="Select difficulty"
                toSelectValue={(v) => String(v)}
                fromSelectValue={(val) => {
                  const n = parseInt(val, 10)
                  return Number.isFinite(n) ? n : 1
                }}
                options={[1, 2, 3, 4, 5].map((level) => ({
                  value: String(level),
                  label: `${level} - ${level === 1 ? "Easy" : level === 5 ? "Hard" : "Medium"}`,
                }))}
              />
            </div>

            <TextareaField
              control={form.control}
              name="content"
              label="Question Content"
              placeholder="Enter the question text here..."
              description="Supports basic text. Rich text editor coming soon."
              textareaClassName="min-h-[100px]"
            />

            <div className="space-y-3">
              <div className="flex items-center justify-between">
                <FormLabel>Knowledge Points</FormLabel>
                <span className="text-xs text-muted-foreground">
                  {selectedKnowledgePointIds.length > 0 ? `${selectedKnowledgePointIds.length} selected` : "Optional"}
                </span>
              </div>
              <Input
                placeholder="Search knowledge points..."
                value={knowledgePointQuery}
                onChange={(e) => setKnowledgePointQuery(e.target.value)}
              />
              <div className="rounded-md border">
                <ScrollArea className="h-48">
                  {isLoadingKnowledgePoints ? (
                    <div className="p-3 text-sm text-muted-foreground">Loading...</div>
                  ) : filteredKnowledgePoints.length === 0 ? (
                    <div className="p-3 text-sm text-muted-foreground">No knowledge points found.</div>
                  ) : (
                    <div className="space-y-1 p-2">
                      {filteredKnowledgePoints.map((kp) => {
                        const labelParts = [
                          kp.textbookTitle,
                          kp.chapterTitle,
                          kp.name,
                        ].filter(Boolean)
                        const label = labelParts.join(" · ")
                        return (
                          <label key={kp.id} className="flex items-center gap-2 rounded-md px-2 py-1 hover:bg-muted/50">
                            <Checkbox
                              checked={selectedKnowledgePointIds.includes(kp.id)}
                              onCheckedChange={(checked) => {
                                const isChecked = checked === true
                                setSelectedKnowledgePointIds((prev) => {
                                  if (isChecked) {
                                    if (prev.includes(kp.id)) return prev
                                    return [...prev, kp.id]
                                  }
                                  return prev.filter((id) => id !== kp.id)
                                })
                              }}
                            />
                            <span className="text-sm">{label}</span>
                          </label>
                        )
                      })}
                    </div>
                  )}
                </ScrollArea>
              </div>
            </div>

            {(questionType === "single_choice" || questionType === "multiple_choice") && (
              <div className="space-y-4">
                <div className="flex items-center justify-between">
                  <FormLabel>Options</FormLabel>
                  <Button
                    type="button"
                    variant="outline"
                    size="sm"
                    onClick={() => {
                      const currentOptions = form.getValues("options") || []
                      const nextIndex = currentOptions.length
                      const nextChar = nextIndex < 26 ? String.fromCharCode(65 + nextIndex) : String(nextIndex + 1)
                      form.setValue("options", [
                        ...currentOptions,
                        {
                          label: `Option ${nextChar}`,
                          value: nextChar,
                          isCorrect: false,
                        },
                      ])
                    }}
                  >
                    <Plus className="mr-2 h-3 w-3" /> Add Option
                  </Button>
                </div>
                
                <div className="space-y-2">
                  {form.watch("options")?.map((option, index) => (
                    <div key={option.value || `option-${index}`} className="flex items-center gap-2">
                      <div className="flex h-8 w-8 items-center justify-center text-muted-foreground">
                        <GripVertical className="h-4 w-4" />
                      </div>
                      <Checkbox
                        checked={option.isCorrect}
                        onCheckedChange={(checked) => {
                          const next = [...(form.getValues("options") || [])]
                          if (!next[index]) return

                          const isChecked = checked === true
                          if (questionType === "single_choice" && isChecked) {
                            for (let i = 0; i < next.length; i++) next[i].isCorrect = i === index
                          } else {
                            next[index].isCorrect = isChecked
                          }
                          form.setValue("options", next)
                        }}
                        aria-label="Mark correct"
                      />
                      <Input
                        value={option.label}
                        onChange={(e) => {
                          const next = [...(form.getValues("options") || [])]
                          if (!next[index]) return
                          next[index].label = e.target.value
                          form.setValue("options", next)
                        }}
                        placeholder={`Option ${index + 1}`}
                      />
                      <Button
                        type="button"
                        variant="ghost"
                        size="icon"
                        className="text-destructive hover:text-destructive/90"
                        onClick={() => {
                          const next = [...(form.getValues("options") || [])]
                          next.splice(index, 1)
                          form.setValue("options", next)
                        }}
                      >
                        <Trash2 className="h-4 w-4" />
                      </Button>
                    </div>
                  ))}
                </div>
              </div>
            )}

            <DialogFooter>
              <Button type="button" variant="outline" onClick={() => onOpenChange(false)}>
                Cancel
              </Button>
              <Button type="submit" disabled={isPending}>
                {isPending ? (isEdit ? "Updating..." : "Creating...") : (isEdit ? "Update Question" : "Create Question")}
              </Button>
            </DialogFooter>
          </form>
        </Form>
      </DialogContent>
    </Dialog>
  )
}
