"use client"

import { useCallback, useMemo, useState } from "react"
import { toast } from "sonner"
import { useTranslations } from "next-intl"

import type { GradeListItem, SchoolListItem, StaffOption } from "../types"
import { createGradeAction, updateGradeAction } from "../actions"
import { Button } from "@/shared/components/ui/button"
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/shared/components/ui/dialog"
import { Input } from "@/shared/components/ui/input"
import { Label } from "@/shared/components/ui/label"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/shared/components/ui/select"
import { useActionMutation } from "@/shared/hooks/use-action-mutation"

type FormState = {
  schoolId: string
  name: string
  order: string
  gradeHeadId: string
  teachingHeadId: string
}

type FormErrors = Partial<Record<keyof FormState, string>>

type GradeFormDialogProps = {
  open: boolean
  onOpenChange: (open: boolean) => void
  editItem: GradeListItem | null
  schools: SchoolListItem[]
  staff: StaffOption[]
  grades: GradeListItem[]
  onSuccess: () => void
}

const NONE_SELECT_VALUE = "__none__"

const normalizeName = (v: string): string => v.trim().replace(/\s+/g, " ")

const parseOrder = (raw: string): number | null => {
  const v = raw.trim()
  if (!v) return 0
  const n = Number(v)
  if (!Number.isFinite(n) || !Number.isInteger(n) || n < 0) return null
  return n
}

const toFormState = (item: GradeListItem | null, fallbackSchoolId: string): FormState => ({
  schoolId: item?.school.id ?? fallbackSchoolId,
  name: item?.name ?? "",
  order: String(item?.order ?? 0),
  gradeHeadId: item?.gradeHead?.id ?? "",
  teachingHeadId: item?.teachingHead?.id ?? "",
})

/**
 * 年级创建/编辑表单对话框。
 *
 * 根据 `editItem` 是否存在自动切换模式。内部管理表单状态与客户端校验
 * （必填、长度、order 格式、同校重名检测、isDirty 检测），
 * mutation 通过 useActionMutation 统一处理 loading/toast。
 * 成功后调用 `onOpenChange(false)` 关闭对话框并触发 `onSuccess` 通知父组件刷新。
 */
export function GradeFormDialog({
  open,
  onOpenChange,
  editItem,
  schools,
  staff,
  grades,
  onSuccess,
}: GradeFormDialogProps) {
  const t = useTranslations("school")
  const isEdit = Boolean(editItem)
  const defaultSchoolId = schools[0]?.id ?? ""

  const [state, setState] = useState<FormState>(() => toFormState(editItem, defaultSchoolId))

  const staffOptions = useMemo(() => {
    return [...staff].sort((a, b) => {
      const byName = a.name.localeCompare(b.name)
      if (byName !== 0) return byName
      return a.email.localeCompare(b.email)
    })
  }, [staff])

  const validateForm = useCallback(
    (formState: FormState, excludeGradeId?: string): { ok: boolean; errors: FormErrors } => {
      const errors: FormErrors = {}

      const schoolId = formState.schoolId.trim()
      if (!schoolId) errors.schoolId = t("grades.validation.selectSchool")

      const name = normalizeName(formState.name)
      if (!name) errors.name = t("grades.validation.enterName")
      if (name.length > 100) errors.name = t("grades.validation.nameTooLong")

      const order = parseOrder(formState.order)
      if (order === null) errors.order = t("grades.validation.orderInvalid")

      if (schoolId && name) {
        const dup = grades.find((g) => {
          if (excludeGradeId && g.id === excludeGradeId) return false
          return g.school.id === schoolId && normalizeName(g.name).toLowerCase() === name.toLowerCase()
        })
        if (dup) errors.name = t("grades.validation.duplicateName")
      }

      return { ok: Object.keys(errors).length === 0, errors }
    },
    [t, grades]
  )

  const validation = useMemo(
    () => validateForm(state, editItem?.id),
    [state, editItem?.id, validateForm]
  )

  const isDirty = useMemo(() => {
    if (!editItem) return true
    const next = {
      schoolId: state.schoolId.trim(),
      name: normalizeName(state.name),
      order: parseOrder(state.order),
      gradeHeadId: state.gradeHeadId || "",
      teachingHeadId: state.teachingHeadId || "",
    }
    const prev = {
      schoolId: editItem.school.id,
      name: normalizeName(editItem.name),
      order: editItem.order,
      gradeHeadId: editItem.gradeHead?.id ?? "",
      teachingHeadId: editItem.teachingHead?.id ?? "",
    }
    return (
      next.schoolId !== prev.schoolId ||
      next.name !== prev.name ||
      (typeof next.order === "number" ? next.order : null) !== prev.order ||
      next.gradeHeadId !== prev.gradeHeadId ||
      next.teachingHeadId !== prev.teachingHeadId
    )
  }, [editItem, state])

  const createMutation = useActionMutation({
    errorMessage: t("grades.failedCreate"),
    onSuccess: () => {
      onOpenChange(false)
      onSuccess()
    },
  })

  const updateMutation = useActionMutation({
    errorMessage: t("grades.failedUpdate"),
    onSuccess: () => {
      onOpenChange(false)
      onSuccess()
    },
  })

  const isWorking = createMutation.isWorking || updateMutation.isWorking

  const handleSubmit = (): void => {
    const result = validateForm(state, editItem?.id)
    if (!result.ok) {
      toast.error(Object.values(result.errors)[0] || t("grades.validation.fixForm"))
      return
    }
    if (isEdit && !isDirty) {
      toast.message(t("grades.validation.noChanges"))
      return
    }

    const fd = new FormData()
    fd.set("schoolId", state.schoolId)
    fd.set("name", normalizeName(state.name))
    fd.set("order", state.order)
    fd.set("gradeHeadId", state.gradeHeadId)
    fd.set("teachingHeadId", state.teachingHeadId)

    if (isEdit && editItem) {
      void updateMutation.mutate(() => updateGradeAction(editItem.id, undefined, fd))
    } else {
      void createMutation.mutate(() => createGradeAction(undefined, fd))
    }
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[560px]">
        <DialogHeader>
          <DialogTitle>
            {isEdit ? t("grades.form.editTitle") : t("grades.form.createTitle")}
          </DialogTitle>
        </DialogHeader>
        <form
          className="space-y-4"
          onSubmit={(e) => {
            e.preventDefault()
            void handleSubmit()
          }}
        >
          <div className="grid grid-cols-4 items-center gap-4">
            <Label className="text-right">{t("grades.form.school")}</Label>
            <div className="col-span-3">
              <Select
                value={state.schoolId}
                onValueChange={(v) => setState((p) => ({ ...p, schoolId: v }))}
              >
                <SelectTrigger>
                  <SelectValue placeholder={t("grades.form.school")} />
                </SelectTrigger>
                <SelectContent>
                  {schools.map((s) => (
                    <SelectItem key={s.id} value={s.id}>
                      {s.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
            {validation.errors.schoolId ? (
              <div className="col-span-3 col-start-2 text-sm font-medium text-destructive">
                {validation.errors.schoolId}
              </div>
            ) : null}
          </div>

          <div className="grid grid-cols-4 items-center gap-4">
            <Label htmlFor="grade-name" className="text-right">
              {t("grades.form.name")}
            </Label>
            <Input
              id="grade-name"
              className="col-span-3"
              value={state.name}
              onChange={(e) => setState((p) => ({ ...p, name: e.target.value }))}
              placeholder={t("grades.form.name")}
              autoFocus={!isEdit}
            />
            {validation.errors.name ? (
              <div className="col-span-3 col-start-2 text-sm font-medium text-destructive">
                {validation.errors.name}
              </div>
            ) : null}
          </div>

          <div className="grid grid-cols-4 items-center gap-4">
            <Label htmlFor="grade-order" className="text-right">
              {t("grades.form.order")}
            </Label>
            <Input
              id="grade-order"
              className="col-span-3"
              type="number"
              inputMode="numeric"
              min={0}
              step={1}
              value={state.order}
              onChange={(e) => setState((p) => ({ ...p, order: e.target.value }))}
            />
            {validation.errors.order ? (
              <div className="col-span-3 col-start-2 text-sm font-medium text-destructive">
                {validation.errors.order}
              </div>
            ) : null}
          </div>

          <div className="grid grid-cols-4 items-center gap-4">
            <Label className="text-right">{t("grades.form.gradeHead")}</Label>
            <div className="col-span-3">
              <Select
                value={state.gradeHeadId}
                onValueChange={(v) =>
                  setState((p) => ({ ...p, gradeHeadId: v === NONE_SELECT_VALUE ? "" : v }))
                }
              >
                <SelectTrigger>
                  <SelectValue placeholder={t("grades.optional")} />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={NONE_SELECT_VALUE}>-</SelectItem>
                  {staffOptions.map((u) => (
                    <SelectItem key={u.id} value={u.id}>
                      {u.name} ({u.email})
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>

          <div className="grid grid-cols-4 items-center gap-4">
            <Label className="text-right">{t("grades.form.teachingHead")}</Label>
            <div className="col-span-3">
              <Select
                value={state.teachingHeadId}
                onValueChange={(v) =>
                  setState((p) => ({ ...p, teachingHeadId: v === NONE_SELECT_VALUE ? "" : v }))
                }
              >
                <SelectTrigger>
                  <SelectValue placeholder={t("grades.optional")} />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value={NONE_SELECT_VALUE}>-</SelectItem>
                  {staffOptions.map((u) => (
                    <SelectItem key={u.id} value={u.id}>
                      {u.name} ({u.email})
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>
          </div>

          <DialogFooter>
            <Button type="button" variant="outline" onClick={() => onOpenChange(false)} disabled={isWorking}>
              {t("grades.form.cancel")}
            </Button>
            <Button type="submit" disabled={isWorking}>
              {isEdit ? t("grades.form.save") : t("grades.form.create")}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  )
}
