import { useCallback, useEffect, useState } from "react"
import { useSearchParams } from "react-router-dom"
import {
  Alert,
  Avatar,
  Button,
  Card,
  Col,
  Form,
  Input,
  InputNumber,
  Progress,
  Radio,
  Row,
  Space,
  Switch,
  Table,
  Tabs,
  Tag,
  Typography,
  message,
  type TableColumnsType,
} from "antd"
import { QRCodeSVG } from "qrcode.react"
import {
  BellOutlined,
  CheckOutlined,
  CloseOutlined,
  EditOutlined,
  KeyOutlined,
  MailOutlined,
  PhoneOutlined,
  SafetyCertificateOutlined,
  UserOutlined,
} from "@ant-design/icons"
import { useAuth } from "../contexts/AuthContext"
import {
  bindEmail,
  bindPhone,
  changePassword,
  sendBindEmailCode,
  sendBindPhoneCode,
  updateProfile,
} from "../api/account"
import {
  getNotificationPreferences,
  updateNotificationPreferences,
  type NotificationPreference,
} from "../api/notifications"
import {
  createRedirectVerificationSession,
  getVerificationOptions,
  getVerificationStatus,
  purchaseVerificationQuota,
  queryRedirectVerificationResult,
  submitThreeFactorVerification,
  submitTwoFactorVerification,
  type VerificationOptions,
  type VerificationStatus,
} from "../api/verification"
import { verifyCaptcha } from "../utils/geetest"
import { PageSkeleton, type SkeletonSpec } from "../utils/skeleton"
import type { User } from "../types"

const { Paragraph, Text, Title } = Typography

const CN_PHONE = /^1[3-9]\d{9}$/
const CN_EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
const REDIRECT_TOKEN_PARAMS = ["BizToken", "bizToken", "biz_token", "external_id", "task_no", "TaskNo", "taskNo", "task_id", "TaskId", "taskId"]

type TabKey = "profile" | "security" | "bindings" | "notifications" | "verification"

function getRedirectExternalId(params: URLSearchParams) {
  for (const key of REDIRECT_TOKEN_PARAMS) {
    const value = params.get(key)
    if (value) return value
  }
  return null
}

const PAGE_SKELETON: SkeletonSpec[] = [
  { type: "header", title: 200, subtitle: 280 },
  { type: "rect", h: 44, rounded: 12 },
  { type: "card", h: 320 },
]

const NOTIFICATION_CATEGORY_LABEL: Record<string, string> = {
  system: "系统通知",
  order: "订单消息",
  instance: "服务器消息",
  finance: "财务消息",
  ticket: "工单消息",
  promotion: "推广活动",
  membership: "会员消息",
  announcement: "平台公告",
}

function maskEmail(s: string) {
  const [u, d] = s.split("@")
  if (!u || !d) return s
  if (u.length <= 2) return `${u[0]}*@${d}`
  return `${u.slice(0, 2)}***${u.slice(-1)}@${d}`
}

function maskPhone(p: string) {
  if (p.length !== 11) return p
  return `${p.slice(0, 3)}****${p.slice(-4)}`
}

function getErrorDetail(err: unknown, fallback: string) {
  const detail = (err as { response?: { data?: { detail?: unknown } } })?.response?.data?.detail
  if (typeof detail === "string") return detail
  if (detail && typeof detail === "object" && "message" in detail) {
    const message = (detail as { message?: unknown }).message
    if (typeof message === "string") return message
  }
  return fallback
}

function formatCents(value?: number | null) {
  return `¥${((value ?? 0) / 100).toFixed(2)}`
}

function useCooldown(initial = 0): [number, (n: number) => void] {
  const [value, setValue] = useState(initial)
  useEffect(() => {
    if (value <= 0) return
    const timer = window.setInterval(() => setValue((v) => (v <= 1 ? 0 : v - 1)), 1000)
    return () => window.clearInterval(timer)
  }, [value])
  return [value, setValue]
}

function SectionTitle({ icon, title }: { icon: React.ReactNode; title: string }) {
  return (
    <Space size={10}>
      {icon}
      <span>{title}</span>
    </Space>
  )
}

function StatusTag({ ok, okLabel, warnLabel }: { ok: boolean; okLabel: string; warnLabel: string }) {
  return ok ? <Tag color="success">{okLabel}</Tag> : <Tag color="warning">{warnLabel}</Tag>
}

export default function Settings() {
  const { user } = useAuth()
  const [searchParams, setSearchParams] = useSearchParams()
  const [tab, setTab] = useState<TabKey>(searchParams.get("tab") === "verification" ? "verification" : "profile")
  const [mounting, setMounting] = useState(true)

  useEffect(() => {
    const timer = window.setTimeout(() => setMounting(false), 350)
    return () => window.clearTimeout(timer)
  }, [])

  useEffect(() => {
    if (searchParams.get("tab") === "verification") setTab("verification")
  }, [searchParams])

  if (!user) return null

  return (
    <PageSkeleton loading={mounting} spec={PAGE_SKELETON}>
      <Space direction="vertical" size={20} className="qycw-page-enter" style={{ width: "100%" }}>
        <div>
          <Title level={3} style={{ marginBottom: 4 }}>账户设置</Title>
          <Paragraph type="secondary" style={{ marginBottom: 0 }}>
            管理您的资料、安全、绑定方式与通知接收偏好。
          </Paragraph>
        </div>

        <Tabs
          activeKey={tab}
          onChange={(key) => {
            const next = key as TabKey
            setTab(next)
            setSearchParams(next === "verification" ? { tab: "verification" } : {}, { replace: true })
          }}
          items={[
            {
              key: "profile",
              label: <Space><UserOutlined />基本资料</Space>,
              children: <ProfilePanel />,
            },
            {
              key: "security",
              label: <Space><SafetyCertificateOutlined />安全</Space>,
              children: <SecurityPanel />,
            },
            {
              key: "bindings",
              label: <Space><MailOutlined />绑定管理</Space>,
              children: <BindingsPanel />,
            },
            {
              key: "notifications",
              label: <Space><BellOutlined />通知</Space>,
              children: <NotificationPreferencesPanel />,
            },
            {
              key: "verification",
              label: <Space><SafetyCertificateOutlined />实名认证</Space>,
              children: <VerificationPanel />,
            },
          ]}
        />
      </Space>
    </PageSkeleton>
  )
}

function ProfilePanel() {
  const { user, setUser } = useAuth()
  const [nickname, setNickname] = useState(user?.nickname || "")
  const [avatar, setAvatar] = useState(user?.avatar || "")
  const [saving, setSaving] = useState(false)

  const dirty = nickname !== (user?.nickname || "") || avatar !== (user?.avatar || "")
  const initial = (user?.nickname || user?.username || "U").charAt(0).toUpperCase()

  const handleSave = async () => {
    if (!dirty) return
    setSaving(true)
    try {
      const res = await updateProfile({
        nickname: nickname || undefined,
        avatar: avatar || undefined,
      })
      if (res.data) {
        setUser(res.data)
        message.success("已保存")
      }
    } catch (err: unknown) {
      message.error(getErrorDetail(err, "保存失败"))
    } finally {
      setSaving(false)
    }
  }

  return (
    <Card
      variant="outlined"
      title={<SectionTitle icon={<UserOutlined />} title="基本资料" />}
    >
      <Row gutter={[24, 24]}>
        <Col xs={24} md={6} lg={5}>
          <Space direction="vertical" align="center" style={{ width: "100%" }}>
            <Avatar size={96} src={avatar || undefined} icon={!avatar ? initial : undefined} />
            <Text type="secondary">头像预览</Text>
          </Space>
        </Col>
        <Col xs={24} md={18} lg={14}>
          <Form layout="vertical">
            <Form.Item label="用户名">
              <Input value={user?.username} disabled />
            </Form.Item>
            <Form.Item label="昵称" required>
              <Input value={nickname} onChange={(e) => setNickname(e.target.value)} placeholder="您希望别人怎么称呼您" />
            </Form.Item>
            <Form.Item label="头像 URL" extra="支持外链图片地址，留空将使用默认头像">
              <Input value={avatar} onChange={(e) => setAvatar(e.target.value)} placeholder="https://..." />
            </Form.Item>
            <Space>
              <Button type="primary" loading={saving} disabled={!dirty} onClick={handleSave}>
                保存修改
              </Button>
              {dirty && !saving && <Text type="secondary">有未保存的修改</Text>}
            </Space>
          </Form>
        </Col>
      </Row>
    </Card>
  )
}

function SecurityPanel() {
  const { user, setUser } = useAuth()
  const hasPassword = user?.has_password ?? false
  const [oldPwd, setOldPwd] = useState("")
  const [newPwd, setNewPwd] = useState("")
  const [confirmPwd, setConfirmPwd] = useState("")
  const [saving, setSaving] = useState(false)

  const checks = [
    { label: "至少 8 个字符", valid: newPwd.length >= 8 },
    { label: "包含字母", valid: /[a-zA-Z]/.test(newPwd) },
    { label: "包含数字", valid: /\d/.test(newPwd) },
  ]
  const passedCount = checks.filter((item) => item.valid).length
  const allValid = passedCount === checks.length
  const confirmMatch = !confirmPwd || confirmPwd === newPwd
  const strengthLabel = newPwd.length === 0 ? "" : passedCount <= 1 ? "弱" : passedCount === 2 ? "中" : "强"
  const progressStatus = passedCount <= 1 ? "exception" : passedCount === 2 ? "normal" : "success"

  const handleSubmit = async () => {
    if (!allValid) {
      message.error("新密码不符合要求")
      return
    }
    if (newPwd !== confirmPwd) {
      message.error("两次输入的新密码不一致")
      return
    }
    setSaving(true)
    try {
      const res = await changePassword({
        old_password: hasPassword ? oldPwd : undefined,
        new_password: newPwd,
      })
      if (res.data) setUser(res.data as User)
      message.success(hasPassword ? "密码已修改" : "密码已设置")
      setOldPwd("")
      setNewPwd("")
      setConfirmPwd("")
    } catch (err: unknown) {
      message.error(getErrorDetail(err, "操作失败"))
    } finally {
      setSaving(false)
    }
  }

  return (
    <Card
      variant="outlined"
      title={<SectionTitle icon={<KeyOutlined />} title={hasPassword ? "修改登录密码" : "设置登录密码"} />}
      extra={<StatusTag ok={hasPassword} okLabel="已设置" warnLabel="未设置" />}
    >
      <Form layout="vertical" style={{ maxWidth: 560 }}>
        {hasPassword && (
          <Form.Item label="当前密码" required>
            <Input.Password value={oldPwd} onChange={(e) => setOldPwd(e.target.value)} placeholder="请输入当前密码" />
          </Form.Item>
        )}
        <Form.Item label="新密码" required>
          <Input.Password value={newPwd} onChange={(e) => setNewPwd(e.target.value)} placeholder="至少 8 位，含字母与数字" />
        </Form.Item>
        {newPwd.length > 0 && (
          <Space direction="vertical" size={8} style={{ width: "100%", marginBottom: 18 }}>
            <Space style={{ width: "100%" }}>
              <Progress
                percent={(passedCount / checks.length) * 100}
                showInfo={false}
                status={progressStatus}
                style={{ width: 220 }}
              />
              <Text type={progressStatus === "exception" ? "danger" : undefined}>{strengthLabel}</Text>
            </Space>
            <Space wrap>
              {checks.map((item) => (
                <Tag key={item.label} color={item.valid ? "success" : "default"} icon={item.valid ? <CheckOutlined /> : <CloseOutlined />}>
                  {item.label}
                </Tag>
              ))}
            </Space>
          </Space>
        )}
        <Form.Item
          label="确认新密码"
          required
          validateStatus={confirmMatch ? undefined : "error"}
          help={confirmMatch ? undefined : "两次输入的密码不一致"}
        >
          <Input.Password value={confirmPwd} onChange={(e) => setConfirmPwd(e.target.value)} placeholder="再次输入新密码" />
        </Form.Item>
        <Button type="primary" loading={saving} onClick={handleSubmit}>
          {hasPassword ? "修改密码" : "设置密码"}
        </Button>
      </Form>
    </Card>
  )
}

function BindingsPanel() {
  return (
    <Row gutter={[16, 16]}>
      <Col xs={24} lg={12}>
        <EmailBindCard />
      </Col>
      <Col xs={24} lg={12}>
        <PhoneBindCard />
      </Col>
    </Row>
  )
}

function EmailBindCard() {
  const { user, setUser } = useAuth()
  const [editing, setEditing] = useState(false)
  const [email, setEmail] = useState("")
  const [code, setCode] = useState("")
  const [cooldown, setCooldown] = useCooldown()
  const [sending, setSending] = useState(false)
  const [saving, setSaving] = useState(false)
  const bound = !!user?.email

  const cancel = () => {
    setEditing(false)
    setEmail("")
    setCode("")
    setCooldown(0)
  }

  const handleSend = async () => {
    if (!email || !CN_EMAIL.test(email)) {
      message.error("请输入有效邮箱")
      return
    }
    setSending(true)
    try {
      const captcha = await verifyCaptcha()
      const res = await sendBindEmailCode(email, captcha)
      setCooldown(res.data?.cooldown ?? 60)
      message.success("验证码已发送至新邮箱")
    } catch (err: unknown) {
      message.error(getErrorDetail(err, err instanceof Error ? err.message : "发送失败"))
    } finally {
      setSending(false)
    }
  }

  const handleSubmit = async () => {
    setSaving(true)
    try {
      const res = await bindEmail(email, code)
      if (res.data) {
        setUser(res.data)
        message.success(bound ? "邮箱已换绑" : "邮箱已绑定")
        cancel()
      }
    } catch (err: unknown) {
      message.error(getErrorDetail(err, "绑定失败"))
    } finally {
      setSaving(false)
    }
  }

  return (
    <Card
      variant="outlined"
      title={<SectionTitle icon={<MailOutlined />} title="邮箱" />}
      extra={
        <Space>
          <StatusTag ok={bound} okLabel="已绑定" warnLabel="未绑定" />
          {!editing && (
            <Button size="small" icon={<EditOutlined />} onClick={() => setEditing(true)}>
              {bound ? "更换" : "绑定"}
            </Button>
          )}
        </Space>
      }
    >
      <Paragraph type="secondary">
        {user?.email ? maskEmail(user.email) : "用于接收账单与重要通知"}
      </Paragraph>
      {editing && (
        <Form layout="vertical">
          <Form.Item label={bound ? "新邮箱" : "邮箱"} required>
            <Input value={email} onChange={(e) => setEmail(e.target.value)} placeholder="you@example.com" />
          </Form.Item>
          <Form.Item label="邮箱验证码" required>
            <Space.Compact style={{ width: "100%" }}>
              <Input
                value={code}
                onChange={(e) => setCode(e.target.value.replace(/\D/g, "").slice(0, 6))}
                placeholder="6 位数字"
                maxLength={6}
              />
              <Button loading={sending} disabled={cooldown > 0} onClick={handleSend}>
                {cooldown > 0 ? `${cooldown}s 后重试` : "获取验证码"}
              </Button>
            </Space.Compact>
          </Form.Item>
          <Space>
            <Button type="primary" loading={saving} onClick={handleSubmit}>确认</Button>
            <Button onClick={cancel}>取消</Button>
          </Space>
        </Form>
      )}
    </Card>
  )
}

function PhoneBindCard() {
  const { user, setUser } = useAuth()
  const [editing, setEditing] = useState(false)
  const [phone, setPhone] = useState("")
  const [code, setCode] = useState("")
  const [cooldown, setCooldown] = useCooldown()
  const [sending, setSending] = useState(false)
  const [saving, setSaving] = useState(false)
  const bound = !!user?.phone

  const cancel = () => {
    setEditing(false)
    setPhone("")
    setCode("")
    setCooldown(0)
  }

  const handleSend = async () => {
    if (!CN_PHONE.test(phone)) {
      message.error("请输入有效手机号")
      return
    }
    setSending(true)
    try {
      const captcha = await verifyCaptcha()
      const res = await sendBindPhoneCode(phone, captcha)
      setCooldown(res.data?.cooldown ?? 60)
      message.success("验证码已发送至新手机")
    } catch (err: unknown) {
      message.error(getErrorDetail(err, err instanceof Error ? err.message : "发送失败"))
    } finally {
      setSending(false)
    }
  }

  const handleSubmit = async () => {
    setSaving(true)
    try {
      const res = await bindPhone(phone, code)
      if (res.data) {
        setUser(res.data)
        message.success(bound ? "手机号已换绑" : "手机号已绑定")
        cancel()
      }
    } catch (err: unknown) {
      message.error(getErrorDetail(err, "绑定失败"))
    } finally {
      setSaving(false)
    }
  }

  return (
    <Card
      variant="outlined"
      title={<SectionTitle icon={<PhoneOutlined />} title="手机号" />}
      extra={
        <Space>
          <StatusTag ok={bound} okLabel="已绑定" warnLabel="未绑定" />
          {!editing && (
            <Button size="small" icon={<EditOutlined />} onClick={() => setEditing(true)}>
              {bound ? "更换" : "绑定"}
            </Button>
          )}
        </Space>
      }
    >
      <Paragraph type="secondary">
        {user?.phone ? maskPhone(user.phone) : "用于登录与安全验证"}
      </Paragraph>
      {editing && (
        <Form layout="vertical">
          <Form.Item label={bound ? "新手机号" : "手机号"} required>
            <Input
              value={phone}
              onChange={(e) => setPhone(e.target.value.replace(/\D/g, "").slice(0, 11))}
              placeholder="11 位手机号"
              maxLength={11}
            />
          </Form.Item>
          <Form.Item label="短信验证码" required>
            <Space.Compact style={{ width: "100%" }}>
              <Input
                value={code}
                onChange={(e) => setCode(e.target.value.replace(/\D/g, "").slice(0, 6))}
                placeholder="6 位数字"
                maxLength={6}
              />
              <Button loading={sending} disabled={cooldown > 0} onClick={handleSend}>
                {cooldown > 0 ? `${cooldown}s 后重试` : "获取验证码"}
              </Button>
            </Space.Compact>
          </Form.Item>
          <Space>
            <Button type="primary" loading={saving} onClick={handleSubmit}>确认</Button>
            <Button onClick={cancel}>取消</Button>
          </Space>
        </Form>
      )}
    </Card>
  )
}

function NotificationPreferencesPanel() {
  const [items, setItems] = useState<NotificationPreference[]>([])
  const [loading, setLoading] = useState(true)
  const [saving, setSaving] = useState(false)

  useEffect(() => {
    let active = true
    getNotificationPreferences()
      .then((data) => {
        if (active) setItems(data)
      })
      .catch(() => message.error("通知偏好加载失败"))
      .finally(() => {
        if (active) setLoading(false)
      })
    return () => { active = false }
  }, [])

  const updateItem = (category: string, key: keyof Omit<NotificationPreference, "category">, value: boolean) => {
    setItems((list) => list.map((item) => item.category === category ? { ...item, [key]: value } : item))
  }

  const handleSave = async () => {
    setSaving(true)
    try {
      const data = await updateNotificationPreferences(items)
      setItems(data)
      message.success("通知偏好已保存")
    } catch {
      message.error("保存失败")
    } finally {
      setSaving(false)
    }
  }

  const columns: TableColumnsType<NotificationPreference> = [
    {
      title: "类型",
      dataIndex: "category",
      render: (value: string) => <Text strong>{NOTIFICATION_CATEGORY_LABEL[value] || value}</Text>,
    },
    {
      title: "站内信",
      align: "center",
      render: (_, record) => (
        <Switch
          checked={record.in_app_enabled}
          onChange={(checked) => updateItem(record.category, "in_app_enabled", checked)}
        />
      ),
    },
    {
      title: "邮件",
      align: "center",
      render: (_, record) => (
        <Switch
          checked={record.email_enabled}
          onChange={(checked) => updateItem(record.category, "email_enabled", checked)}
        />
      ),
    },
    {
      title: "短信",
      align: "center",
      render: (_, record) => (
        <Switch
          checked={record.sms_enabled}
          onChange={(checked) => updateItem(record.category, "sms_enabled", checked)}
        />
      ),
    },
  ]

  return (
    <Card
      variant="outlined"
      title={<SectionTitle icon={<BellOutlined />} title="通知偏好" />}
      extra={
        <Button type="primary" loading={saving} disabled={loading} onClick={handleSave}>
          保存偏好
        </Button>
      }
    >
      <Table
        rowKey="category"
        loading={loading}
        columns={columns}
        dataSource={items}
        pagination={false}
        size="middle"
      />
    </Card>
  )
}

function VerificationPanel() {
  const [searchParams, setSearchParams] = useSearchParams()
  const [form] = Form.useForm<{ real_name: string; id_card_no: string; phone?: string }>()
  const [status, setStatus] = useState<VerificationStatus | null>(null)
  const [options, setOptions] = useState<VerificationOptions | null>(null)
  const [mode, setMode] = useState("two_factor")
  const [loading, setLoading] = useState(true)
  const [submitting, setSubmitting] = useState(false)
  const [purchasing, setPurchasing] = useState(false)
  const [purchaseCount, setPurchaseCount] = useState(1)
  const [checkingRedirect, setCheckingRedirect] = useState(false)
  const [redirectUrl, setRedirectUrl] = useState<string | null>(null)
  const [redirectExternalId, setRedirectExternalId] = useState<string | null>(null)
  const [redirectRecordId, setRedirectRecordId] = useState<number | null>(null)

  const load = useCallback(async () => {
    setLoading(true)
    try {
      const [statusRes, optionsRes] = await Promise.all([
        getVerificationStatus(),
        getVerificationOptions(),
      ])
      const nextStatus = statusRes.data ?? null
      const nextOptions = optionsRes.data ?? null
      const publicModes = (nextOptions?.supported_modes ?? []).filter((item) => item !== "face_api")
      const defaultMode = nextOptions?.default_mode && nextOptions.default_mode !== "face_api"
        ? nextOptions.default_mode
        : publicModes[0]
      setStatus(nextStatus)
      setOptions(nextOptions)
      setMode(defaultMode || "two_factor")
    } catch (err: unknown) {
      message.error(getErrorDetail(err, "实名认证状态加载失败"))
    } finally {
      setLoading(false)
    }
  }, [])

  const checkRedirectResult = useCallback(async (externalId?: string | null, recordId?: number | null) => {
    setCheckingRedirect(true)
    try {
      const res = await queryRedirectVerificationResult({
        external_id: externalId || redirectExternalId,
        record_id: recordId ?? redirectRecordId,
      })
      const result = res.data
      if (result?.passed) {
        message.success("实名认证已通过")
        form.resetFields()
        setRedirectUrl(null)
        setRedirectExternalId(null)
        setRedirectRecordId(null)
      } else if (result?.status === "processing" || result?.status === "pending") {
        message.info(result.reason || "认证尚未完成，请完成后再刷新")
      } else {
        message.error(result?.reject_reason || result?.reason || "实名认证未通过")
      }
      await load()
    } catch (err: unknown) {
      message.error(getErrorDetail(err, "认证结果查询失败"))
    } finally {
      setCheckingRedirect(false)
    }
  }, [form, load, redirectExternalId, redirectRecordId])

  useEffect(() => {
    void load()
  }, [load])

  useEffect(() => {
    const externalId = getRedirectExternalId(searchParams)
    if (!externalId) return
    setRedirectExternalId(externalId)
    void checkRedirectResult(externalId, null)

    const next = new URLSearchParams(searchParams)
    for (const key of REDIRECT_TOKEN_PARAMS) next.delete(key)
    next.set("tab", "verification")
    setSearchParams(next, { replace: true })
  }, [checkRedirectResult, searchParams, setSearchParams])

  const submit = async () => {
    let values: { real_name: string; id_card_no: string; phone?: string }
    try {
      values = await form.validateFields()
    } catch {
      return
    }
    setSubmitting(true)
    try {
      if (mode === "face_redirect") {
        const res = await createRedirectVerificationSession({
          real_name: values.real_name,
          id_card_no: values.id_card_no,
          return_url: `${window.location.origin}/settings?tab=verification`,
        })
        setRedirectUrl(res.data?.url || res.data?.qr_payload || null)
        setRedirectExternalId(res.data?.external_id || null)
        setRedirectRecordId(res.data?.record_id ?? null)
        await load()
        message.success("认证链接已生成")
        return
      }
      const res = mode === "three_factor"
        ? await submitThreeFactorVerification({ real_name: values.real_name, id_card_no: values.id_card_no, phone: values.phone || "" })
        : await submitTwoFactorVerification({ real_name: values.real_name, id_card_no: values.id_card_no })
      if (res.data?.passed) {
        message.success("实名认证已通过")
        form.resetFields()
        setRedirectUrl(null)
        setRedirectExternalId(null)
        setRedirectRecordId(null)
      } else {
        message.error(res.data?.reject_reason || "实名认证未通过")
      }
      await load()
    } catch (err: unknown) {
      message.error(getErrorDetail(err, "实名认证提交失败"))
    } finally {
      setSubmitting(false)
    }
  }

  const buyQuota = async () => {
    setPurchasing(true)
    try {
      const res = await purchaseVerificationQuota({ count: purchaseCount })
      message.success(`已购买 ${res.data?.purchased_count ?? purchaseCount} 次实名认证次数`)
      await load()
    } catch (err: unknown) {
      message.error(getErrorDetail(err, "实名认证次数购买失败"))
    } finally {
      setPurchasing(false)
    }
  }

  const modeOptions = (options?.supported_modes ?? []).filter((item) => item !== "face_api").map((item) => ({
    value: item,
    label: item === "two_factor" ? "二要素" : item === "three_factor" ? "三要素" : item === "face_redirect" ? "扫脸跳转" : item,
  }))

  const verified = status?.status === "verified"
  const rejected = status?.status === "rejected"
  const quota = status?.quota
  const priceCents = quota?.price_cents ?? options?.quota?.price_cents ?? 0
  const purchaseEnabled = quota?.purchase_enabled ?? options?.quota?.purchase_enabled ?? false
  const remainingTotal = quota?.remaining_total ?? 0

  return (
    <Card
      loading={loading}
      variant="outlined"
      title={<SectionTitle icon={<SafetyCertificateOutlined />} title="实名认证" />}
      extra={<StatusTag ok={!!verified} okLabel="已实名" warnLabel={status?.status === "pending" ? "认证中" : "未实名"} />}
    >
      <Space direction="vertical" size={16} style={{ width: "100%" }}>
        {verified && (
          <Alert
            type="success"
            showIcon
            message="实名认证已完成"
            description={(
              <Space wrap>
                {status?.real_name && <Tag>{status.real_name}</Tag>}
                {status?.id_card_no && <Tag>{status.id_card_no}</Tag>}
                {status?.verified_at && <Tag>{new Date(status.verified_at).toLocaleString()}</Tag>}
              </Space>
            )}
          />
        )}
        {rejected && status?.reject_reason && (
          <Alert type="warning" showIcon message="上次认证未通过" description={status.reject_reason} />
        )}
        {!options?.enabled && (
          <Alert type="info" showIcon message="实名认证暂未启用" />
        )}
        {!verified && options?.enabled && quota && (
          <Alert
            type={remainingTotal > 0 ? "info" : "warning"}
            showIcon
            message={remainingTotal > 0 ? "实名认证次数可用" : "实名认证次数不足"}
            description={(
              <Space direction="vertical" size={8} style={{ width: "100%" }}>
                <Space wrap>
                  <Tag color={quota.free_remaining > 0 ? "green" : undefined}>免费剩余 {quota.free_remaining} 次</Tag>
                  <Tag color={quota.paid_remaining > 0 ? "blue" : undefined}>已购剩余 {quota.paid_remaining} 次</Tag>
                  <Tag>单价 {formatCents(priceCents)} / 次</Tag>
                  <Tag>余额 {formatCents(quota.balance_cents)}</Tag>
                </Space>
                {purchaseEnabled && (
                  <Space wrap>
                    <InputNumber
                      min={1}
                      max={100}
                      value={purchaseCount}
                      onChange={(value) => setPurchaseCount(Number(value || 1))}
                      addonAfter="次"
                      style={{ width: 140 }}
                    />
                    <Button loading={purchasing} onClick={buyQuota}>
                      购买实名次数
                    </Button>
                    <Text type="secondary">合计 {formatCents(priceCents * purchaseCount)}</Text>
                  </Space>
                )}
              </Space>
            )}
          />
        )}

        {!verified && options?.enabled && (
          <Form form={form} layout="vertical" style={{ maxWidth: 620 }}>
            {modeOptions.length > 0 && (
              <Form.Item label="核验方式">
                <Radio.Group
                  optionType="button"
                  buttonStyle="solid"
                  value={mode}
                  options={modeOptions}
                  onChange={(event) => {
                    setMode(event.target.value)
                    setRedirectUrl(null)
                    setRedirectExternalId(null)
                    setRedirectRecordId(null)
                  }}
                />
              </Form.Item>
            )}
            <Form.Item
              label="真实姓名"
              name="real_name"
              rules={[{ required: true, message: "请输入真实姓名" }, { min: 2, message: "姓名至少 2 个字符" }]}
            >
              <Input placeholder="真实姓名" />
            </Form.Item>
            <Form.Item
              label="身份证号"
              name="id_card_no"
              rules={[
                { required: true, message: "请输入身份证号" },
                { pattern: /^[\dXx]{15,18}$/, message: "请输入有效身份证号" },
              ]}
            >
              <Input placeholder="身份证号" maxLength={18} />
            </Form.Item>
            {mode === "three_factor" && (
              <Form.Item
                label="手机号"
                name="phone"
                rules={[
                  { required: true, message: "请输入手机号" },
                  { pattern: /^1[3-9]\d{9}$/, message: "请输入有效手机号" },
                ]}
              >
                <Input placeholder="手机号" maxLength={11} />
              </Form.Item>
            )}
            {mode === "face_redirect" && redirectUrl && (
              <Form.Item label="扫码认证">
                <Card size="small" variant="outlined" style={{ maxWidth: 320 }}>
                  <Space direction="vertical" size={12} align="center" style={{ width: "100%" }}>
                    <div style={{ padding: 12, background: "#fff", border: "1px solid #f0f0f0", borderRadius: 8 }}>
                      <QRCodeSVG value={redirectUrl} size={188} level="M" includeMargin />
                    </div>
                    <Text strong>请使用手机扫码进行人脸识别</Text>
                    <Text type="secondary" style={{ textAlign: "center" }}>
                      完成后回到本页刷新认证结果。
                    </Text>
                    <Space wrap>
                      <Button type="primary" loading={checkingRedirect} onClick={() => checkRedirectResult()}>
                        刷新认证结果
                      </Button>
                      <Button onClick={() => window.open(redirectUrl, "_blank", "noopener,noreferrer")}>
                        打开链接
                      </Button>
                    </Space>
                  </Space>
                </Card>
              </Form.Item>
            )}
            {mode === "face_redirect" && !redirectUrl && (redirectExternalId || redirectRecordId || status?.status === "pending") && (
              <Form.Item>
                <Button loading={checkingRedirect} onClick={() => checkRedirectResult()}>
                  刷新认证结果
                </Button>
              </Form.Item>
            )}
            <Button type="primary" loading={submitting} disabled={!!quota && remainingTotal <= 0} onClick={submit}>
              {mode === "face_redirect" ? "生成扫码二维码" : "提交认证"}
            </Button>
          </Form>
        )}
      </Space>
    </Card>
  )
}
