"use client"

import { useEffect, useState, useCallback } from "react"
import {
  AlertTriangle,
  ClipboardList,
  Clock,
  RefreshCw,
  Users,
} from "lucide-react"

import { cn, formatDateTime } from "@/shared/lib/utils"
import { usePermission } from "@/shared/hooks/use-permission"
import { Permissions } from "@/shared/types/permissions"
import { Badge } from "@/shared/components/ui/badge"
import { Button } from "@/shared/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardHeader,
  CardTitle,
} from "@/shared/components/ui/card"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/shared/components/ui/table"
import { ScrollArea } from "@/shared/components/ui/scroll-area"

import { getProctoringDashboardAction } from "../actions"
import type {
  ProctoringDashboardData,
  ProctoringEventType,
} from "../types"
import { PROCTORING_EVENT_LABELS, EXAM_MODE_LABELS } from "../types"

const REFRESH_INTERVAL_MS = 10_000

/**
 * P1-3 修复：类型守卫替代 `as ProctoringEventType[]` 断言。
 * `Object.keys()` 返回 `string[]`，需过滤为合法的 ProctoringEventType。
 */
const PROCTORING_EVENT_TYPE_SET: ReadonlySet<string> = new Set([
  "tab_switch",
  "window_blur",
  "copy_attempt",
  "paste_attempt",
  "right_click",
  "devtools_open",
  "fullscreen_exit",
  "idle_timeout",
])

const isProctoringEventType = (v: string): v is ProctoringEventType =>
  PROCTORING_EVENT_TYPE_SET.has(v)

const toProctoringEventTypes = (keys: string[]): ProctoringEventType[] =>
  keys.filter(isProctoringEventType)

const formatTime = (iso: string | null): string => {
  if (!iso) return "—"
  return formatDateTime(iso)
}

const statusBadge = (status: string | null) => {
  if (!status) return <Badge variant="outline">未开始</Badge>
  if (status === "started") return <Badge variant="secondary">已开始</Badge>
  if (status === "submitted") return <Badge>已提交</Badge>
  if (status === "graded") return <Badge>已批改</Badge>
  return <Badge variant="outline">{status}</Badge>
}

type StatCardProps = {
  icon: React.ReactNode
  label: string
  value: number | string
  hint?: string
  highlight?: boolean
}

function StatCard({ icon, label, value, hint, highlight }: StatCardProps) {
  return (
    <Card className={cn(highlight && "border-destructive/50")}>
      <CardContent className="flex items-center gap-3 p-4">
        <div
          className={cn(
            "flex h-9 w-9 items-center justify-center rounded-md bg-muted",
            highlight && "bg-destructive/10 text-destructive",
          )}
        >
          {icon}
        </div>
        <div>
          <div className="text-sm text-muted-foreground">{label}</div>
          <div className="text-xl font-semibold">{value}</div>
          {hint && <div className="text-xs text-muted-foreground">{hint}</div>}
        </div>
      </CardContent>
    </Card>
  )
}

type ProctoringDashboardProps = {
  examId: string
  initialData: ProctoringDashboardData | null
}

export function ProctoringDashboard({
  examId,
  initialData,
}: ProctoringDashboardProps) {
  const { hasPermission } = usePermission()
  const canProctor = hasPermission(Permissions.EXAM_PROCTOR)

  const [data, setData] = useState<ProctoringDashboardData | null>(initialData)
  const [loading, setLoading] = useState(false)
  const [lastUpdated, setLastUpdated] = useState<Date | null>(
    initialData ? new Date() : null,
  )

  const refresh = useCallback(async () => {
    if (!canProctor) return
    setLoading(true)
    try {
      const result = await getProctoringDashboardAction(examId)
      if (result.success && result.data) {
        setData(result.data)
        setLastUpdated(new Date())
      }
    } catch (error) {
      console.error("Failed to refresh proctoring dashboard:", error)
    } finally {
      setLoading(false)
    }
  }, [examId, canProctor])

  useEffect(() => {
    if (!canProctor) return
    const timer = setInterval(refresh, REFRESH_INTERVAL_MS)
    return () => clearInterval(timer)
  }, [refresh, canProctor])

  if (!canProctor) {
    return (
      <Card>
        <CardContent className="py-10 text-center text-muted-foreground">
          您没有监考权限（exam:proctor）。
        </CardContent>
      </Card>
    )
  }

  if (!data) {
    return (
      <Card>
        <CardContent className="py-10 text-center text-muted-foreground">
          暂无监考数据
        </CardContent>
      </Card>
    )
  }

  const { summary, students, recentEvents } = data
  const notStarted = summary.totalStudents - summary.startedStudents - summary.submittedStudents

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <div>
          <h2 className="text-lg font-semibold">{summary.examTitle}</h2>
          <p className="text-sm text-muted-foreground">
            模式：{EXAM_MODE_LABELS[summary.examMode]} · 最后更新：
            {lastUpdated ? formatTime(lastUpdated.toISOString()) : "—"}
          </p>
        </div>
        <Button variant="outline" size="sm" onClick={refresh} disabled={loading}>
          <RefreshCw className={cn("mr-2 h-4 w-4", loading && "animate-spin")} />
          刷新
        </Button>
      </div>

      <div className="grid gap-4 md:grid-cols-4">
        <StatCard icon={<Users className="h-4 w-4" />} label="学生总数" value={summary.totalStudents} hint={`未开始 ${notStarted}`} />
        <StatCard icon={<Clock className="h-4 w-4" />} label="已开始 / 已提交" value={`${summary.startedStudents} / ${summary.submittedStudents}`} />
        <StatCard icon={<ClipboardList className="h-4 w-4" />} label="异常事件总数" value={summary.totalEvents} />
        <StatCard icon={<AlertTriangle className="h-4 w-4" />} label="异常学生数" value={summary.abnormalStudents} highlight={summary.abnormalStudents > 0} />
      </div>

      <Card>
        <CardHeader>
          <CardTitle>事件类型分布</CardTitle>
          <CardDescription>各类监考事件触发次数</CardDescription>
        </CardHeader>
        <CardContent>
          <div className="flex flex-wrap gap-2">
            {toProctoringEventTypes(Object.keys(summary.eventsByType)).map((type) => {
              const count = summary.eventsByType[type]
              if (count === 0) return null
              return (
                <Badge key={type} variant="destructive">
                  {PROCTORING_EVENT_LABELS[type]}：{count}
                </Badge>
              )
            })}
            {summary.totalEvents === 0 && (
              <span className="text-sm text-muted-foreground">暂无异常事件</span>
            )}
          </div>
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>学生监考状态</CardTitle>
          <CardDescription>异常学生（事件数 ≥ 3）高亮显示</CardDescription>
        </CardHeader>
        <CardContent>
          {students.length === 0 ? (
            <div className="py-6 text-center text-sm text-muted-foreground">暂无学生提交记录</div>
          ) : (
            <Table>
              <TableHeader>
                <TableRow>
                  <TableHead>学生</TableHead>
                  <TableHead>提交状态</TableHead>
                  <TableHead className="text-right">事件数</TableHead>
                  <TableHead>最后事件</TableHead>
                  <TableHead>异常类型</TableHead>
                </TableRow>
              </TableHeader>
              <TableBody>
                {students.map((s) => (
                  <TableRow key={s.studentId} className={cn(s.isAbnormal && "bg-destructive/5")}>
                    <TableCell className="font-medium">
                      {s.studentName}
                      {s.isAbnormal && <AlertTriangle className="ml-2 inline h-3 w-3 text-destructive" />}
                    </TableCell>
                    <TableCell>{statusBadge(s.submissionStatus)}</TableCell>
                    <TableCell className="text-right">
                      {s.eventCount > 0 ? (
                        <span className={cn(s.isAbnormal && "font-semibold text-destructive")}>{s.eventCount}</span>
                      ) : (
                        <span className="text-muted-foreground">0</span>
                      )}
                    </TableCell>
                    <TableCell className="text-muted-foreground">{formatTime(s.lastEventAt)}</TableCell>
                    <TableCell>
                      <div className="flex flex-wrap gap-1">
                        {toProctoringEventTypes(Object.keys(s.eventsByType))
                          .filter((t) => s.eventsByType[t] > 0)
                          .map((t) => (
                            <Badge key={t} variant="outline" className="text-xs">
                              {PROCTORING_EVENT_LABELS[t]}×{s.eventsByType[t]}
                            </Badge>
                          ))}
                      </div>
                    </TableCell>
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          )}
        </CardContent>
      </Card>

      <Card>
        <CardHeader>
          <CardTitle>最近事件</CardTitle>
          <CardDescription>最新 20 条监考事件</CardDescription>
        </CardHeader>
        <CardContent>
          {recentEvents.length === 0 ? (
            <div className="py-6 text-center text-sm text-muted-foreground">暂无事件</div>
          ) : (
            <ScrollArea className="h-72">
              <ul className="space-y-2">
                {recentEvents.map((e) => (
                  <li key={e.id} className="flex items-start justify-between gap-3 rounded-md border p-2 text-sm">
                    <div>
                      <div className="font-medium">
                        {e.studentName}
                        <Badge variant="destructive" className="ml-2 text-xs">
                          {PROCTORING_EVENT_LABELS[e.eventType]}
                        </Badge>
                      </div>
                      {e.eventDetail && (
                        <div className="text-xs text-muted-foreground">{e.eventDetail}</div>
                      )}
                    </div>
                    <span className="text-xs text-muted-foreground">{formatTime(e.occurredAt)}</span>
                  </li>
                ))}
              </ul>
            </ScrollArea>
          )}
        </CardContent>
      </Card>
    </div>
  )
}
