"use client"

import * as React from "react"
import { useTranslations } from "next-intl"
import { toast } from "sonner"
import { Copy, Plus, Ban, Clock, Hash } from "lucide-react"

import { Button } from "@/shared/components/ui/button"
import { Input } from "@/shared/components/ui/input"
import { Label } from "@/shared/components/ui/label"
import { Badge } from "@/shared/components/ui/badge"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/shared/components/ui/dialog"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/shared/components/ui/table"
import {
  createClassInvitationCodeAction,
  revokeClassInvitationCodeAction,
} from "@/modules/classes/actions"

/**
 * 班级邀请码管理面板（v3 新增，对标 Google Classroom / 钉钉教育）。
 *
 * 功能：
 * - 列出班级所有邀请码（含状态/有效期/使用次数）
 * - 生成自定义邀请码（可选有效期/次数/备注）
 * - 撤销邀请码（软删除）
 * - 复制邀请码到剪贴板
 *
 * 权限：调用方需确保用户拥有 CLASS_ENROLL 权限（actions 内部已校验）
 */
interface InvitationCodeRecord {
  id: string
  code: string
  status: "active" | "disabled" | "expired" | "exhausted"
  maxUses: number | null
  usedCount: number
  expiresAt: string | null
  createdAt: string
  revokedAt: string | null
  note: string | null
}

interface ClassInvitationManagerProps {
  classId: string
  initialCodes: InvitationCodeRecord[]
}

export function ClassInvitationManager({
  classId,
  initialCodes,
}: ClassInvitationManagerProps) {
  const t = useTranslations("classes.invitation")
  const [codes, setCodes] = React.useState<InvitationCodeRecord[]>(initialCodes)
  const [isGenerateOpen, setIsGenerateOpen] = React.useState(false)
  const [revokeTarget, setRevokeTarget] = React.useState<InvitationCodeRecord | null>(null)
  const [isSubmitting, setIsSubmitting] = React.useState(false)

  const handleCopy = async (code: string): Promise<void> => {
    try {
      await navigator.clipboard.writeText(code)
      toast.success(t("copied"))
    } catch {
      toast.error(t("copy"))
    }
  }

  const handleRevoke = async (): Promise<void> => {
    if (!revokeTarget) return
    setIsSubmitting(true)
    try {
      const formData = new FormData()
      formData.set("codeId", revokeTarget.id)
      const result = await revokeClassInvitationCodeAction(null, formData)
      if (result.success) {
        toast.success(t("revokeSuccess"))
        setCodes((prev) =>
          prev.map((c) =>
            c.id === revokeTarget.id
              ? { ...c, status: "disabled", revokedAt: new Date().toISOString() }
              : c
          )
        )
        setRevokeTarget(null)
      } else {
        toast.error(result.message ?? t("revokeFailed"))
      }
    } catch {
      toast.error(t("revokeFailed"))
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <div className="grid gap-4">
      <div className="flex items-center justify-between">
        <h3 className="text-lg font-semibold">{t("title")}</h3>
        <Dialog open={isGenerateOpen} onOpenChange={setIsGenerateOpen}>
          <DialogTrigger asChild>
            <Button size="sm">
              <Plus className="mr-1.5 h-4 w-4" />
              {t("generate")}
            </Button>
          </DialogTrigger>
          <GenerateCodeDialog
            classId={classId}
            onClose={() => setIsGenerateOpen(false)}
            onCreated={(record) => {
              setCodes((prev) => [record, ...prev])
            }}
          />
        </Dialog>
      </div>

      {codes.length === 0 ? (
        <p className="py-8 text-center text-sm text-muted-foreground">{t("empty")}</p>
      ) : (
        <Table>
          <TableHeader>
            <TableRow>
              <TableHead>{t("code")}</TableHead>
              <TableHead>{t("status")}</TableHead>
              <TableHead>{t("usedCount")}</TableHead>
              <TableHead>{t("expiresAt")}</TableHead>
              <TableHead>{t("note")}</TableHead>
              <TableHead className="text-right">{t("copy")}</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {codes.map((record) => (
              <TableRow key={record.id}>
                <TableCell className="font-mono font-medium tracking-wider">
                  {record.code}
                </TableCell>
                <TableCell>
                  <StatusBadge status={record.status} />
                </TableCell>
                <TableCell>
                  <span className="text-sm">
                    {record.usedCount}
                    {record.maxUses !== null ? ` / ${record.maxUses}` : ""}
                  </span>
                </TableCell>
                <TableCell className="text-sm text-muted-foreground">
                  {record.expiresAt
                    ? new Date(record.expiresAt).toLocaleString()
                    : t("neverExpires")}
                </TableCell>
                <TableCell className="max-w-[200px] truncate text-sm text-muted-foreground">
                  {record.note ?? "—"}
                </TableCell>
                <TableCell className="text-right">
                  <div className="flex justify-end gap-1">
                    <Button
                      variant="ghost"
                      size="icon"
                      onClick={() => handleCopy(record.code)}
                      aria-label={t("copy")}
                    >
                      <Copy className="h-4 w-4" />
                    </Button>
                    {record.status === "active" ? (
                      <Button
                        variant="ghost"
                        size="icon"
                        onClick={() => setRevokeTarget(record)}
                        aria-label={t("revoke")}
                      >
                        <Ban className="h-4 w-4" />
                      </Button>
                    ) : null}
                  </div>
                </TableCell>
              </TableRow>
            ))}
          </TableBody>
        </Table>
      )}

      {/* 撤销确认对话框 */}
      <Dialog open={!!revokeTarget} onOpenChange={(open) => !open && setRevokeTarget(null)}>
        <DialogContent>
          <DialogHeader>
            <DialogTitle>{t("revoke")}</DialogTitle>
            <DialogDescription>{t("revokeConfirm")}</DialogDescription>
          </DialogHeader>
          <DialogFooter>
            <Button variant="outline" onClick={() => setRevokeTarget(null)} disabled={isSubmitting}>
              {t("cancel")}
            </Button>
            <Button variant="destructive" onClick={handleRevoke} disabled={isSubmitting}>
              {t("revoke")}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  )
}

function StatusBadge({ status }: { status: InvitationCodeRecord["status"] }) {
  const t = useTranslations("classes.invitation")
  const variant = status === "active" ? "default" : "secondary"
  return <Badge variant={variant}>{t(status)}</Badge>
}

interface GenerateCodeDialogProps {
  classId: string
  onClose: () => void
  onCreated: (record: InvitationCodeRecord) => void
}

function GenerateCodeDialog({ classId, onClose, onCreated }: GenerateCodeDialogProps) {
  const t = useTranslations("classes.invitation")
  const [expiresInHours, setExpiresInHours] = React.useState("")
  const [maxUses, setMaxUses] = React.useState("")
  const [note, setNote] = React.useState("")
  const [isSubmitting, setIsSubmitting] = React.useState(false)

  const handleSubmit = async (e: React.FormEvent): Promise<void> => {
    e.preventDefault()
    setIsSubmitting(true)
    try {
      const formData = new FormData()
      formData.set("classId", classId)
      formData.set("expiresInHours", expiresInHours)
      formData.set("maxUses", maxUses)
      formData.set("note", note)
      const result = await createClassInvitationCodeAction(null, formData)
      if (result.success && result.data) {
        toast.success(t("generateSuccess"))
        onCreated({
          id: result.data.id,
          code: result.data.code,
          status: "active",
          maxUses: maxUses ? Number(maxUses) : null,
          usedCount: 0,
          expiresAt: expiresInHours
            ? new Date(Date.now() + Number(expiresInHours) * 60 * 60 * 1000).toISOString()
            : null,
          createdAt: new Date().toISOString(),
          revokedAt: null,
          note: note || null,
        })
        onClose()
      } else {
        toast.error(result.message ?? t("generateFailed"))
      }
    } catch {
      toast.error(t("generateFailed"))
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <DialogContent>
      <DialogHeader>
        <DialogTitle>{t("generateWithCustom")}</DialogTitle>
        <DialogDescription>
          {t("defaultDuration")} · {t("defaultMaxUses")}
        </DialogDescription>
      </DialogHeader>
      <form onSubmit={handleSubmit} className="grid gap-4">
        <div className="grid gap-2">
          <Label htmlFor="expiresInHours" className="flex items-center gap-1.5">
            <Clock className="h-3.5 w-3.5" />
            {t("expiresInHours")}
          </Label>
          <Input
            id="expiresInHours"
            type="number"
            min="1"
            value={expiresInHours}
            onChange={(e) => setExpiresInHours(e.target.value)}
            placeholder={t("defaultDuration")}
          />
        </div>
        <div className="grid gap-2">
          <Label htmlFor="maxUses" className="flex items-center gap-1.5">
            <Hash className="h-3.5 w-3.5" />
            {t("maxUsesLabel")}
          </Label>
          <Input
            id="maxUses"
            type="number"
            min="1"
            value={maxUses}
            onChange={(e) => setMaxUses(e.target.value)}
            placeholder={t("defaultMaxUses")}
          />
        </div>
        <div className="grid gap-2">
          <Label htmlFor="note">{t("customNote")}</Label>
          <Input
            id="note"
            value={note}
            onChange={(e) => setNote(e.target.value)}
            placeholder={t("customNotePlaceholder")}
            maxLength={255}
          />
        </div>
        <DialogFooter>
          <Button type="button" variant="outline" onClick={onClose} disabled={isSubmitting}>
            {t("cancel")}
          </Button>
          <Button type="submit" disabled={isSubmitting}>
            {isSubmitting ? t("generate") + "..." : t("generate")}
          </Button>
        </DialogFooter>
      </form>
    </DialogContent>
  )
}
