import { useCallback, useEffect, useState } from 'react'
import {
  Alert,
  Avatar,
  Button,
  Checkbox,
  Col,
  Form,
  Input,
  Modal,
  Popconfirm,
  Row,
  Space,
  Table,
  Tag,
  Typography,
  Upload,
  message,
  type TableColumnsType,
} from 'antd'
import {
  CheckCircleOutlined,
  DesktopOutlined,
  LockOutlined,
  SafetyOutlined,
  UploadOutlined,
  UserOutlined,
  CheckOutlined,
} from '@ant-design/icons'
import type { RcFile } from 'antd/es/upload'
import dayjs from 'dayjs'
import { useAuth } from '@/app/providers/auth-context'
import { getErrorMessage } from '@/lib/errors'
import { parseOAuthCallbackHash, validateOAuthUrl } from '@/lib/auth/oauth'
import { getDeviceFingerprint } from '@/lib/device-fingerprint'
import { PageLayout, ContentCard } from '@/components/layout'
import { PageHeader } from '@/components/common'
import { getAuthCapabilities } from '@/services/auth'
import { listSocialAccounts, startSocialBinding, unbindSocialAccount } from '@/services/social-accounts'
import {
  disableTOTP,
  enableTOTP,
  getTOTPSetup,
  getTOTPStatus,
  updatePassword,
  uploadAvatar,
} from '@/services/profile'
import { deleteDevice, listDevices, trustDevice, trustDeviceByDeviceId, untrustDevice, updateDeviceStatus } from '@/services/devices'
import { listMyLoginLogs } from '@/services/login-logs'
import { listMyOperationLogs } from '@/services/operation-logs'
import { ContactBindingsSection } from './ContactBindingsSection'
import {
  DeviceStatusColor,
  DeviceStatusText,
  DeviceTypeText,
  type Device,
} from '@/types/device'
import { LoginStatusColor, LoginStatusText, LoginTypeText, type LoginLog } from '@/types/login-log'
import type { OperationLog } from '@/types/operation-log'
import type { OAuthProviderInfo, SocialAccountInfo } from '@/types'

const { Text } = Typography

interface PasswordFormValues {
  current_password: string
  new_password: string
  confirm_password: string
}

interface SocialVerificationFormValues {
  current_password?: string
  totp_code?: string
}

export function ProfileSecurityPage() {
  const { user, refreshUser } = useAuth()
  const [passwordForm] = Form.useForm<PasswordFormValues>()
  const [bindSocialForm] = Form.useForm<SocialVerificationFormValues>()
  const [unbindSocialForm] = Form.useForm<SocialVerificationFormValues>()
  const [passwordLoading, setPasswordLoading] = useState(false)
  const [avatarLoading, setAvatarLoading] = useState(false)
  const [totpLoading, setTotpLoading] = useState(false)
  const [setupVisible, setSetupVisible] = useState(false)
  const [disableVisible, setDisableVisible] = useState(false)
  const [totpCode, setTotpCode] = useState('')
  const [disableCode, setDisableCode] = useState('')
  const [totpEnabled, setTotpEnabled] = useState(false)
  const [totpSetup, setTotpSetup] = useState<{
    secret: string
    qr_code_base64: string
    recovery_codes: string[]
  } | null>(null)
  const [totpRememberDevice, setTotpRememberDevice] = useState(false)
  const [devicesLoading, setDevicesLoading] = useState(true)
  const [devices, setDevices] = useState<Device[]>([])
  const [loginLogs, setLoginLogs] = useState<LoginLog[]>([])
  const [operationLogs, setOperationLogs] = useState<OperationLog[]>([])
  const [logsLoading, setLogsLoading] = useState(true)
  const [socialLoading, setSocialLoading] = useState(true)
  const [socialAccounts, setSocialAccounts] = useState<SocialAccountInfo[]>([])
  const [oauthProviders, setOAuthProviders] = useState<OAuthProviderInfo[]>([])
  const [emailBindingEnabled, setEmailBindingEnabled] = useState(false)
  const [phoneBindingEnabled, setPhoneBindingEnabled] = useState(false)
  const [bindVisible, setBindVisible] = useState(false)
  const [unbindVisible, setUnbindVisible] = useState(false)
  const [socialSubmitting, setSocialSubmitting] = useState(false)
  const [activeProvider, setActiveProvider] = useState<string | null>(null)

  const fetchSecurityData = useCallback(async () => {
    if (!user) {
      return
    }

    try {
      setDevicesLoading(true)
      setLogsLoading(true)
      setSocialLoading(true)
      const [deviceResult, totpStatus, loginLogResult, operationLogResult, socialAccountResult, authCapabilities] = await Promise.all([
        listDevices({ page: 1, page_size: 20 }),
        getTOTPStatus(),
        listMyLoginLogs({ page: 1, page_size: 5 }),
        listMyOperationLogs({ page: 1, page_size: 5 }),
        listSocialAccounts(),
        getAuthCapabilities(),
      ])

      setDevices(deviceResult.items)
      setTotpEnabled(totpStatus.totp_enabled)
      setLoginLogs(loginLogResult.items)
      setOperationLogs(operationLogResult.items)
      setSocialAccounts(socialAccountResult)
      setOAuthProviders(authCapabilities.oauth_providers)
      setEmailBindingEnabled(authCapabilities.email_code)
      setPhoneBindingEnabled(authCapabilities.sms_code)
    } catch (error) {
      message.error(getErrorMessage(error, '获取安全设置失败'))
    } finally {
      setDevicesLoading(false)
      setLogsLoading(false)
      setSocialLoading(false)
    }
  }, [user])

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

  const getProviderLabel = useCallback((provider: string) => {
    const match = oauthProviders.find((item) => item.provider === provider)
    return match?.name || provider
  }, [oauthProviders])

  useEffect(() => {
    if (!window.location.hash) {
      return
    }

    const callbackResult = parseOAuthCallbackHash(window.location.hash)
    if (!callbackResult.status || !callbackResult.provider) {
      return
    }

    const nextUrl = `${window.location.pathname}${window.location.search}`
    window.history.replaceState(window.history.state, document.title, nextUrl)

    if (callbackResult.status === 'success') {
      const providerLabel = getProviderLabel(callbackResult.provider)
      message.success(callbackResult.message || `${providerLabel} 绑定成功`)
      void fetchSecurityData()
      return
    }

    message.error(callbackResult.message || `${getProviderLabel(callbackResult.provider)} 绑定失败`)
  }, [fetchSecurityData, getProviderLabel])

  const openBindModal = (provider: string) => {
    bindSocialForm.resetFields()
    setActiveProvider(provider)
    setBindVisible(true)
  }

  const openUnbindModal = (provider: string) => {
    unbindSocialForm.resetFields()
    setActiveProvider(provider)
    setUnbindVisible(true)
  }

  const handleStartSocialBinding = async (values: SocialVerificationFormValues) => {
    if (!activeProvider) {
      return
    }

    try {
      setSocialSubmitting(true)
      const result = await startSocialBinding({
        provider: activeProvider,
        return_to: `${window.location.pathname}${window.location.search}`,
        current_password: values.current_password?.trim() || undefined,
        totp_code: values.totp_code?.trim() || undefined,
      })

      // 验证 OAuth URL origin 防止开放重定向攻击
      if (!validateOAuthUrl(result.auth_url)) {
        throw new Error('Invalid OAuth authorization URL')
      }

      setBindVisible(false)
      setActiveProvider(null)
      bindSocialForm.resetFields()
      window.location.assign(result.auth_url)
    } catch (error) {
      message.error(getErrorMessage(error, '发起社交账号绑定失败'))
    } finally {
      setSocialSubmitting(false)
    }
  }

  const handleConfirmUnbind = async (values: SocialVerificationFormValues) => {
    if (!activeProvider) {
      return
    }

    try {
      setSocialSubmitting(true)
      await unbindSocialAccount(activeProvider, {
        current_password: values.current_password?.trim() || undefined,
        totp_code: values.totp_code?.trim() || undefined,
      })
      setUnbindVisible(false)
      setActiveProvider(null)
      unbindSocialForm.resetFields()
      message.success(`${getProviderLabel(activeProvider)} 已解绑`)
      await fetchSecurityData()
    } catch (error) {
      message.error(getErrorMessage(error, '解绑社交账号失败'))
    } finally {
      setSocialSubmitting(false)
    }
  }

  const handlePasswordSubmit = async (values: PasswordFormValues) => {
    if (!user) {
      return
    }

    try {
      setPasswordLoading(true)
      await updatePassword(user.id, values)
      passwordForm.resetFields()
      message.success('密码修改成功')
    } catch (error) {
      message.error(getErrorMessage(error, '密码修改失败'))
    } finally {
      setPasswordLoading(false)
    }
  }

  const handleAvatarUpload = async (file: RcFile) => {
    if (!user) {
      return false
    }

    const isImage = file.type.startsWith('image/')
    if (!isImage) {
      message.error('只能上传图片文件')
      return false
    }

    const isLt2M = file.size / 1024 / 1024 < 2
    if (!isLt2M) {
      message.error('图片大小不能超过 2MB')
      return false
    }

    try {
      setAvatarLoading(true)
      await uploadAvatar(user.id, file)
      await refreshUser()
      message.success('头像上传成功')
    } catch (error) {
      message.error(getErrorMessage(error, '头像上传失败'))
    } finally {
      setAvatarLoading(false)
    }

    return false
  }

  const handleOpenTOTPSetup = async () => {
    try {
      setTotpLoading(true)
      const data = await getTOTPSetup()
      setTotpSetup(data)
      setTotpCode('')
      setSetupVisible(true)
    } catch (error) {
      message.error(getErrorMessage(error, '获取 TOTP 设置信息失败'))
    } finally {
      setTotpLoading(false)
    }
  }

  const handleEnableTOTP = async () => {
    if (totpCode.length !== 6) {
      message.error('请输入 6 位验证码')
      return
    }

    try {
      setTotpLoading(true)
      await enableTOTP(totpCode)
      // If "remember device" is checked, trust the current device
      if (totpRememberDevice) {
        try {
          const deviceInfo = getDeviceFingerprint()
          await trustDeviceByDeviceId(deviceInfo.device_id, '30d')
        } catch {
          // Non-critical: device trust failed, but TOTP was enabled
        }
      }
      setTotpEnabled(true)
      setSetupVisible(false)
      setTotpRememberDevice(false)
      message.success('TOTP 已启用')
    } catch (error) {
      message.error(getErrorMessage(error, '启用 TOTP 失败'))
    } finally {
      setTotpLoading(false)
    }
  }

  const handleDisableTOTP = async () => {
    if (!disableCode) {
      message.error('请输入验证码或恢复码')
      return
    }

    try {
      setTotpLoading(true)
      await disableTOTP(disableCode)
      setTotpEnabled(false)
      setDisableVisible(false)
      setDisableCode('')
      message.success('TOTP 已禁用')
    } catch (error) {
      message.error(getErrorMessage(error, '禁用 TOTP 失败'))
    } finally {
      setTotpLoading(false)
    }
  }

  const handleToggleDeviceStatus = async (device: Device) => {
    const nextStatus = device.status === 1 ? 0 : 1

    try {
      await updateDeviceStatus(device.id, nextStatus)
      message.success(nextStatus === 1 ? '设备已重新激活' : '设备已禁用')
      await fetchSecurityData()
    } catch (error) {
      message.error(getErrorMessage(error, '更新设备状态失败'))
    }
  }

  const handleDeleteDevice = async (deviceId: number) => {
    try {
      await deleteDevice(deviceId)
      message.success('设备已删除')
      await fetchSecurityData()
    } catch (error) {
      message.error(getErrorMessage(error, '删除设备失败'))
    }
  }

  const handleTrustDevice = async (device: Device) => {
    try {
      await trustDevice(device.id, '30d')
      message.success('设备已设为信任，30天内无需二次验证')
      await fetchSecurityData()
    } catch (error) {
      message.error(getErrorMessage(error, '信任设备失败'))
    }
  }

  const handleUntrustDevice = async (device: Device) => {
    try {
      await untrustDevice(device.id)
      message.success('已取消设备信任')
      await fetchSecurityData()
    } catch (error) {
      message.error(getErrorMessage(error, '取消信任失败'))
    }
  }

  const boundProviderSet = new Set(socialAccounts.map((account) => account.provider))
  const availableSocialProviders = oauthProviders.filter((provider) => !boundProviderSet.has(provider.provider))

  const socialAccountColumns: TableColumnsType<SocialAccountInfo> = [
    {
      title: '平台',
      dataIndex: 'provider',
      key: 'provider',
      render: (value: string) => getProviderLabel(value),
    },
    {
      title: '账号信息',
      key: 'account',
      render: (_, record) => (
        <Space>
          <Avatar size={32} src={record.avatar || undefined} icon={<UserOutlined />} />
          <Space direction="vertical" size={0}>
            <Text strong>{record.nickname || getProviderLabel(record.provider)}</Text>
            <Text type="secondary">{record.provider}</Text>
          </Space>
        </Space>
      ),
    },
    {
      title: '状态',
      dataIndex: 'status',
      key: 'status',
      render: (status: SocialAccountInfo['status']) => (
        <Tag color={status === 1 ? 'success' : status === 2 ? 'error' : 'default'}>
          {status === 1 ? '已绑定' : status === 2 ? '已禁用' : '未激活'}
        </Tag>
      ),
    },
    {
      title: '绑定时间',
      dataIndex: 'created_at',
      key: 'created_at',
      render: (value) => (value ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '-'),
    },
    {
      title: '操作',
      key: 'action',
      render: (_, record) => (
        <Button type="link" danger onClick={() => openUnbindModal(record.provider)}>
          解绑
        </Button>
      ),
    },
  ]

  const deviceColumns: TableColumnsType<Device> = [
    {
      title: '设备',
      key: 'device',
      render: (_, record) => (
        <Space direction="vertical" size={0}>
          <Space>
            <Text strong>{record.device_name || record.device_id}</Text>
            {record.is_trusted && (
              <Tag color="success" icon={<CheckOutlined />}>已信任</Tag>
            )}
          </Space>
          <Text type="secondary">
            {DeviceTypeText[record.device_type]} / {record.device_browser || '-'} / {record.device_os || '-'}
          </Text>
        </Space>
      ),
    },
    {
      title: '状态',
      dataIndex: 'status',
      key: 'status',
      render: (status: Device['status']) => (
        <Tag color={DeviceStatusColor[status]}>{DeviceStatusText[status]}</Tag>
      ),
    },
    {
      title: '信任状态',
      key: 'trusted',
      render: (_, record) => (
        record.is_trusted ? (
          <Text type="success">已信任{record.trust_expires_at ? ` (至 ${dayjs(record.trust_expires_at).format('YYYY-MM-DD')})` : ''}</Text>
        ) : (
          <Text type="secondary">未信任</Text>
        )
      ),
    },
    {
      title: 'IP / 位置',
      key: 'location',
      render: (_, record) => (
        <Space direction="vertical" size={0}>
          <Text code>{record.ip}</Text>
          <Text type="secondary">{record.location || '-'}</Text>
        </Space>
      ),
    },
    {
      title: '最后活跃',
      dataIndex: 'last_active_time',
      key: 'last_active_time',
      render: (value) => (value ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '-'),
    },
    {
      title: '操作',
      key: 'action',
      render: (_, record) => (
        <Space>
          {record.is_trusted ? (
            <Button type="link" size="small" onClick={() => handleUntrustDevice(record)}>
              取消信任
            </Button>
          ) : (
            <Button type="link" size="small" onClick={() => handleTrustDevice(record)}>
              设为信任
            </Button>
          )}
          <Button type="link" size="small" onClick={() => handleToggleDeviceStatus(record)}>
            {record.status === 1 ? '禁用' : '启用'}
          </Button>
          <Popconfirm
            title="确定删除此设备吗？"
            onConfirm={() => handleDeleteDevice(record.id)}
          >
            <Button type="link" size="small" danger>
              删除
            </Button>
          </Popconfirm>
        </Space>
      ),
    },
  ]

  const loginLogColumns: TableColumnsType<LoginLog> = [
    {
      title: '登录类型',
      dataIndex: 'login_type',
      key: 'login_type',
      render: (value: LoginLog['login_type']) => LoginTypeText[value] || value,
    },
    {
      title: '状态',
      dataIndex: 'status',
      key: 'status',
      render: (status: LoginLog['status']) => (
        <Tag color={LoginStatusColor[status]}>{LoginStatusText[status]}</Tag>
      ),
    },
    {
      title: 'IP',
      dataIndex: 'ip',
      key: 'ip',
    },
    {
      title: '位置',
      dataIndex: 'location',
      key: 'location',
      render: (value) => value || '-',
    },
    {
      title: '时间',
      dataIndex: 'created_at',
      key: 'created_at',
      render: (value) => dayjs(value).format('YYYY-MM-DD HH:mm:ss'),
    },
  ]

  const operationLogColumns: TableColumnsType<OperationLog> = [
    {
      title: '操作类型',
      dataIndex: 'operation_type',
      key: 'operation_type',
    },
    {
      title: '操作名称',
      dataIndex: 'operation_name',
      key: 'operation_name',
    },
    {
      title: '方法',
      dataIndex: 'request_method',
      key: 'request_method',
      render: (value) => <Tag>{value}</Tag>,
    },
    {
      title: '状态码',
      dataIndex: 'response_status',
      key: 'response_status',
      render: (value) => (
        <Tag color={value >= 200 && value < 300 ? 'success' : 'error'}>{value}</Tag>
      ),
    },
    {
      title: '时间',
      dataIndex: 'created_at',
      key: 'created_at',
      render: (value) => dayjs(value).format('YYYY-MM-DD HH:mm:ss'),
    },
  ]

  return (
    <PageLayout>
      <PageHeader
        title="安全设置"
        description="维护头像、密码、TOTP、设备和当前账号最近的审计日志"
      />

      <Row gutter={[24, 24]}>
        <Col xs={24} lg={8}>
          <ContentCard
            title={
              <Space>
                <UserOutlined />
                头像
              </Space>
            }
          >
            <Space direction="vertical" align="center" style={{ width: '100%' }}>
              <Avatar size={96} src={user?.avatar || null} icon={<UserOutlined />} />
              <Upload
                accept="image/*"
                showUploadList={false}
                beforeUpload={handleAvatarUpload}
              >
                <Button icon={<UploadOutlined />} loading={avatarLoading}>
                  上传头像
                </Button>
              </Upload>
              <Text type="secondary">后端当前只支持上传，不支持删除或回滚默认头像。</Text>
            </Space>
          </ContentCard>
        </Col>

        <Col xs={24} lg={8}>
          <ContentCard
            title={
              <Space>
                <LockOutlined />
                修改密码
              </Space>
            }
          >
            <Form form={passwordForm} layout="vertical" onFinish={handlePasswordSubmit}>
              <Form.Item
                name="current_password"
                label="当前密码"
                rules={[{ required: true, message: '请输入当前密码' }]}
              >
                <Input.Password placeholder="请输入当前密码" />
              </Form.Item>
              <Form.Item
                name="new_password"
                label="新密码"
                rules={[
                  { required: true, message: '请输入新密码' },
                  { min: 8, message: '密码至少 8 位' },
                ]}
              >
                <Input.Password placeholder="请输入新密码" />
              </Form.Item>
              <Form.Item
                name="confirm_password"
                label="确认新密码"
                dependencies={['new_password']}
                rules={[
                  { required: true, message: '请再次输入新密码' },
                  ({ getFieldValue }) => ({
                    validator(_, value) {
                      if (!value || getFieldValue('new_password') === value) {
                        return Promise.resolve()
                      }
                      return Promise.reject(new Error('两次输入的密码不一致'))
                    },
                  }),
                ]}
              >
                <Input.Password placeholder="请再次输入新密码" />
              </Form.Item>
              <Form.Item style={{ marginBottom: 0 }}>
                <Button type="primary" htmlType="submit" loading={passwordLoading}>
                  修改密码
                </Button>
              </Form.Item>
            </Form>
          </ContentCard>
        </Col>

        <Col xs={24} lg={8}>
          <ContentCard
            title={
              <Space>
                <SafetyOutlined />
                TOTP 双因素认证
              </Space>
            }
          >
            {totpEnabled ? (
              <Space direction="vertical" style={{ width: '100%' }}>
                <Alert
                  type="success"
                  showIcon
                  icon={<CheckCircleOutlined />}
                  message="TOTP 已启用"
                  description="当前账号登录时可以使用动态验证码进行二次验证。"
                />
                <Button danger onClick={() => setDisableVisible(true)}>
                  禁用 TOTP
                </Button>
              </Space>
            ) : (
              <Space direction="vertical" style={{ width: '100%' }}>
                <Alert
                  type="info"
                  showIcon
                  message="TOTP 未启用"
                  description="后端已接入 `/auth/2fa/*`，可以完成真实的初始化、启用和禁用。"
                />
                <Button type="primary" onClick={handleOpenTOTPSetup} loading={totpLoading}>
                  启用 TOTP
                </Button>
              </Space>
            )}
          </ContentCard>
        </Col>
      </Row>

      {user && (
        <ContactBindingsSection
          userId={user.id}
          emailBindingEnabled={emailBindingEnabled}
          phoneBindingEnabled={phoneBindingEnabled}
          refreshSessionUser={refreshUser}
        />
      )}

      <ContentCard title="社交账号绑定" style={{ marginTop: 24 }}>
        <Space direction="vertical" size={16} style={{ width: '100%' }}>
          <Alert
            type="info"
            showIcon
            message="绑定前会校验当前会话身份；解绑时系统会校验密码或 TOTP，并确保至少保留一种登录方式。"
          />

          <div>
            <Text strong>可绑定平台</Text>
            <div style={{ marginTop: 12 }}>
              <Space wrap>
                {availableSocialProviders.map((provider) => (
                  <Button key={provider.provider} onClick={() => openBindModal(provider.provider)}>
                    绑定 {provider.name}
                  </Button>
                ))}
                {availableSocialProviders.length === 0 && (
                  <Text type="secondary">当前没有可新增绑定的平台</Text>
                )}
              </Space>
            </div>
          </div>

          <Table
            rowKey="id"
            dataSource={socialAccounts}
            columns={socialAccountColumns}
            loading={socialLoading}
            pagination={false}
            locale={{ emptyText: '暂无已绑定的社交账号' }}
          />
        </Space>
      </ContentCard>

      <ContentCard
        title={
          <Space>
            <DesktopOutlined />
            我的设备
          </Space>
        }
        style={{ marginTop: 24 }}
      >
        <Table
          rowKey="id"
          dataSource={devices}
          columns={deviceColumns}
          loading={devicesLoading}
          pagination={false}
          locale={{ emptyText: '暂无设备数据' }}
        />
      </ContentCard>

      <Row gutter={[24, 24]} style={{ marginTop: 24 }}>
        <Col xs={24} xl={12}>
          <ContentCard title="我的登录日志">
            <Table
              rowKey="id"
              dataSource={loginLogs}
              columns={loginLogColumns}
              loading={logsLoading}
              pagination={false}
              size="small"
              locale={{ emptyText: '暂无登录日志' }}
            />
          </ContentCard>
        </Col>
        <Col xs={24} xl={12}>
          <ContentCard title="我的操作日志">
            <Table
              rowKey="id"
              dataSource={operationLogs}
              columns={operationLogColumns}
              loading={logsLoading}
              pagination={false}
              size="small"
              locale={{ emptyText: '暂无操作日志' }}
            />
          </ContentCard>
        </Col>
      </Row>

      <Modal
        title={activeProvider ? `绑定 ${getProviderLabel(activeProvider)}` : '绑定社交账号'}
        open={bindVisible}
        onCancel={() => {
          setBindVisible(false)
          setActiveProvider(null)
          bindSocialForm.resetFields()
        }}
        onOk={() => bindSocialForm.submit()}
        confirmLoading={socialSubmitting}
        okText="继续授权"
      >
        <Space direction="vertical" style={{ width: '100%' }}>
          <Alert
            type="info"
            showIcon
            message="如果当前账号已设置密码或 TOTP，请至少提供一种验证方式。纯 OAuth 账号在没有额外因子时会直接使用当前登录会话继续授权。"
          />
          <Form form={bindSocialForm} layout="vertical" onFinish={handleStartSocialBinding}>
            <Form.Item name="current_password" label="当前密码">
              <Input.Password placeholder="有密码时建议填写" />
            </Form.Item>
            <Form.Item name="totp_code" label="TOTP / 恢复码">
              <Input placeholder="已开启 TOTP 时可填写验证码或恢复码" />
            </Form.Item>
          </Form>
        </Space>
      </Modal>

      <Modal
        title={activeProvider ? `解绑 ${getProviderLabel(activeProvider)}` : '解绑社交账号'}
        open={unbindVisible}
        onCancel={() => {
          setUnbindVisible(false)
          setActiveProvider(null)
          unbindSocialForm.resetFields()
        }}
        onOk={() => unbindSocialForm.submit()}
        confirmLoading={socialSubmitting}
        okText="确认解绑"
        okButtonProps={{ danger: true }}
      >
        <Space direction="vertical" style={{ width: '100%' }}>
          <Alert
            type="warning"
            showIcon
            message="解绑前需要验证当前账号身份；如果解绑后没有其他可用登录方式，系统会拒绝本次操作。"
          />
          <Form form={unbindSocialForm} layout="vertical" onFinish={handleConfirmUnbind}>
            <Form.Item name="current_password" label="当前密码">
              <Input.Password placeholder="填写当前密码" />
            </Form.Item>
            <Form.Item name="totp_code" label="TOTP / 恢复码">
              <Input placeholder="或填写 TOTP 验证码 / 恢复码" />
            </Form.Item>
          </Form>
        </Space>
      </Modal>

      <Modal
        title="启用 TOTP"
        open={setupVisible}
        onCancel={() => {
          setSetupVisible(false)
          setTotpCode('')
          setTotpRememberDevice(false)
        }}
        onOk={handleEnableTOTP}
        confirmLoading={totpLoading}
        okText="确认启用"
      >
        {totpSetup && (
          <Space direction="vertical" style={{ width: '100%' }}>
            <Alert
              type="info"
              showIcon
              message="请先使用身份验证器扫码，再输入 6 位验证码完成启用。"
            />
            <div style={{ textAlign: 'center' }}>
              <img
                src={`data:image/png;base64,${totpSetup.qr_code_base64}`}
                alt="TOTP QR Code"
                style={{ maxWidth: 240 }}
              />
            </div>
            <Text copyable>密钥：{totpSetup.secret}</Text>
            {totpSetup.recovery_codes.length > 0 && (
              <div>
                <Text strong>恢复码</Text>
                <div style={{ marginTop: 8 }}>
                  <Space wrap>
                    {totpSetup.recovery_codes.map((code) => (
                      <Tag key={code}>{code}</Tag>
                    ))}
                  </Space>
                </div>
              </div>
            )}
            <Input
              value={totpCode}
              onChange={(event) => setTotpCode(event.target.value.trim())}
              maxLength={6}
              placeholder="请输入 6 位验证码"
            />
            <Checkbox checked={totpRememberDevice} onChange={(e) => setTotpRememberDevice(e.target.checked)}>
              记住此设备，30天内无需二次验证
            </Checkbox>
          </Space>
        )}
      </Modal>

      <Modal
        title="禁用 TOTP"
        open={disableVisible}
        onCancel={() => {
          setDisableVisible(false)
          setDisableCode('')
        }}
        onOk={handleDisableTOTP}
        confirmLoading={totpLoading}
        okText="确认禁用"
      >
        <Space direction="vertical" style={{ width: '100%' }}>
          <Alert
            type="warning"
            showIcon
            message="请输入当前验证码或恢复码完成禁用。"
          />
          <Input
            value={disableCode}
            onChange={(event) => setDisableCode(event.target.value.trim())}
            placeholder="验证码或恢复码"
          />
        </Space>
      </Modal>
    </PageLayout>
  )
}
