import {
  CheckCircleOutlined,
  EllipsisOutlined,
  MailOutlined,
  ReloadOutlined,
  SendOutlined,
  UserSwitchOutlined
} from '@ant-design/icons';
import {
  Alert,
  App as AntApp,
  Button,
  Card,
  Checkbox,
  Descriptions,
  Dropdown,
  Form,
  Input,
  InputNumber,
  List,
  Modal,
  Select,
  Space,
  Switch,
  Table,
  Tabs,
  Tag,
  Tooltip,
  Typography
} from 'antd';
import type { MenuProps } from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { useEffect, useRef, useState } from 'react';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';

import { EmptyState } from '../../components/common/EmptyState';
import { PageHeader } from '../../components/common/PageHeader';
import { SectionCard } from '../../components/common/SectionCard';
import { StatusPill } from '../../components/common/StatusPill';
import { useAppContext } from '../../frontend/app-context';
import { useMediaQuery } from '../../frontend/use-media-query';
import {
  adminUserStatusMeta,
  buildMergeConfirmationText,
  mergePreviewSummary,
  serializeAuditFilters,
  serializeSystemEmailPayload
} from './admin-model.js';
import { useI18n } from '../../frontend/i18n/react';
import { api } from '../../frontend/services/api';
import type {
  AdminResourceInventory,
  AdminUser,
  AuditLogEntry,
  SystemEmailSettings,
  UserMergeOptions,
  UserMergePreview,
  UserRole,
  UserStatus
} from '../../frontend/types';

const statusValues: UserStatus[] = ['pending_email', 'pending_review', 'active', 'disabled'];
const roleValues: UserRole[] = ['user', 'admin'];
const adminSections = ['users', 'resources', 'migration', 'system-email', 'audit-logs'] as const;
type AdminSection = typeof adminSections[number];

const mergeOptionLabels: Array<[keyof UserMergeOptions, string, string]> = [
  ['transferDomains', '迁移域名', 'Transfer domains'],
  ['transferDnsCredentials', '迁移 DNS 凭据', 'Transfer DNS credentials'],
  ['transferApiTokens', '迁移 API 密钥', 'Transfer API keys'],
  ['transferSendEvents', '迁移发送记录', 'Transfer sending activity'],
  ['transferSmtpCredential', '迁移 SMTP 凭据', 'Transfer SMTP credential'],
  ['disableSource', '禁用源用户', 'Disable source user']
];

export default function AdminPage() {
  const { message, modal } = AntApp.useApp();
  const { locale, t } = useI18n();
  const { user: me } = useAppContext();
  const navigate = useNavigate();
  const params = useParams<{ section?: string }>();
  const [searchParams, setSearchParams] = useSearchParams();
  const auditQuery = searchParams.toString();
  const activeSection: AdminSection = adminSections.includes(params.section as AdminSection)
    ? params.section as AdminSection
    : 'users';
  const [users, setUsers] = useState<AdminUser[]>([]);
  const [inventory, setInventory] = useState<AdminResourceInventory | null>(null);
  const [systemEmail, setSystemEmail] = useState<SystemEmailSettings | null>(null);
  const [auditLogs, setAuditLogs] = useState<AuditLogEntry[]>([]);
  const [loading, setLoading] = useState(false);
  const [actionKeys, setActionKeys] = useState<Set<string>>(() => new Set());
  const loadedSections = useRef(new Set<AdminSection>());
  const auditRequestId = useRef(0);

  useEffect(() => {
    if (!params.section || !adminSections.includes(params.section as AdminSection)) {
      navigate('/admin/users', { replace: true });
    }
  }, [navigate, params.section]);

  useEffect(() => {
    if (me?.role === 'admin') void loadSection(activeSection, activeSection === 'audit-logs', auditQuery);
    return () => {
      if (activeSection === 'audit-logs') auditRequestId.current += 1;
    };
  }, [activeSection, auditQuery, me?.role]);

  if (me?.role !== 'admin') {
    return (
      <Space direction="vertical" size={20} className="full-width admin-page">
        <PageHeader title={t('nav.adminCenter')} />
        <SectionCard>
          <Typography.Text type="secondary">{t('settings.noPermission')}</Typography.Text>
        </SectionCard>
      </Space>
    );
  }

  async function loadSection(section: AdminSection, force = false, query = auditQuery, showLoading = true) {
    if (!force && loadedSections.current.has(section)) {
      if (showLoading) setLoading(false);
      return;
    }
    let currentAuditRequestId: number | null = null;
    if (showLoading) setLoading(true);
    try {
      if (section === 'users' || section === 'migration') {
        const result = await api.adminUsers();
        setUsers(result.users || []);
      } else if (section === 'resources') {
        const [usersResult, resourcesResult] = await Promise.all([api.adminUsers(), api.adminResources()]);
        setUsers(usersResult.users || []);
        setInventory(resourcesResult.inventory || null);
      } else if (section === 'system-email') {
        const result = await api.adminSystemEmail();
        setSystemEmail(result.settings || null);
      } else if (section === 'audit-logs') {
        currentAuditRequestId = ++auditRequestId.current;
        const [usersResult, auditResult] = await Promise.all([api.adminUsers(), api.adminAuditLogs(query)]);
        if (currentAuditRequestId !== auditRequestId.current) return;
        setUsers(usersResult.users || []);
        setAuditLogs(auditResult.logs || []);
      }
      loadedSections.current.add(section);
    } catch (error) {
      if (currentAuditRequestId !== null && currentAuditRequestId !== auditRequestId.current) return;
      message.error(error instanceof Error ? error.message : tr(locale, '管理员数据加载失败', 'Failed to load admin data'));
    } finally {
      if (showLoading && (currentAuditRequestId === null || currentAuditRequestId === auditRequestId.current)) setLoading(false);
    }
  }

  async function runAction(key: string, action: () => Promise<unknown>, success: string, refresh = true) {
    setActionKeys((current) => new Set(current).add(key));
    try {
      await action();
      message.success(success);
      if (refresh) await loadSection(activeSection, true, auditQuery, false);
    } catch (error) {
      message.error(error instanceof Error ? error.message : tr(locale, '操作失败', 'Operation failed'));
    } finally {
      setActionKeys((current) => {
        const next = new Set(current);
        next.delete(key);
        return next;
      });
    }
  }

  function confirm(title: string, action: () => Promise<unknown>) {
    modal.confirm({
      title,
      okText: t('common.confirm'),
      cancelText: t('common.cancel'),
      onOk: action
    });
  }

  async function searchAuditLogs(query: string) {
    const next = new URLSearchParams(query);
    const nextQuery = next.toString();
    if (nextQuery === auditQuery) {
      await loadSection('audit-logs', true, nextQuery);
      return;
    }
    setSearchParams(next);
  }

  const tabItems = [
    {
      key: 'users',
      label: t('admin.users'),
      children: (
        <AdminUsers
          users={users}
          loading={loading}
          actionKeys={actionKeys}
          onApprove={(user) => confirm(tr(locale, `确认审批用户 ${user.username}？`, `Approve user ${user.username}?`), () =>
            runAction(`approve:${user.id}`, () => api.approveAdminUser(user.id), tr(locale, '用户已审批', 'User approved'))
          )}
          onResendVerification={(user) => runAction(`resend:${user.id}`, () => api.resendAdminVerification(user.id), tr(locale, '验证邮件请求已提交', 'Verification email requested'))}
          onPasswordReset={(user) => confirm(tr(locale, `确认给 ${user.email} 发送密码重置邮件？`, `Send a password reset email to ${user.email}?`), () =>
            runAction(`reset:${user.id}`, () => api.sendAdminPasswordReset(user.id), tr(locale, '密码重置邮件请求已提交', 'Password reset email requested'))
          )}
          onTemporaryPassword={(user, password) => confirm(tr(locale, `确认为用户 ${user.username} 设置临时密码？`, `Set a temporary password for ${user.username}?`), () =>
            runAction(`temporary-password:${user.id}`, () => api.setAdminTemporaryPassword(user.id, password), tr(locale, '临时密码已设置', 'Temporary password set'))
          )}
          onUpdateUser={(user, patch) => confirm(tr(locale, `确认更新用户 ${user.username}？`, `Update user ${user.username}?`), () =>
            runAction(`update:${user.id}`, () => api.updateAdminUser(user.id, patch), tr(locale, '用户已更新', 'User updated'))
          )}
        />
      )
    },
    {
      key: 'resources',
      label: t('admin.resources'),
      children: (
        <AdminResources
          users={users}
          inventory={inventory}
          loading={loading}
          actionKeys={actionKeys}
          onTransferDomain={(domainId, values) =>
            runAction(`transfer-domain:${domainId}`, () => api.transferAdminDomain(domainId, values), tr(locale, '域名已迁移', 'Domain transferred'))
          }
          onTransferDnsCredential={(credentialId, values) =>
            runAction(`transfer-dns:${credentialId}`, () => api.transferAdminDnsCredential(credentialId, values), tr(locale, 'DNS 凭据已迁移', 'DNS credential transferred'))
          }
          onTransferApiTokens={(values) =>
            runAction('transfer-token', () => api.transferAdminApiTokens(values), tr(locale, 'API 密钥已迁移', 'API keys transferred'))
          }
        />
      )
    },
    {
      key: 'migration',
      label: t('admin.migration'),
      children: (
        <AdminMigration
          users={users}
          loading={loading}
          actionKeys={actionKeys}
          onPreview={(values) => api.previewUserMerge(values)}
          onExecute={(values) => runAction('merge', () => api.executeUserMerge(values), tr(locale, '用户资源已合并', 'User resources merged'))}
        />
      )
    },
    {
      key: 'system-email',
      label: t('admin.systemEmail'),
      children: (
        <AdminSystemEmail
          settings={systemEmail}
          loading={loading}
          actionKeys={actionKeys}
          onSave={(values) => runAction('system-email:save', () => api.saveAdminSystemEmail(values), tr(locale, '系统邮件配置已保存', 'System email settings saved'))}
          onTest={(to) => runAction('system-email:test', () => api.testAdminSystemEmail(to), tr(locale, '测试邮件请求已提交', 'Test email requested'), false)}
        />
      )
    },
    {
      key: 'audit-logs',
      label: t('admin.auditLogs'),
      children: (
        <AdminAuditLogs
          logs={auditLogs}
          users={users}
          query={auditQuery}
          loading={loading}
          onSearch={searchAuditLogs}
        />
      )
    }
  ];

  return (
    <Space direction="vertical" size={20} className="full-width admin-page">
      <PageHeader
        title={t('nav.adminCenter')}
        extra={
          <Button icon={<ReloadOutlined />} loading={loading} onClick={() => void loadSection(activeSection, true)}>
            {t('common.refresh')}
          </Button>
        }
      />
      <SectionCard className="admin-center-card">
        <Tabs
          className="admin-center-tabs"
          activeKey={activeSection}
          items={tabItems}
          destroyOnHidden
          onChange={(key) => navigate(`/admin/${key}`)}
        />
      </SectionCard>
    </Space>
  );
}

function AdminUsers({
  users,
  loading,
  actionKeys,
  onApprove,
  onResendVerification,
  onPasswordReset,
  onTemporaryPassword,
  onUpdateUser
}: {
  users: AdminUser[];
  loading: boolean;
  actionKeys: ReadonlySet<string>;
  onApprove: (user: AdminUser) => void;
  onResendVerification: (user: AdminUser) => void;
  onPasswordReset: (user: AdminUser) => void;
  onTemporaryPassword: (user: AdminUser, password: string) => void;
  onUpdateUser: (user: AdminUser, patch: { role?: UserRole; status?: UserStatus }) => void;
}) {
  const { locale } = useI18n();
  const isTableView = useMediaQuery('(min-width: 768px)');
  const [tempUser, setTempUser] = useState<AdminUser | null>(null);
  const [form] = Form.useForm<{ password: string }>();

  const columns: ColumnsType<AdminUser> = [
    { title: 'ID', dataIndex: 'id', width: 72 },
    {
      title: tr(locale, '用户', 'User'),
      width: 260,
      className: 'admin-user-column',
      render: (_, user) => <AdminUserIdentity user={user} />
    },
    {
      title: tr(locale, '状态', 'Status'),
      dataIndex: 'status',
      width: 200,
      render: (_, user) => <AdminUserStatusSelect user={user} actionKeys={actionKeys} onUpdateUser={onUpdateUser} />
    },
    {
      title: tr(locale, '角色', 'Role'),
      dataIndex: 'role',
      width: 152,
      render: (_, user) => <AdminUserRoleSelect user={user} actionKeys={actionKeys} onUpdateUser={onUpdateUser} />
    },
    {
      title: tr(locale, '资源', 'Resources'),
      width: 340,
      render: (_, user) => <ResourceCountTags counts={user.resourceCounts} />
    },
    {
      title: tr(locale, '创建时间', 'Created at'),
      dataIndex: 'createdAt',
      width: 190,
      render: formatDate
    },
    {
      title: tr(locale, '操作', 'Actions'),
      width: 72,
      fixed: 'right',
      align: 'center',
      render: (_, user) => (
        <AdminUserActions
          user={user}
          actionKeys={actionKeys}
          onApprove={onApprove}
          onResendVerification={onResendVerification}
          onPasswordReset={onPasswordReset}
          onTemporaryPassword={() => setTempUser(user)}
        />
      )
    }
  ];

  async function submitTemporaryPassword() {
    if (!tempUser) return;
    const values = await form.validateFields();
    onTemporaryPassword(tempUser, values.password);
    setTempUser(null);
    form.resetFields();
  }

  return (
    <>
      {isTableView ? (
        <Table
          className="admin-users-table"
          rowKey="id"
          columns={columns}
          dataSource={users}
          loading={loading}
          tableLayout="fixed"
          scroll={{ x: 1280 }}
        />
      ) : (
        <List
          className="admin-users-list"
          dataSource={users}
          loading={loading}
          renderItem={(user) => (
            <List.Item>
              <Card className="admin-user-card" size="small">
                <div className="admin-user-card__header">
                  <AdminUserIdentity user={user} />
                  <AdminUserActions
                    user={user}
                    actionKeys={actionKeys}
                    onApprove={onApprove}
                    onResendVerification={onResendVerification}
                    onPasswordReset={onPasswordReset}
                    onTemporaryPassword={() => setTempUser(user)}
                  />
                </div>
                <Typography.Text type="secondary" className="admin-user-card__meta">
                  ID #{user.id} · {formatDate(user.createdAt)}
                </Typography.Text>
                <div className="admin-user-card__fields">
                  <div className="admin-user-card__field">
                    <Typography.Text type="secondary">{tr(locale, '状态', 'Status')}</Typography.Text>
                    <AdminUserStatusSelect user={user} actionKeys={actionKeys} onUpdateUser={onUpdateUser} />
                  </div>
                  <div className="admin-user-card__field">
                    <Typography.Text type="secondary">{tr(locale, '角色', 'Role')}</Typography.Text>
                    <AdminUserRoleSelect user={user} actionKeys={actionKeys} onUpdateUser={onUpdateUser} />
                  </div>
                </div>
                <div className="admin-user-card__resources">
                  <Typography.Text type="secondary">{tr(locale, '资源', 'Resources')}</Typography.Text>
                  <ResourceCountTags counts={user.resourceCounts} />
                </div>
              </Card>
            </List.Item>
          )}
        />
      )}
      <Modal
        title={tempUser ? `${tr(locale, '设置临时密码', 'Set temporary password')} · ${tempUser.username}` : tr(locale, '设置临时密码', 'Set temporary password')}
        open={Boolean(tempUser)}
        confirmLoading={actionKeys.has(`temporary-password:${tempUser?.id}`)}
        onCancel={() => setTempUser(null)}
        onOk={submitTemporaryPassword}
      >
        <Form form={form} layout="vertical">
          <Form.Item
            name="password"
            label={tr(locale, '临时密码', 'Temporary password')}
            rules={[{ required: true, min: 8, message: tr(locale, '密码至少需要 8 位。', 'Password must be at least 8 characters.') }]}
          >
            <Input.Password autoComplete="new-password" />
          </Form.Item>
        </Form>
      </Modal>
    </>
  );
}

function AdminUserIdentity({ user }: { user: AdminUser }) {
  return (
    <div className="admin-user-identity">
      <Typography.Text strong className="admin-user-identity__line" ellipsis={{ tooltip: user.username }}>
        {user.username}
      </Typography.Text>
      <Typography.Text type="secondary" className="admin-user-identity__line" ellipsis={{ tooltip: user.email }}>
        {user.email}
      </Typography.Text>
    </div>
  );
}

function AdminUserStatusSelect({
  user,
  actionKeys,
  onUpdateUser
}: {
  user: AdminUser;
  actionKeys: ReadonlySet<string>;
  onUpdateUser: (user: AdminUser, patch: { role?: UserRole; status?: UserStatus }) => void;
}) {
  const { locale } = useI18n();
  return (
    <Select
      aria-label={tr(locale, `用户状态 · ${user.username}`, `Status · ${user.username}`)}
      value={user.status}
      loading={actionKeys.has(`update:${user.id}`)}
      disabled={userMutationPending(actionKeys, user.id)}
      options={statusValues.map((value) => ({ value, label: userStatusLabel(value, locale) }))}
      onChange={(status) => onUpdateUser(user, { status })}
      className="table-select admin-user-select"
    />
  );
}

function AdminUserRoleSelect({
  user,
  actionKeys,
  onUpdateUser
}: {
  user: AdminUser;
  actionKeys: ReadonlySet<string>;
  onUpdateUser: (user: AdminUser, patch: { role?: UserRole; status?: UserStatus }) => void;
}) {
  const { locale } = useI18n();
  return (
    <Select
      aria-label={tr(locale, `用户角色 · ${user.username}`, `Role · ${user.username}`)}
      value={user.role}
      loading={actionKeys.has(`update:${user.id}`)}
      disabled={userMutationPending(actionKeys, user.id)}
      options={roleValues.map((value) => ({ value, label: value }))}
      onChange={(role) => onUpdateUser(user, { role })}
      className="table-select admin-user-select"
    />
  );
}

function AdminUserActions({
  user,
  actionKeys,
  onApprove,
  onResendVerification,
  onPasswordReset,
  onTemporaryPassword
}: {
  user: AdminUser;
  actionKeys: ReadonlySet<string>;
  onApprove: (user: AdminUser) => void;
  onResendVerification: (user: AdminUser) => void;
  onPasswordReset: (user: AdminUser) => void;
  onTemporaryPassword: () => void;
}) {
  const { locale } = useI18n();
  const pending = userMutationPending(actionKeys, user.id);
  const actionLabel = tr(locale, `用户操作 · ${user.username}`, `User actions · ${user.username}`);
  const items: MenuProps['items'] = [
    {
      key: 'approve',
      icon: <CheckCircleOutlined />,
      label: tr(locale, '审批', 'Approve'),
      disabled: pending || user.status !== 'pending_review'
    },
    {
      key: 'resend',
      icon: <MailOutlined />,
      label: tr(locale, '重发验证', 'Resend verification'),
      disabled: pending || user.status !== 'pending_email'
    },
    { type: 'divider' },
    {
      key: 'reset',
      icon: <SendOutlined />,
      label: tr(locale, '重置邮件', 'Reset email'),
      danger: true,
      disabled: pending
    },
    {
      key: 'temporary-password',
      icon: <UserSwitchOutlined />,
      label: tr(locale, '临时密码', 'Temporary password'),
      danger: true,
      disabled: pending
    }
  ];

  function runSelectedAction(key: string) {
    if (key === 'approve') onApprove(user);
    else if (key === 'resend') onResendVerification(user);
    else if (key === 'reset') onPasswordReset(user);
    else if (key === 'temporary-password') onTemporaryPassword();
  }

  return (
    <Tooltip title={actionLabel}>
      <Dropdown
        trigger={['click']}
        placement="bottomRight"
        menu={{ items, onClick: ({ key }) => runSelectedAction(key) }}
        disabled={pending}
      >
        <Button
          aria-label={actionLabel}
          icon={<EllipsisOutlined />}
          loading={pending}
          disabled={pending}
          className="admin-user-actions-trigger"
        />
      </Dropdown>
    </Tooltip>
  );
}

function AdminResources({
  users,
  inventory,
  loading,
  actionKeys,
  onTransferDomain,
  onTransferDnsCredential,
  onTransferApiTokens
}: {
  users: AdminUser[];
  inventory: AdminResourceInventory | null;
  loading: boolean;
  actionKeys: ReadonlySet<string>;
  onTransferDomain: (domainId: number, values: { targetUserId: number; dnsCredentialMode?: 'domain_only' | 'with_dns_credential' | 'clear_dns_credential' }) => Promise<void>;
  onTransferDnsCredential: (credentialId: number, values: { targetUserId: number }) => Promise<void>;
  onTransferApiTokens: (values: { tokenIds: number[]; targetUserId: number }) => Promise<void>;
}) {
  const { locale } = useI18n();
  const [domainForm] = Form.useForm<{ domainId: number; targetUserId: number; dnsCredentialMode: 'domain_only' | 'with_dns_credential' | 'clear_dns_credential' }>();
  const [dnsForm] = Form.useForm<{ credentialId: number; targetUserId: number }>();
  const [tokenForm] = Form.useForm<{ tokenIds: number[]; targetUserId: number }>();
  const selectedDomainId = Form.useWatch('domainId', domainForm);
  const selectedCredentialId = Form.useWatch('credentialId', dnsForm);
  const groups = inventory?.users || [];
  const targetOptions = users
    .filter((user) => user.status !== 'disabled')
    .map((user) => ({ value: user.id, label: `${user.username} (#${user.id})` }));
  const domains = groups.flatMap((group) => group.domains.map((domain) => ({ ...domain, owner: group.user })));
  const credentials = groups.flatMap((group) => group.dnsCredentials.map((credential) => ({ ...credential, owner: group.user })));
  const tokens = groups.flatMap((group) => group.apiTokens.map((token) => ({ ...token, owner: group.user })));

  const groupColumns: ColumnsType<AdminResourceInventory['users'][number]> = [
    {
      title: tr(locale, '用户', 'User'),
      width: 260,
      render: (_, group) => (
        <div className="admin-resource-owner">
          <Typography.Text strong ellipsis={{ tooltip: group.user.username }}>{group.user.username}</Typography.Text>
          <UserStatusTag status={group.user.status} />
        </div>
      )
    },
    { title: tr(locale, '资源', 'Resources'), width: 360, render: (_, group) => <ResourceCountTags counts={group.user.resourceCounts} /> },
    { title: tr(locale, '发送记录', 'Sending activity'), dataIndex: 'sendEventCount', width: 120 },
    { title: tr(locale, '入站邮件', 'Inbound mail'), dataIndex: 'inboundMessageCount', width: 120 },
    {
      title: 'SMTP',
      width: 120,
      render: (_, group) => (
        group.smtpCredential
          ? <StatusPill tone="success">{tr(locale, '已配置', 'Configured')}</StatusPill>
          : <StatusPill tone="neutral">{tr(locale, '无', 'None')}</StatusPill>
      )
    }
  ];

  async function submitDomainTransfer(values: { domainId: number; targetUserId: number; dnsCredentialMode: 'domain_only' | 'with_dns_credential' | 'clear_dns_credential' }) {
    Modal.confirm({
      title: tr(locale, '确认迁移该域名？', 'Transfer this domain?'),
      onOk: async () => {
        await onTransferDomain(values.domainId, {
          targetUserId: values.targetUserId,
          dnsCredentialMode: values.dnsCredentialMode
        });
        domainForm.resetFields();
      }
    });
  }

  async function submitDnsTransfer(values: { credentialId: number; targetUserId: number }) {
    Modal.confirm({
      title: tr(locale, '确认迁移该 DNS 凭据？', 'Transfer this DNS credential?'),
      onOk: async () => {
        await onTransferDnsCredential(values.credentialId, { targetUserId: values.targetUserId });
        dnsForm.resetFields();
      }
    });
  }

  async function submitTokenTransfer(values: { tokenIds: number[]; targetUserId: number }) {
    Modal.confirm({
      title: tr(locale, `确认迁移 ${values.tokenIds.length} 个 API 密钥？`, `Transfer ${values.tokenIds.length} API keys?`),
      onOk: async () => {
        await onTransferApiTokens({ tokenIds: values.tokenIds, targetUserId: values.targetUserId });
        tokenForm.resetFields();
      }
    });
  }

  return (
    <Space direction="vertical" size={16} className="full-width">
      {inventory?.warnings?.length ? (
        <Alert
          type="warning"
          showIcon
          message={tr(locale, `发现 ${inventory.warnings.length} 个 DNS 凭据归属不一致的域名`, `${inventory.warnings.length} domains have mismatched DNS credential ownership`)}
        />
      ) : null}
      <div className="form-grid three">
        <SectionCard title={tr(locale, '迁移域名', 'Transfer domain')}>
          <Form form={domainForm} layout="vertical" onFinish={submitDomainTransfer} disabled={loading || actionKeys.has(`transfer-domain:${selectedDomainId}`)}>
            <Form.Item name="domainId" label={tr(locale, '域名', 'Domain')} rules={[{ required: true }]}>
              <Select
                showSearch
                optionFilterProp="label"
                options={domains.map((domain) => ({
                  value: domain.id,
                  label: `${domain.domain} · ${domain.owner.username}`
                }))}
              />
            </Form.Item>
            <Form.Item name="targetUserId" label={tr(locale, '目标用户', 'Target user')} rules={[{ required: true }]}>
              <Select options={targetOptions} />
            </Form.Item>
            <Form.Item name="dnsCredentialMode" label={tr(locale, 'DNS 凭据', 'DNS credential')} initialValue="domain_only">
              <Select
                options={[
                  { value: 'domain_only', label: tr(locale, '仅迁移域名', 'Domain only') },
                  { value: 'with_dns_credential', label: tr(locale, '连同 DNS 凭据迁移', 'Include DNS credential') },
                  { value: 'clear_dns_credential', label: tr(locale, '清空 DNS 凭据绑定', 'Clear DNS credential binding') }
                ]}
              />
            </Form.Item>
            <Button type="primary" htmlType="submit" loading={actionKeys.has(`transfer-domain:${selectedDomainId}`)}>{tr(locale, '执行迁移', 'Transfer')}</Button>
          </Form>
        </SectionCard>
        <SectionCard title={tr(locale, '迁移 DNS 凭据', 'Transfer DNS credential')}>
          <Form form={dnsForm} layout="vertical" onFinish={submitDnsTransfer} disabled={loading || actionKeys.has(`transfer-dns:${selectedCredentialId}`)}>
            <Form.Item name="credentialId" label={tr(locale, 'DNS 凭据', 'DNS credential')} rules={[{ required: true }]}>
              <Select
                showSearch
                optionFilterProp="label"
                options={credentials.map((credential) => ({
                  value: credential.id,
                  label: `${credential.name} · ${credential.zoneName} · ${credential.owner.username}`
                }))}
              />
            </Form.Item>
            <Form.Item name="targetUserId" label={tr(locale, '目标用户', 'Target user')} rules={[{ required: true }]}>
              <Select options={targetOptions} />
            </Form.Item>
            <Button htmlType="submit" loading={actionKeys.has(`transfer-dns:${selectedCredentialId}`)}>{tr(locale, '执行迁移', 'Transfer')}</Button>
          </Form>
        </SectionCard>
        <SectionCard title={tr(locale, '迁移 API 密钥', 'Transfer API keys')}>
          <Form form={tokenForm} layout="vertical" onFinish={submitTokenTransfer} disabled={loading || actionKeys.has('transfer-token')}>
            <Form.Item name="tokenIds" label={tr(locale, 'API 密钥', 'API key')} rules={[{ required: true }]}>
              <Select
                mode="multiple"
                optionFilterProp="label"
                options={tokens.map((token) => ({
                  value: token.id,
                  label: `${token.name} · ${token.tokenPrefix} · ${token.owner.username}`
                }))}
              />
            </Form.Item>
            <Form.Item name="targetUserId" label={tr(locale, '目标用户', 'Target user')} rules={[{ required: true }]}>
              <Select options={targetOptions} />
            </Form.Item>
            <Button htmlType="submit" loading={actionKeys.has('transfer-token')}>{tr(locale, '执行迁移', 'Transfer')}</Button>
          </Form>
        </SectionCard>
      </div>
      <SectionCard title={tr(locale, '资源归属', 'Resource ownership')}>
        <Table
          rowKey={(group) => group.user.id}
          columns={groupColumns}
          dataSource={groups}
          loading={loading}
          expandable={{ expandedRowRender: (group) => <ResourceDetails group={group} /> }}
          scroll={{ x: 980 }}
        />
      </SectionCard>
    </Space>
  );
}

function ResourceDetails({ group }: { group: AdminResourceInventory['users'][number] }) {
  const { locale } = useI18n();
  return (
    <Space direction="vertical" size={16} className="full-width">
      <Descriptions size="small" column={2} className="admin-resource-descriptions">
        <Descriptions.Item label={tr(locale, '邮箱', 'Email')}><span className="admin-breakable-text">{group.user.email}</span></Descriptions.Item>
        <Descriptions.Item label={tr(locale, '角色', 'Role')}>{group.user.role}</Descriptions.Item>
      </Descriptions>
      <Table
        size="small"
        rowKey="id"
        pagination={false}
        dataSource={group.domains}
        columns={[
          { title: tr(locale, '域名', 'Domain'), dataIndex: 'domain' },
          { title: tr(locale, '发信主机', 'Sending host'), dataIndex: 'senderHost' },
          { title: tr(locale, 'DNS 凭据 ID', 'DNS credential ID'), dataIndex: 'dnsCredentialId' }
        ]}
        scroll={{ x: 640 }}
      />
      <Table
        size="small"
        rowKey="id"
        pagination={false}
        dataSource={group.dnsCredentials}
        columns={[
          { title: tr(locale, 'DNS 凭据', 'DNS credential'), dataIndex: 'name' },
          { title: 'Provider', dataIndex: 'provider' },
          { title: 'Zone', dataIndex: 'zoneName' }
        ]}
        scroll={{ x: 520 }}
      />
      <Table
        size="small"
        rowKey="id"
        pagination={false}
        dataSource={group.apiTokens}
        columns={[
          { title: tr(locale, 'API 密钥', 'API key'), dataIndex: 'name' },
          { title: tr(locale, '前缀', 'Prefix'), dataIndex: 'tokenPrefix' },
          { title: tr(locale, '创建时间', 'Created at'), dataIndex: 'createdAt', render: formatDate }
        ]}
        scroll={{ x: 580 }}
      />
    </Space>
  );
}

function AdminMigration({
  users,
  loading,
  actionKeys,
  onPreview,
  onExecute
}: {
  users: AdminUser[];
  loading: boolean;
  actionKeys: ReadonlySet<string>;
  onPreview: (values: { sourceUserId: number; targetUserId: number }) => Promise<{ preview: UserMergePreview }>;
  onExecute: (values: {
    sourceUserId: number;
    targetUserId: number;
    options: Partial<UserMergeOptions>;
    confirmation: string;
  }) => Promise<void>;
}) {
  const { message } = AntApp.useApp();
  const { locale } = useI18n();
  const [form] = Form.useForm<{ sourceUserId: number; targetUserId: number }>();
  const [preview, setPreview] = useState<UserMergePreview | null>(null);
  const [options, setOptions] = useState<Partial<UserMergeOptions>>({});
  const [confirmation, setConfirmation] = useState('');
  const [previewLoading, setPreviewLoading] = useState(false);
  const userOptions = users.map((user) => ({ value: user.id, label: `${user.username} (#${user.id})` }));

  async function submitPreview(values: { sourceUserId: number; targetUserId: number }) {
    setPreviewLoading(true);
    try {
      const result = await onPreview(values);
      setPreview(result.preview);
      setOptions(result.preview.defaultOptions);
      setConfirmation('');
    } catch (error) {
      message.error(error instanceof Error ? error.message : tr(locale, '预览失败', 'Preview failed'));
    } finally {
      setPreviewLoading(false);
    }
  }

  async function execute() {
    if (!preview) return;
    await onExecute({
      sourceUserId: preview.sourceUser.id,
      targetUserId: preview.targetUser.id,
      options,
      confirmation
    });
    setPreview(null);
    form.resetFields();
    setConfirmation('');
  }

  const expectedConfirmation = preview
    ? buildMergeConfirmationText(preview.sourceUser, preview.targetUser)
    : '';

  return (
    <Space direction="vertical" size={16} className="full-width">
      <SectionCard title={tr(locale, '合并预览', 'Merge preview')}>
        <Form form={form} layout="inline" onFinish={submitPreview} disabled={loading} className="admin-inline-form">
          <Form.Item name="sourceUserId" label={tr(locale, '源用户', 'Source user')} rules={[{ required: true }]}>
            <Select options={userOptions} className="toolbar-select" />
          </Form.Item>
          <Form.Item name="targetUserId" label={tr(locale, '目标用户', 'Target user')} rules={[{ required: true }]}>
            <Select options={userOptions} className="toolbar-select" />
          </Form.Item>
          <Button type={preview ? 'default' : 'primary'} htmlType="submit" loading={previewLoading}>{tr(locale, '预览', 'Preview')}</Button>
        </Form>
      </SectionCard>
      {preview ? (
        <SectionCard title={`${preview.sourceUser.username} → ${preview.targetUser.username}`}>
          <Space direction="vertical" size={16} className="full-width">
            {preview.warnings.length ? (
              <Alert type="warning" showIcon message={preview.warnings.map((item) => item.message || item.type).join('；')} />
            ) : null}
            <Space wrap>
              {mergePreviewSummary(preview).map((item) => (
                <StatusPill key={item.key} tone="neutral">{resourceLabel(item.key, locale)}: {item.count}</StatusPill>
              ))}
            </Space>
            <div className="form-grid two">
              {mergeOptionLabels.map(([key, zhLabel, enLabel]) => (
                <Checkbox
                  key={key}
                  checked={options[key] !== false}
                  onChange={(event) => setOptions((current) => ({ ...current, [key]: event.target.checked }))}
                >
                  {tr(locale, zhLabel, enLabel)}
                </Checkbox>
              ))}
            </div>
            <Descriptions column={1} bordered size="small">
              <Descriptions.Item label={tr(locale, '确认文本', 'Confirmation text')}>
                <Typography.Text code>{expectedConfirmation}</Typography.Text>
              </Descriptions.Item>
            </Descriptions>
            <Input
              value={confirmation}
              onChange={(event) => setConfirmation(event.target.value)}
              placeholder={expectedConfirmation}
            />
            <Button
              danger
              type="primary"
              loading={actionKeys.has('merge')}
              disabled={confirmation !== expectedConfirmation}
              onClick={execute}
            >
              {tr(locale, '执行合并', 'Merge users')}
            </Button>
          </Space>
        </SectionCard>
      ) : (
        <EmptyState description={tr(locale, '暂无预览', 'No preview yet')} />
      )}
    </Space>
  );
}

function AdminSystemEmail({
  settings,
  loading,
  actionKeys,
  onSave,
  onTest
}: {
  settings: SystemEmailSettings | null;
  loading: boolean;
  actionKeys: ReadonlySet<string>;
  onSave: (values: Partial<SystemEmailSettings>) => Promise<void>;
  onTest: (to?: string) => Promise<void>;
}) {
  const { locale } = useI18n();
  const [form] = Form.useForm<SystemEmailSettings>();

  useEffect(() => {
    if (settings) form.setFieldsValue(settings);
  }, [form, settings]);

  async function submit(values: SystemEmailSettings) {
    await onSave(serializeSystemEmailPayload(values));
    form.setFieldValue('password', '');
  }

  return (
    <SectionCard title={tr(locale, '系统邮件服务器', 'System email server')}>
      <Form form={form} layout="vertical" onFinish={submit} disabled={loading}>
        <div className="form-grid two">
          <Form.Item name="host" label="SMTP Host" rules={[{ required: true }]}>
            <Input />
          </Form.Item>
          <Form.Item name="port" label="SMTP Port" rules={[{ required: true }]}>
            <InputNumber min={1} max={65535} className="full-width" />
          </Form.Item>
          <Form.Item name="secure" label="SSL / TLS" valuePropName="checked">
            <Switch />
          </Form.Item>
          <Form.Item name="helo" label="HELO">
            <Input />
          </Form.Item>
          <Form.Item name="username" label="Username">
            <Input autoComplete="off" />
          </Form.Item>
          <Form.Item name="password" label={settings?.passwordSet ? tr(locale, 'Password（留空保留）', 'Password (leave blank to keep)') : 'Password'}>
            <Input.Password autoComplete="new-password" />
          </Form.Item>
          <Form.Item name="fromEmail" label="From Email" rules={[{ required: true, type: 'email' }]}>
            <Input />
          </Form.Item>
          <Form.Item name="fromName" label="From Name">
            <Input />
          </Form.Item>
          <Form.Item name="testRecipient" label="Test Recipient">
            <Input />
          </Form.Item>
        </div>
        <Space wrap>
          <Button type="primary" htmlType="submit" loading={actionKeys.has('system-email:save')}>{tr(locale, '保存配置', 'Save settings')}</Button>
          <Button onClick={() => onTest(form.getFieldValue('testRecipient'))} loading={actionKeys.has('system-email:test')}>{tr(locale, '发送测试', 'Send test')}</Button>
        </Space>
      </Form>
    </SectionCard>
  );
}

function AdminAuditLogs({
  logs,
  users,
  query,
  loading,
  onSearch
}: {
  logs: AuditLogEntry[];
  users: AdminUser[];
  query: string;
  loading: boolean;
  onSearch: (query: string) => Promise<void>;
}) {
  const { locale } = useI18n();
  const [form] = Form.useForm();
  const userOptions = users.map((user) => ({ value: user.id, label: `${user.username} (#${user.id})` }));

  useEffect(() => {
    form.setFieldsValue(auditFiltersFromQuery(query));
  }, [form, query]);

  const columns: ColumnsType<AuditLogEntry> = [
    { title: tr(locale, '时间', 'Time'), dataIndex: 'createdAt', width: 190, render: formatDate },
    { title: tr(locale, '动作', 'Action'), dataIndex: 'action', width: 220 },
    { title: tr(locale, '操作者', 'Actor'), dataIndex: 'actorUserId', width: 130, render: (value) => value ?? 'system' },
    { title: tr(locale, '目标用户', 'Target user'), dataIndex: 'targetUserId', width: 130, render: (value) => value ?? '-' },
    { title: tr(locale, '目标', 'Target'), render: (_, log) => `${log.targetType}:${log.targetId || '-'}`, width: 180 },
    {
      title: tr(locale, '摘要', 'Summary'),
      dataIndex: 'summary',
      render: (value) => (
        <Typography.Text code ellipsis>
          {JSON.stringify(value)}
        </Typography.Text>
      )
    }
  ];

  async function submit(values: Record<string, unknown>) {
    await onSearch(serializeAuditFilters(values));
  }

  return (
    <Space direction="vertical" size={16} className="full-width">
      <SectionCard className="admin-audit-toolbar-card">
        <Form form={form} layout="inline" onFinish={submit} disabled={loading} className="admin-inline-form">
          <Form.Item name="actorUserId" label={tr(locale, '操作者', 'Actor')}>
            <Select allowClear options={[{ value: 'system', label: 'system' }, ...userOptions]} className="toolbar-select" />
          </Form.Item>
          <Form.Item name="targetUserId" label={tr(locale, '目标用户', 'Target user')}>
            <Select allowClear options={userOptions} className="toolbar-select" />
          </Form.Item>
          <Form.Item name="action" label={tr(locale, '动作', 'Action')}>
            <Input placeholder="admin.user_merge" />
          </Form.Item>
          <Form.Item name="from" label={tr(locale, '开始', 'From')}>
            <Input placeholder="2026-07-08" />
          </Form.Item>
          <Form.Item name="to" label={tr(locale, '结束', 'To')}>
            <Input placeholder="2026-07-09" />
          </Form.Item>
          <Button type="primary" htmlType="submit" loading={loading}>{tr(locale, '查询', 'Search')}</Button>
        </Form>
      </SectionCard>
      <Table rowKey="id" columns={columns} dataSource={logs} loading={loading} scroll={{ x: 1100 }} />
    </Space>
  );
}

function ResourceCountTags({ counts }: { counts?: AdminUser['resourceCounts'] }) {
  const { locale } = useI18n();
  if (!counts) return <Tag>{tr(locale, '无资源', 'No resources')}</Tag>;
  return (
    <Space wrap>
      <Tag>{tr(locale, '域名', 'Domains')} {counts.domains}</Tag>
      <Tag>DNS {counts.dnsCredentials}</Tag>
      <Tag>Token {counts.apiTokens}</Tag>
      <Tag>{tr(locale, '收信', 'Mailboxes')} {counts.inboundMailboxes}</Tag>
      <Tag>{tr(locale, '入站', 'Inbound')} {counts.inboundMessages}</Tag>
      <Tag>{tr(locale, '记录', 'Events')} {counts.sendEvents}</Tag>
      <Tag>SMTP {counts.smtpCredential}</Tag>
    </Space>
  );
}

function UserStatusTag({ status }: { status: UserStatus }) {
  const meta = adminUserStatusMeta(status);
  const { locale } = useI18n();
  const tone = statusToneFromColor(meta.color);
  return <StatusPill tone={tone}>{userStatusLabel(status, locale)}</StatusPill>;
}

function statusToneFromColor(color: string): 'success' | 'warning' | 'error' | 'info' | 'neutral' {
  if (color === 'green' || color === 'success') return 'success';
  if (color === 'gold' || color === 'orange' || color === 'warning') return 'warning';
  if (color === 'red' || color === 'error' || color === 'volcano') return 'error';
  if (color === 'blue' || color === 'processing' || color === 'cyan') return 'info';
  return 'neutral';
}

function formatDate(value?: string) {
  return value ? new Date(value).toLocaleString() : '-';
}

function userMutationPending(actionKeys: ReadonlySet<string>, userId: number) {
  return [
    `update:${userId}`,
    `approve:${userId}`,
    `resend:${userId}`,
    `reset:${userId}`,
    `temporary-password:${userId}`
  ].some((key) => actionKeys.has(key));
}

function auditFiltersFromQuery(query: string) {
  const params = new URLSearchParams(query);
  const actor = params.get('actorUserId');
  const target = params.get('targetUserId');
  return {
    actorUserId: actor === 'system' ? actor : positiveInteger(actor),
    targetUserId: positiveInteger(target),
    action: params.get('action') || undefined,
    from: params.get('from') || undefined,
    to: params.get('to') || undefined
  };
}

function positiveInteger(value: string | null) {
  const parsed = Number(value);
  return Number.isInteger(parsed) && parsed > 0 ? parsed : undefined;
}

function tr(locale: string, zh: string, en: string) {
  return locale.startsWith('en') ? en : zh;
}

function userStatusLabel(status: UserStatus, locale: string) {
  const labels: Record<UserStatus, [string, string]> = {
    pending_email: ['待验证邮箱', 'Email verification pending'],
    pending_review: ['待管理员审核', 'Admin review pending'],
    active: ['正常', 'Active'],
    disabled: ['已禁用', 'Disabled']
  };
  const label = labels[status];
  return label ? tr(locale, label[0], label[1]) : status;
}

function resourceLabel(key: string, locale: string) {
  const labels: Record<string, [string, string]> = {
    domains: ['域名', 'Domains'],
    dnsCredentials: ['DNS 凭据', 'DNS credentials'],
    apiTokens: ['API 密钥', 'API keys'],
    inboundMailboxes: ['收信邮箱', 'Mailboxes'],
    inboundMessages: ['入站邮件', 'Inbound mail'],
    sendEvents: ['发送记录', 'Sending activity'],
    smtpCredential: ['SMTP 凭据', 'SMTP credential']
  };
  const label = labels[key];
  return label ? tr(locale, label[0], label[1]) : key;
}
