"use client"

import { useState, useRef, useEffect, useCallback, useMemo } from "react"
import { useFormStatus } from "react-dom"
import { toast } from "sonner"
import { useRouter } from "next/navigation"
import { Search, TrendingUp, Trophy, AlertCircle } from "lucide-react"

import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/shared/components/ui/card"
import { Button } from "@/shared/components/ui/button"
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 {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/shared/components/ui/table"
import { cn } from "@/shared/lib/utils"

import { batchCreateGradeRecordsAction } from "../actions"

type Option = { id: string; name: string }
type Student = { id: string; name: string; email: string }
type GradeType = "exam" | "quiz" | "homework" | "other"
type Semester = "1" | "2"

function isGradeType(v: string): v is GradeType {
  return v === "exam" || v === "quiz" || v === "homework" || v === "other"
}

function isSemester(v: string): v is Semester {
  return v === "1" || v === "2"
}

const MAX_SCORE = 100
const DRAFT_KEY_PREFIX = "grade-draft"

function SubmitButton() {
  const { pending } = useFormStatus()
  return (
    <Button type="submit" disabled={pending}>
      {pending ? "Saving..." : "Save All Grades"}
    </Button>
  )
}

export function BatchGradeEntry({
  classes,
  subjects,
  students,
  defaultClassId,
  defaultSubjectId,
}: {
  classes: Option[]
  subjects: Option[]
  students: Student[]
  defaultClassId?: string
  defaultSubjectId?: string
}) {
  const router = useRouter()
  const initialDraftKey = `${DRAFT_KEY_PREFIX}-${defaultClassId ?? classes[0]?.id ?? ""}-${defaultSubjectId ?? subjects[0]?.id ?? ""}-exam`
  const [classId, setClassId] = useState(defaultClassId ?? classes[0]?.id ?? "")
  const [subjectId, setSubjectId] = useState(defaultSubjectId ?? subjects[0]?.id ?? "")
  const [type, setType] = useState<GradeType>("exam")
  const [semester, setSemester] = useState<Semester>("1")
  const [scores, setScores] = useState<Record<string, string>>(() => {
    // 惰性初始化：从 localStorage 恢复草稿（避免 useEffect 中 setState 导致级联渲染）
    try {
      const raw = localStorage.getItem(initialDraftKey)
      if (raw) {
        const data = JSON.parse(raw) as { scores: Record<string, string>; timestamp: number }
        if (Date.now() - data.timestamp < 2 * 60 * 60 * 1000 && Object.keys(data.scores).length > 0) {
          return data.scores
        }
      }
    } catch {
      // 解析失败，忽略
    }
    return {}
  })
  const [draftRestored] = useState(() => {
    // 检查是否恢复了草稿（用于显示 toast）
    try {
      const raw = localStorage.getItem(initialDraftKey)
      if (raw) {
        const data = JSON.parse(raw) as { scores: Record<string, string>; timestamp: number }
        return Date.now() - data.timestamp < 2 * 60 * 60 * 1000 && Object.keys(data.scores).length > 0
      }
    } catch {
      // 解析失败，忽略
    }
    return false
  })
  const [searchQuery, setSearchQuery] = useState("")
  const [isSubmitting, setIsSubmitting] = useState(false)
  const inputRefs = useRef<Record<string, HTMLInputElement | null>>({})

  const draftKey = `${DRAFT_KEY_PREFIX}-${classId}-${subjectId}-${type}`

  // 草稿恢复提示（仅在首次挂载时显示一次）
  useEffect(() => {
    if (draftRestored) {
      toast.info("已恢复未保存的成绩草稿")
    }
  }, [draftRestored])

  const handleScoreChange = useCallback((studentId: string, value: string) => {
    if (value === "" || /^\d*\.?\d{0,2}$/.test(value)) {
      setScores((prev) => ({ ...prev, [studentId]: value }))
    }
  }, [])

  const validateScore = (value: string): boolean => {
    if (value === "") return true
    const num = Number(value)
    return !isNaN(num) && num >= 0 && num <= MAX_SCORE
  }

  const restoreDraft = useCallback((key: string): boolean => {
    try {
      const raw = localStorage.getItem(key)
      if (raw) {
        const data = JSON.parse(raw) as { scores: Record<string, string>; timestamp: number }
        if (Date.now() - data.timestamp < 2 * 60 * 60 * 1000 && Object.keys(data.scores).length > 0) {
          setScores(data.scores)
          return true
        }
      }
    } catch {
      // 解析失败，忽略
    }
    return false
  }, [])

  const handleClassChange = (newClassId: string) => {
    const hasUnsaved = Object.keys(scores).length > 0
    if (hasUnsaved && newClassId !== classId) {
      if (!window.confirm("当前班级有未保存的成绩记录，确认切换班级？")) {
        return
      }
    }
    setClassId(newClassId)
    setScores({})
    // 切换班级后尝试恢复该班级的草稿
    const newDraftKey = `${DRAFT_KEY_PREFIX}-${newClassId}-${subjectId}-${type}`
    if (restoreDraft(newDraftKey)) {
      toast.info("已恢复未保存的成绩草稿")
    }
    const newUrl = newClassId ? `/teacher/grades/entry?classId=${encodeURIComponent(newClassId)}` : "/teacher/grades/entry"
    router.push(newUrl)
  }

  const filteredStudents = useMemo(
    () => students.filter((s) => !searchQuery || s.name.toLowerCase().includes(searchQuery.toLowerCase())),
    [students, searchQuery]
  )

  const stats = useMemo(() => {
    const validScores = students
      .map((s) => scores[s.id])
      .filter((v): v is string => v !== undefined && v !== "" && validateScore(v))
      .map(Number)
    const entered = validScores.length
    if (entered === 0) return { entered: 0, average: 0, max: 0, min: 0, total: students.length }
    const sum = validScores.reduce((acc, v) => acc + v, 0)
    return {
      entered,
      average: Math.round((sum / entered) * 100) / 100,
      max: Math.max(...validScores),
      min: Math.min(...validScores),
      total: students.length,
    }
  }, [scores, students])

  const hasInvalidScores = Object.values(scores).some((v) => v !== "" && v !== undefined && !validateScore(v))

  // 草稿保存到 localStorage（30秒间隔）
  useEffect(() => {
    const interval = setInterval(() => {
      if (Object.keys(scores).length > 0) {
        try {
          localStorage.setItem(draftKey, JSON.stringify({ scores, timestamp: Date.now() }))
        } catch {
          // localStorage 可能已满或不可用，静默失败
        }
      }
    }, 30000)
    return () => clearInterval(interval)
  }, [scores, draftKey])

  // 清除草稿
  const clearDraft = useCallback(() => {
    try {
      localStorage.removeItem(draftKey)
    } catch {
      // 忽略
    }
  }, [draftKey])

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>, studentId: string) => {
    if (e.key === "Enter") {
      e.preventDefault()
      const currentIndex = filteredStudents.findIndex((s) => s.id === studentId)
      const nextStudent = filteredStudents[currentIndex + 1]
      if (nextStudent && inputRefs.current[nextStudent.id]) {
        inputRefs.current[nextStudent.id]?.focus()
        inputRefs.current[nextStudent.id]?.select()
      }
    }
  }

  const handleSubmit = async (formData: FormData) => {
    if (!classId || !subjectId) {
      toast.error("Please select class and subject")
      return
    }

    if (hasInvalidScores) {
      toast.error("存在无效分数（超过满分或格式错误），请检查后重试")
      return
    }

    const records = students
      .map((s) => ({
        studentId: s.id,
        score: Number(scores[s.id] ?? 0),
      }))
      .filter((r) => r.score > 0 || scores[r.studentId] !== undefined)
    if (records.length === 0) {
      toast.error("Please enter at least one score")
      return
    }

    setIsSubmitting(true)
    formData.set("classId", classId)
    formData.set("subjectId", subjectId)
    formData.set("type", type)
    formData.set("semester", semester)
    formData.set("recordsJson", JSON.stringify(records))

    const result = await batchCreateGradeRecordsAction(null, formData)
    setIsSubmitting(false)
    if (result.success) {
      clearDraft()
      toast.success(result.message)
      router.push("/teacher/grades")
      router.refresh()
    } else {
      toast.error(result.message || "Failed to save")
    }
  }

  return (
    <Card className="relative">
      {isSubmitting && (
        <div className="absolute inset-0 z-10 flex items-center justify-center rounded-lg bg-background/60 backdrop-blur-sm">
          <div className="flex items-center gap-2 text-sm font-medium">
            <div className="h-4 w-4 animate-spin rounded-full border-2 border-primary border-t-transparent" />
            Saving grades...
          </div>
        </div>
      )}
      <CardHeader>
        <CardTitle>Batch Grade Entry</CardTitle>
        <p className="text-sm text-muted-foreground">
          满分 {MAX_SCORE} 分。输入分数后按 Enter 跳到下一位学生。草稿每 30 秒自动保存，2 小时内有效。
        </p>
      </CardHeader>
      <CardContent>
        <form action={handleSubmit} className="space-y-6">
          <div className="grid grid-cols-1 gap-4 md:grid-cols-2">
            <div className="grid gap-2">
              <Label>Class</Label>
              <Select value={classId} onValueChange={handleClassChange}>
                <SelectTrigger>
                  <SelectValue placeholder="Select a class" />
                </SelectTrigger>
                <SelectContent>
                  {classes.map((c) => (
                    <SelectItem key={c.id} value={c.id}>
                      {c.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div className="grid gap-2">
              <Label>Subject</Label>
              <Select value={subjectId} onValueChange={setSubjectId}>
                <SelectTrigger>
                  <SelectValue placeholder="Select a subject" />
                </SelectTrigger>
                <SelectContent>
                  {subjects.map((s) => (
                    <SelectItem key={s.id} value={s.id}>
                      {s.name}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </div>

            <div className="grid gap-2 md:col-span-2">
              <Label htmlFor="title">Exam / Quiz Title</Label>
              <Input id="title" name="title" placeholder="e.g. Mid-term Exam" required />
            </div>

            <div className="grid gap-2">
              <Label htmlFor="fullScore">Full Score</Label>
              <Input id="fullScore" name="fullScore" type="number" step="0.01" min="1" defaultValue={String(MAX_SCORE)} />
            </div>

            <div className="grid gap-2">
              <Label>Type</Label>
              <Select value={type} onValueChange={(v) => { if (isGradeType(v)) setType(v) }}>
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="exam">Exam</SelectItem>
                  <SelectItem value="quiz">Quiz</SelectItem>
                  <SelectItem value="homework">Homework</SelectItem>
                  <SelectItem value="other">Other</SelectItem>
                </SelectContent>
              </Select>
            </div>

            <div className="grid gap-2">
              <Label>Semester</Label>
              <Select value={semester} onValueChange={(v) => { if (isSemester(v)) setSemester(v) }}>
                <SelectTrigger>
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  <SelectItem value="1">Semester 1</SelectItem>
                  <SelectItem value="2">Semester 2</SelectItem>
                </SelectContent>
              </Select>
            </div>
          </div>

          {students.length === 0 ? (
            <p className="text-sm text-muted-foreground">No students in this class.</p>
          ) : (
            <>
              {/* 实时统计栏 */}
              <div className="flex flex-col gap-3 rounded-md border bg-muted/30 p-3 sm:flex-row sm:items-center sm:justify-between">
                <div className="flex flex-wrap items-center gap-4 text-sm">
                  <span className="inline-flex items-center gap-1.5">
                    <span className="text-muted-foreground">已录入</span>
                    <span className="font-semibold tabular-nums">{stats.entered}</span>
                    <span className="text-muted-foreground">/ {stats.total}</span>
                  </span>
                  {stats.entered > 0 && (
                    <>
                      <span className="inline-flex items-center gap-1.5">
                        <TrendingUp className="h-3.5 w-3.5 text-muted-foreground" aria-hidden="true" />
                        <span className="text-muted-foreground">均分</span>
                        <span className="font-semibold tabular-nums">{stats.average}</span>
                      </span>
                      <span className="inline-flex items-center gap-1.5">
                        <Trophy className="h-3.5 w-3.5 text-amber-500" aria-hidden="true" />
                        <span className="text-muted-foreground">最高</span>
                        <span className="font-semibold tabular-nums">{stats.max}</span>
                      </span>
                      <span className="inline-flex items-center gap-1.5">
                        <span className="text-muted-foreground">最低</span>
                        <span className="font-semibold tabular-nums">{stats.min}</span>
                      </span>
                    </>
                  )}
                </div>
                <div className="flex items-center gap-2">
                  {hasInvalidScores && (
                    <span className="inline-flex items-center gap-1 text-xs text-destructive">
                      <AlertCircle className="h-3.5 w-3.5" aria-hidden="true" />
                      存在无效分数
                    </span>
                  )}
                  <div className="relative">
                    <Search className="pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" />
                    <Input
                      type="search"
                      placeholder="Search student..."
                      value={searchQuery}
                      onChange={(e) => setSearchQuery(e.target.value)}
                      className="h-8 w-40 pl-8 text-sm"
                    />
                  </div>
                </div>
              </div>
              <div className="rounded-md border">
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead className="w-12">#</TableHead>
                      <TableHead>Student</TableHead>
                      <TableHead className="hidden md:table-cell">Email</TableHead>
                      <TableHead className="w-32">Score</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {filteredStudents.map((s, idx) => {
                      const scoreValue = scores[s.id] ?? ""
                      const isInvalid = scoreValue !== "" && !validateScore(scoreValue)
                      return (
                        <TableRow key={s.id}>
                          <TableCell className="text-muted-foreground tabular-nums">{idx + 1}</TableCell>
                          <TableCell className="font-medium">{s.name}</TableCell>
                          <TableCell className="hidden text-muted-foreground md:table-cell">{s.email}</TableCell>
                          <TableCell>
                            <Input
                              ref={(el) => { inputRefs.current[s.id] = el }}
                              type="number"
                              step="0.01"
                              min="0"
                              max={MAX_SCORE}
                              placeholder="0"
                              value={scoreValue}
                              onChange={(e) => handleScoreChange(s.id, e.target.value)}
                              onKeyDown={(e) => handleKeyDown(e, s.id)}
                              className={cn("h-8", isInvalid && "border-destructive focus-visible:ring-destructive")}
                              aria-invalid={isInvalid}
                            />
                          </TableCell>
                        </TableRow>
                      )
                    })}
                  </TableBody>
                </Table>
              </div>
            </>
          )}

          <CardFooter className="justify-end gap-2 px-0">
            <Button type="button" variant="outline" onClick={() => router.back()}>
              Cancel
            </Button>
            <SubmitButton />
          </CardFooter>
        </form>
      </CardContent>
    </Card>
  )
}
