"use client"

import * as React from "react"
import { useTranslations } from "next-intl"
import { toast } from "sonner"
import {
  Smartphone,
  Loader2,
  AlertCircle,
  KeyRound,
  Copy,
  Check,
  RefreshCw,
} from "lucide-react"

import {
  disableTwoFactorAction,
  regenerateBackupCodesAction,
  setupTwoFactorAction,
  verifyTwoFactorAction,
  type TwoFactorSetupData,
  type TwoFactorStatus,
} from "@/modules/settings/actions-security"
import { Badge } from "@/shared/components/ui/badge"
import { Button } from "@/shared/components/ui/button"
import { Input } from "@/shared/components/ui/input"
import { Label } from "@/shared/components/ui/label"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/shared/components/ui/dialog"

interface SecurityTwoFactorSectionProps {
  /** 当前 2FA 状态，null 表示尚未加载 */
  twoFactor: TwoFactorStatus | null
  /** 是否正在加载初始数据 */
  loading: boolean
  /** 2FA 状态变更后通知父组件刷新 */
  onStatusChange: (status: TwoFactorStatus) => void
}

type SetupStep = "idle" | "qr" | "backup"

/**
 * 安全中心 - 两步验证区块
 *
 * 负责：
 * - 2FA 启用流程（二维码 + 验证 + 备份码展示）
 * - 2FA 关闭流程
 * - 备份码重新生成
 *
 * 所有 Server Action 调用均封装在本组件内部，
 * 父组件仅需提供初始状态与状态变更回调。
 */
export function SecurityTwoFactorSection({
  twoFactor,
  loading,
  onStatusChange,
}: SecurityTwoFactorSectionProps): React.ReactElement {
  const t = useTranslations("settings.security.center")

  // 启用 2FA Dialog 状态
  const [enableDialogOpen, setEnableDialogOpen] = React.useState(false)
  const [setupStep, setSetupStep] = React.useState<SetupStep>("idle")
  const [setupData, setSetupData] = React.useState<TwoFactorSetupData | null>(null)
  const [verifyCode, setVerifyCode] = React.useState("")
  const [backupCodes, setBackupCodes] = React.useState<string[]>([])
  const [setupLoading, setSetupLoading] = React.useState(false)
  const [copied, setCopied] = React.useState(false)

  // 关闭 2FA Dialog 状态
  const [disableDialogOpen, setDisableDialogOpen] = React.useState(false)
  const [disableCode, setDisableCode] = React.useState("")
  const [disableLoading, setDisableLoading] = React.useState(false)

  // 重新生成备份码 Dialog 状态
  const [regenDialogOpen, setRegenDialogOpen] = React.useState(false)
  const [regenCode, setRegenCode] = React.useState("")
  const [regenLoading, setRegenLoading] = React.useState(false)
  const [regenBackupCodes, setRegenBackupCodes] = React.useState<string[]>([])

  // --- 启用 2FA 流程 ---

  const handleEnable2FA = async (): Promise<void> => {
    setEnableDialogOpen(true)
    setSetupStep("idle")
    setSetupData(null)
    setVerifyCode("")
    setBackupCodes([])
    setSetupLoading(true)
    try {
      const result = await setupTwoFactorAction()
      if (result.success && result.data) {
        setSetupData(result.data)
        setSetupStep("qr")
      } else {
        toast.error(result.message || t("twoFactor.setupFailure"))
        setEnableDialogOpen(false)
      }
    } catch {
      toast.error(t("twoFactor.setupFailure"))
      setEnableDialogOpen(false)
    } finally {
      setSetupLoading(false)
    }
  }

  const handleVerifySetup = async (): Promise<void> => {
    if (!verifyCode.trim()) return
    setSetupLoading(true)
    try {
      const result = await verifyTwoFactorAction(verifyCode.trim())
      if (result.success && result.data) {
        setBackupCodes(result.data.backupCodes)
        onStatusChange(result.data.status)
        setSetupStep("backup")
        toast.success(t("twoFactor.enableSuccess"))
      } else {
        toast.error(result.message || t("twoFactor.invalidCode"))
      }
    } catch {
      toast.error(t("twoFactor.verifyFailure"))
    } finally {
      setSetupLoading(false)
    }
  }

  const handleCopyBackupCodes = async (): Promise<void> => {
    try {
      await navigator.clipboard.writeText(backupCodes.join("\n"))
      setCopied(true)
      setTimeout(() => setCopied(false), 2000)
    } catch {
      // 剪贴板不可用时静默
    }
  }

  const handleCloseEnableDialog = (): void => {
    setEnableDialogOpen(false)
    setSetupStep("idle")
    setSetupData(null)
    setVerifyCode("")
    setBackupCodes([])
  }

  // --- 关闭 2FA 流程 ---

  const handleDisable2FA = async (): Promise<void> => {
    if (!disableCode.trim()) return
    setDisableLoading(true)
    try {
      const result = await disableTwoFactorAction(disableCode.trim())
      if (result.success && result.data) {
        onStatusChange(result.data)
        setDisableDialogOpen(false)
        setDisableCode("")
        toast.success(t("twoFactor.disableSuccess"))
      } else {
        toast.error(result.message || t("twoFactor.invalidCode"))
      }
    } catch {
      toast.error(t("twoFactor.disableFailure"))
    } finally {
      setDisableLoading(false)
    }
  }

  // --- 重新生成备份码 ---

  const handleRegenerateBackupCodes = async (): Promise<void> => {
    if (!regenCode.trim()) return
    setRegenLoading(true)
    try {
      const result = await regenerateBackupCodesAction(regenCode.trim())
      if (result.success && result.data) {
        setRegenBackupCodes(result.data.backupCodes)
        onStatusChange(result.data.status)
        setRegenCode("")
        toast.success(t("twoFactor.regenerateSuccess"))
      } else {
        toast.error(result.message || t("twoFactor.invalidCode"))
      }
    } catch {
      toast.error(t("twoFactor.regenerateFailure"))
    } finally {
      setRegenLoading(false)
    }
  }

  const handleRegenDialogOpen = (): void => {
    setRegenDialogOpen(true)
    setRegenCode("")
    setRegenBackupCodes([])
  }

  return (
    <div className="space-y-3">
      <div className="flex items-center justify-between rounded-lg border p-4">
        <div className="flex items-start gap-3">
          <Smartphone className="mt-0.5 h-5 w-5 text-muted-foreground" />
          <div className="space-y-0.5">
            <div className="text-sm font-medium">{t("twoFactor.title")}</div>
            <p className="text-sm text-muted-foreground">
              {t("twoFactor.description")}
            </p>
            {twoFactor?.enabled ? (
              <div className="mt-1 flex items-center gap-2">
                <Badge variant="secondary">{t("twoFactor.enabled")}</Badge>
                <span className="text-xs text-muted-foreground">
                  {t("twoFactor.backupRemaining", { count: twoFactor.backupCodesRemaining })}
                </span>
              </div>
            ) : null}
          </div>
        </div>
        {loading ? (
          <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
        ) : twoFactor?.enabled ? (
          <Button
            type="button"
            variant="outline"
            size="sm"
            onClick={() => setDisableDialogOpen(true)}
          >
            {t("twoFactor.disable")}
          </Button>
        ) : (
          <Button
            type="button"
            size="sm"
            onClick={handleEnable2FA}
          >
            {t("twoFactor.enable")}
          </Button>
        )}
      </div>
      {twoFactor?.enabled ? (
        <div className="flex items-center justify-between rounded-lg border border-dashed p-3">
          <div className="flex items-start gap-2">
            <KeyRound className="mt-0.5 h-4 w-4 text-muted-foreground" />
            <div>
              <div className="text-xs font-medium">{t("twoFactor.backupCodes")}</div>
              <p className="text-xs text-muted-foreground">
                {t("twoFactor.backupHint")}
              </p>
            </div>
          </div>
          <Button
            type="button"
            variant="ghost"
            size="sm"
            onClick={handleRegenDialogOpen}
            className="h-7 gap-1.5 text-xs"
          >
            <RefreshCw className="h-3.5 w-3.5" />
            {t("twoFactor.regenerate")}
          </Button>
        </div>
      ) : (
        <p className="flex items-start gap-1.5 text-xs text-muted-foreground">
          <AlertCircle className="mt-0.5 h-3.5 w-3.5 flex-shrink-0" />
          {t("twoFactor.hint")}
        </p>
      )}

      {/* 启用 2FA Dialog */}
      <Dialog open={enableDialogOpen} onOpenChange={(o) => { if (!o) handleCloseEnableDialog() }}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>{t("twoFactor.title")}</DialogTitle>
            <DialogDescription>{t("twoFactor.description")}</DialogDescription>
          </DialogHeader>

          {setupStep === "qr" && setupData ? (
            <div className="space-y-4">
              <div className="flex flex-col items-center gap-3">
                {/* eslint-disable-next-line @next/next/no-img-element */}
                <img
                  src={setupData.qrCodeDataUrl}
                  alt="2FA QR Code"
                  className="rounded-md border"
                  width={240}
                  height={240}
                />
                <p className="text-center text-sm text-muted-foreground">
                  {t("twoFactor.scanQr")}
                </p>
              </div>
              <div className="space-y-1">
                <Label className="text-xs">{t("twoFactor.manualEntry")}</Label>
                <code className="block rounded-md bg-muted p-2 text-xs break-all">
                  {setupData.secret}
                </code>
              </div>
              <div className="space-y-2">
                <Label htmlFor="verifyCode">{t("twoFactor.enterCode")}</Label>
                <Input
                  id="verifyCode"
                  type="text"
                  inputMode="numeric"
                  autoComplete="one-time-code"
                  placeholder="123456"
                  maxLength={6}
                  value={verifyCode}
                  onChange={(e) => setVerifyCode(e.target.value)}
                  disabled={setupLoading}
                  autoFocus
                />
              </div>
              <DialogFooter>
                <Button variant="outline" onClick={handleCloseEnableDialog} disabled={setupLoading}>
                  {t("twoFactor.cancel")}
                </Button>
                <Button onClick={handleVerifySetup} disabled={setupLoading || !verifyCode.trim()}>
                  {setupLoading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
                  {t("twoFactor.verify")}
                </Button>
              </DialogFooter>
            </div>
          ) : null}

          {setupStep === "backup" ? (
            <div className="space-y-4">
              <div className="rounded-md border border-amber-200 bg-amber-50 p-3 dark:border-amber-900 dark:bg-amber-950">
                <p className="flex items-start gap-1.5 text-xs text-amber-800 dark:text-amber-200">
                  <AlertCircle className="mt-0.5 h-3.5 w-3.5 flex-shrink-0" />
                  {t("twoFactor.backupWarning")}
                </p>
              </div>
              <div className="space-y-2">
                <div className="flex items-center justify-between">
                  <Label>{t("twoFactor.backupCodes")}</Label>
                  <Button
                    type="button"
                    variant="ghost"
                    size="sm"
                    onClick={handleCopyBackupCodes}
                    className="h-7 gap-1.5 text-xs"
                  >
                    {copied ? <Check className="h-3.5 w-3.5" /> : <Copy className="h-3.5 w-3.5" />}
                    {copied ? t("twoFactor.copied") : t("twoFactor.copy")}
                  </Button>
                </div>
                <div className="grid grid-cols-2 gap-2 rounded-md border p-3">
                  {backupCodes.map((code, i) => (
                    <code key={i} className="text-sm font-mono">
                      {code}
                    </code>
                  ))}
                </div>
              </div>
              <DialogFooter>
                <Button onClick={handleCloseEnableDialog}>
                  {t("twoFactor.done")}
                </Button>
              </DialogFooter>
            </div>
          ) : null}

          {setupStep === "idle" ? (
            <div className="flex items-center justify-center py-8">
              <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
            </div>
          ) : null}
        </DialogContent>
      </Dialog>

      {/* 关闭 2FA Dialog */}
      <Dialog open={disableDialogOpen} onOpenChange={setDisableDialogOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>{t("twoFactor.disableTitle")}</DialogTitle>
            <DialogDescription>{t("twoFactor.disableDescription")}</DialogDescription>
          </DialogHeader>
          <div className="space-y-2">
            <Label htmlFor="disableCode">{t("twoFactor.enterCodeDisable")}</Label>
            <Input
              id="disableCode"
              type="text"
              inputMode="numeric"
              autoComplete="one-time-code"
              placeholder="123456"
              maxLength={8}
              value={disableCode}
              onChange={(e) => setDisableCode(e.target.value)}
              disabled={disableLoading}
              autoFocus
            />
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setDisableDialogOpen(false)} disabled={disableLoading}>
              {t("twoFactor.cancel")}
            </Button>
            <Button
              variant="destructive"
              onClick={handleDisable2FA}
              disabled={disableLoading || !disableCode.trim()}
            >
              {disableLoading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
              {t("twoFactor.disable")}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* 重新生成备份码 Dialog */}
      <Dialog open={regenDialogOpen} onOpenChange={setRegenDialogOpen}>
        <DialogContent className="max-w-md">
          <DialogHeader>
            <DialogTitle>{t("twoFactor.regenerateTitle")}</DialogTitle>
            <DialogDescription>{t("twoFactor.regenerateDescription")}</DialogDescription>
          </DialogHeader>
          {regenBackupCodes.length === 0 ? (
            <>
              <div className="space-y-2">
                <Label htmlFor="regenCode">{t("twoFactor.enterCodeRegen")}</Label>
                <Input
                  id="regenCode"
                  type="text"
                  inputMode="numeric"
                  autoComplete="one-time-code"
                  placeholder="123456"
                  maxLength={6}
                  value={regenCode}
                  onChange={(e) => setRegenCode(e.target.value)}
                  disabled={regenLoading}
                  autoFocus
                />
              </div>
              <DialogFooter>
                <Button variant="outline" onClick={() => setRegenDialogOpen(false)} disabled={regenLoading}>
                  {t("twoFactor.cancel")}
                </Button>
                <Button
                  onClick={handleRegenerateBackupCodes}
                  disabled={regenLoading || !regenCode.trim()}
                >
                  {regenLoading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : null}
                  {t("twoFactor.regenerate")}
                </Button>
              </DialogFooter>
            </>
          ) : (
            <div className="space-y-4">
              <div className="rounded-md border border-amber-200 bg-amber-50 p-3 dark:border-amber-900 dark:bg-amber-950">
                <p className="flex items-start gap-1.5 text-xs text-amber-800 dark:text-amber-200">
                  <AlertCircle className="mt-0.5 h-3.5 w-3.5 flex-shrink-0" />
                  {t("twoFactor.backupWarning")}
                </p>
              </div>
              <div className="grid grid-cols-2 gap-2 rounded-md border p-3">
                {regenBackupCodes.map((code, i) => (
                  <code key={i} className="text-sm font-mono">
                    {code}
                  </code>
                ))}
              </div>
              <DialogFooter>
                <Button onClick={() => setRegenDialogOpen(false)}>
                  {t("twoFactor.done")}
                </Button>
              </DialogFooter>
            </div>
          )}
        </DialogContent>
      </Dialog>
    </div>
  )
}
