import {
  CopyOutlined,
  DeleteOutlined,
  EditOutlined,
  KeyOutlined,
  PlusOutlined,
  ReadOutlined,
  ReloadOutlined
} from '@ant-design/icons';
import {
  Alert,
  App as AntApp,
  Button,
  Checkbox,
  Collapse,
  Descriptions,
  Drawer,
  Form,
  Input,
  Modal,
  Popconfirm,
  Radio,
  Select,
  Skeleton,
  Space,
  Table,
  Tag,
  Typography
} from 'antd';
import type { ColumnsType } from 'antd/es/table';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';

import { CodeBlock } from '../components/common/CodeBlock';
import { EmptyState } from '../components/common/EmptyState';
import { PageHeader } from '../components/common/PageHeader';
import { SectionCard } from '../components/common/SectionCard';
import { StatusPill, type StatusTone } from '../components/common/StatusPill';
import {
  buildApiUsageExamples,
  buildInboundMessageApiUsageExamples,
  buildMailboxApiUsageExamples,
  canCopyFullApiToken,
  formatApiTokenPrefix,
  getCreatedApiTokenSecret
} from '../frontend/api-token-model.js';
import { useAppContext } from '../frontend/app-context';
import { useI18n } from '../frontend/i18n/react';
import { detailHistoryLocation, detailHistoryState } from '../frontend/navigation-state';
import { api } from '../frontend/services/api';
import type {
  ApiToken,
  ApiTokenInput,
  ApiTokenMailboxAccess,
  InboundMailbox,
  RuntimeConfig
} from '../frontend/types';

interface TokenFormValues {
  name: string;
  scopes: string[];
  expiresAt?: string;
  mailboxAccess: ApiTokenMailboxAccess;
  mailboxIds: number[];
}

type SecretModalMode = 'created' | 'rotated';
type GuideSection = 'send' | 'mailboxes' | 'messages';

const scopeOptions = [
  { label: 'send', value: 'send' },
  { label: 'mailboxes:read', value: 'mailboxes:read' },
  { label: 'mailboxes:write', value: 'mailboxes:write' },
  { label: 'messages:read', value: 'messages:read' }
];

export default function ApiTokens() {
  const { message } = AntApp.useApp();
  const { t } = useI18n();
  const { config, user } = useAppContext();
  const location = useLocation();
  const navigate = useNavigate();
  const [searchParams, setSearchParams] = useSearchParams();
  const [form] = Form.useForm<TokenFormValues>();
  const [tokens, setTokens] = useState<ApiToken[]>([]);
  const [mailboxes, setMailboxes] = useState<InboundMailbox[]>([]);
  const [loading, setLoading] = useState(true);
  const [loadError, setLoadError] = useState('');
  const [mailboxError, setMailboxError] = useState('');
  const [actionKey, setActionKey] = useState('');
  const [editorOpen, setEditorOpen] = useState(false);
  const [editingToken, setEditingToken] = useState<ApiToken | null>(null);
  const [revealedToken, setRevealedToken] = useState<ApiToken | null>(null);
  const [secretModalMode, setSecretModalMode] = useState<SecretModalMode>('created');
  const pendingDirectGuideClose = useRef<string | null>(null);
  const selectedScopes = Form.useWatch('scopes', form) || [];
  const selectedMailboxAccess = Form.useWatch('mailboxAccess', form) || 'owner';
  const messagesReadEnabled = selectedScopes.includes('messages:read');
  const isAdmin = user?.role === 'admin';
  const requestedTokenId = positiveInteger(searchParams.get('tokenId'));
  const guideParam = searchParams.get('guide');
  const guideSection = normalizeGuideSection(guideParam);
  const guideOpen = guideParam != null;
  const selectedToken = useMemo(
    () => requestedTokenId ? tokens.find((token) => token.id === requestedTokenId) || null : null,
    [requestedTokenId, tokens]
  );

  const loadData = useCallback(async () => {
    setLoading(true);
    setLoadError('');
    setMailboxError('');
    const [tokenResult, mailboxResult] = await Promise.allSettled([
      api.apiTokens(),
      api.inboundMailboxes(isAdmin)
    ]);

    if (tokenResult.status === 'fulfilled') {
      const nextTokens = tokenResult.value.tokens || [];
      setTokens(nextTokens);
    } else {
      setLoadError(tokenResult.reason instanceof Error ? tokenResult.reason.message : t('common.error'));
    }

    if (mailboxResult.status === 'fulfilled') {
      setMailboxes(mailboxResult.value.mailboxes || []);
    } else {
      setMailboxError(mailboxResult.reason instanceof Error ? mailboxResult.reason.message : t('common.error'));
    }
    setLoading(false);
  }, [isAdmin, t]);

  useEffect(() => {
    void loadData();
  }, [loadData]);

  useEffect(() => {
    const target = pendingDirectGuideClose.current;
    if (!target || detailHistoryState(location.state)?.origin === 'direct') return;
    pendingDirectGuideClose.current = null;
    navigate(target, { replace: true });
  }, [location.key, location.state, navigate]);

  async function copyValue(value: string) {
    if (!value) return;
    await navigator.clipboard.writeText(value);
    message.success(t('common.copied'));
  }

  function openCreate() {
    setEditingToken(null);
    form.resetFields();
    form.setFieldsValue({ name: '', scopes: ['send'], expiresAt: '', mailboxAccess: 'owner', mailboxIds: [] });
    setEditorOpen(true);
  }

  function openEdit(token: ApiToken) {
    const mailboxAccess = token.mailboxAccess === 'all' && !isAdmin ? 'owner' : token.mailboxAccess || 'owner';
    setEditingToken(token);
    form.resetFields();
    form.setFieldsValue({
      name: token.name,
      scopes: token.scopes || ['send'],
      expiresAt: toDatetimeLocal(token.expiresAt),
      mailboxAccess,
      mailboxIds: token.mailboxIds || []
    });
    setEditorOpen(true);
  }

  async function saveToken() {
    const values = await form.validateFields();
    const payload = toTokenPayload(values);
    const key = editingToken ? `save:${editingToken.id}` : 'create';
    setActionKey(key);
    try {
      if (editingToken) {
        await api.updateApiToken(editingToken.id, payload);
        message.success(t('tokens.updatedSuccess'));
      } else {
        const result = await api.createApiToken({ ...payload, name: values.name.trim() });
        message.success(t('tokens.createdSuccess'));
        if (result.token && canCopyFullApiToken(result.token)) {
          setSecretModalMode('created');
          setRevealedToken(result.token);
        }
      }
      setEditorOpen(false);
      setEditingToken(null);
      form.resetFields();
      await loadData();
    } catch (error) {
      message.error(error instanceof Error ? error.message : t('common.error'));
    } finally {
      setActionKey('');
    }
  }

  async function rotateToken(token: ApiToken) {
    setActionKey(`rotate:${token.id}`);
    try {
      const result = await api.rotateApiToken(token.id);
      message.success(t('tokens.rotatedSuccess'));
      setSecretModalMode('rotated');
      setRevealedToken(result.token);
      await loadData();
    } catch (error) {
      message.error(error instanceof Error ? error.message : t('common.error'));
    } finally {
      setActionKey('');
    }
  }

  async function revokeToken(token: ApiToken) {
    setActionKey(`revoke:${token.id}`);
    try {
      await api.deleteApiToken(token.id);
      message.success(t('tokens.revokedSuccess'));
      if (requestedTokenId === token.id) closeTokenDetail();
      await loadData();
    } catch (error) {
      message.error(error instanceof Error ? error.message : t('common.error'));
    } finally {
      setActionKey('');
    }
  }

  function openTokenDetail(token: ApiToken) {
    const next = new URLSearchParams(searchParams);
    next.set('tokenId', String(token.id));
    setSearchParams(next, {
      state: detailHistoryLocation(`${location.pathname}${location.search}`, 1)
    });
  }

  function closeTokenDetail() {
    const historyState = detailHistoryState(location.state);
    if (historyState) {
      navigate(-historyState.depth);
      return;
    }
    const next = new URLSearchParams(searchParams);
    next.delete('tokenId');
    setSearchParams(next, { replace: true, state: null });
  }

  function openGuide(section: GuideSection = 'send') {
    if (guideOpen && section === guideSection) return;
    const next = new URLSearchParams(searchParams);
    next.set('guide', section);
    if (!guideOpen) {
      setSearchParams(next, {
        state: detailHistoryLocation(`${location.pathname}${location.search}`, 1)
      });
      return;
    }
    const historyState = detailHistoryState(location.state);
    const search = next.toString();
    if (historyState) {
      navigate(
        { pathname: location.pathname, search: search ? `?${search}` : '' },
        {
          state: detailHistoryLocation(
            historyState.listPath,
            historyState.depth + 1,
            historyState.origin
          )
        }
      );
      return;
    }
    const listParams = new URLSearchParams(searchParams);
    listParams.delete('guide');
    const listSearch = listParams.toString();
    navigate(
      { pathname: location.pathname, search: search ? `?${search}` : '' },
      {
        state: detailHistoryLocation(
          `${location.pathname}${listSearch ? `?${listSearch}` : ''}`,
          1,
          'direct'
        )
      }
    );
  }

  function closeGuide() {
    const historyState = detailHistoryState(location.state);
    if (historyState?.origin === 'list') {
      navigate(-historyState.depth);
      return;
    }
    if (historyState?.origin === 'direct') {
      pendingDirectGuideClose.current = historyState.listPath;
      navigate(-historyState.depth);
      return;
    }
    const next = new URLSearchParams(searchParams);
    next.delete('guide');
    setSearchParams(next, { replace: true, state: null });
  }

  const columns: ColumnsType<ApiToken> = [
    {
      title: t('tokens.name'),
      dataIndex: 'name',
      width: 180,
      render: (value: string) => <Typography.Text strong>{value}</Typography.Text>
    },
    {
      title: t('tokens.fullToken'),
      dataIndex: 'token',
      width: 320,
      render: (_value, token) => <TokenValue token={token} onCopy={copyValue} t={t} />
    },
    {
      title: t('tokens.scopes'),
      dataIndex: 'scopes',
      width: 250,
      responsive: ['xl'],
      render: (scopes: string[]) => <Space size={[4, 4]} wrap>{(scopes || []).map((scope) => <Tag key={scope}>{scope}</Tag>)}</Space>
    },
    {
      title: t('tokens.mailboxAccess'),
      dataIndex: 'mailboxAccess',
      width: 210,
      responsive: ['xl'],
      render: (_value, token) => mailboxAccessSummary(token, t)
    },
    {
      title: t('tokens.status'),
      dataIndex: 'status',
      width: 120,
      render: (_value, token) => <StatusPill tone={tokenStatusTone(token.status)}>{tokenStatusText(token.status, t)}</StatusPill>
    },
    {
      title: t('tokens.lastUsed'),
      dataIndex: 'lastUsedAt',
      width: 190,
      render: (value?: string) => value ? formatOptionalTime(value) : t('tokens.neverUsed')
    },
    {
      title: t('tokens.actions'),
      width: 180,
      fixed: 'right',
      render: (_value, token) => (
        <Space onClick={(event) => event.stopPropagation()}>
          {!canCopyFullApiToken(token) ? (
            <RotateTokenConfirm token={token} loading={actionKey === `rotate:${token.id}`} onRotate={rotateToken} t={t} />
          ) : null}
          <Button aria-label={`${t('tokens.edit')} ${token.name}`} disabled={token.status === 'revoked'} icon={<EditOutlined />} onClick={() => openEdit(token)} />
          <Popconfirm title={t('tokens.revokeConfirm')} onConfirm={() => void revokeToken(token)} disabled={token.status === 'revoked'}>
            <Button aria-label={`${t('tokens.revoke')} ${token.name}`} danger disabled={token.status === 'revoked'} icon={<DeleteOutlined />} loading={actionKey === `revoke:${token.id}`} />
          </Popconfirm>
        </Space>
      )
    }
  ];

  const mailboxOptions = mailboxes.map((mailbox) => ({
    value: mailbox.id,
    label: `${mailbox.address}${isAdmin && mailbox.userId !== user?.id ? ` · UID ${mailbox.userId}` : ''}`
  }));
  const mailboxAccessOptions = [
    { label: t('tokens.mailboxAccessOwner'), value: 'owner' },
    { label: t('tokens.mailboxAccessSelected'), value: 'selected' },
    ...(isAdmin ? [{ label: t('tokens.mailboxAccessAll'), value: 'all' }] : [])
  ];

  return (
    <Space direction="vertical" size={20} className="full-width">
      <PageHeader
        title={t('nav.tokens')}
        subtitle={t('tokens.subtitle')}
        extra={
          <Space wrap>
            <Button icon={<ReadOutlined />} onClick={() => openGuide()} style={{ minHeight: 44 }}>{t('tokens.docsTitle')}</Button>
            <Button type="primary" icon={<PlusOutlined />} onClick={openCreate} style={{ minHeight: 44 }}>{t('tokens.create')}</Button>
          </Space>
        }
      />
      {loadError ? <Alert type="error" showIcon message={loadError} action={<Button icon={<ReloadOutlined />} onClick={() => void loadData()}>{t('common.refresh')}</Button>} /> : null}
      {loadError && !tokens.length ? null : (
        <SectionCard title={t('tokens.listTitle')} extra={<StatusPill tone="neutral">{tokens.length}</StatusPill>}>
          <Alert type="info" showIcon message={t('tokens.prefixOnlyHelp')} style={{ marginBottom: 16 }} />
          {loading ? <Skeleton active paragraph={{ rows: 6 }} /> : tokens.length ? (
            <Table
              rowKey="id"
              columns={columns}
              dataSource={tokens}
              scroll={{ x: 1030 }}
              onRow={(token) => ({
                onClick: () => openTokenDetail(token),
                style: { cursor: 'pointer' },
                tabIndex: 0,
                onKeyDown: (event) => {
                  if (event.target !== event.currentTarget) return;
                  if (event.key === 'Enter' || event.key === ' ') {
                    event.preventDefault();
                    openTokenDetail(token);
                  }
                }
              })}
            />
          ) : <EmptyState description={t('tokens.noTokenHint')} action={<Button icon={<PlusOutlined />} onClick={openCreate}>{t('tokens.create')}</Button>} />}
        </SectionCard>
      )}

      <Drawer
        title={editingToken ? t('tokens.editTitle') : t('tokens.createTitle')}
        width={560}
        open={editorOpen}
        onClose={() => setEditorOpen(false)}
        destroyOnHidden
        footer={<Space style={{ display: 'flex', justifyContent: 'flex-end' }}><Button onClick={() => setEditorOpen(false)}>{t('common.cancel')}</Button><Button type="primary" icon={<KeyOutlined />} loading={actionKey === 'create' || actionKey.startsWith('save:')} onClick={() => void saveToken()}>{editingToken ? t('common.save') : t('tokens.create')}</Button></Space>}
      >
        {!editingToken ? <Alert type="info" showIcon message={t('tokens.createdWarning')} style={{ marginBottom: 20 }} /> : null}
        <Form form={form} layout="vertical" initialValues={{ scopes: ['send'], mailboxAccess: 'owner', mailboxIds: [] }}>
          <Form.Item name="name" label={t('tokens.name')} rules={[{ required: true, message: t('tokens.nameRequired') }]}><Input placeholder={t('tokens.namePlaceholder')} autoComplete="off" /></Form.Item>
          <Form.Item name="expiresAt" label={t('tokens.expiresAt')} extra={t('tokens.expiresAtExtra')}><Input type="datetime-local" /></Form.Item>
          <Form.Item name="scopes" label={t('tokens.scopes')} rules={[{ required: true, type: 'array', min: 1, message: t('tokens.scopesRequired') }]} extra={t('tokens.scopesExtra')}><Checkbox.Group options={scopeOptions} /></Form.Item>
          {messagesReadEnabled ? (
            <>
              <Form.Item name="mailboxAccess" label={t('tokens.mailboxAccess')} extra={t('tokens.mailboxAccessExtra')} rules={[{ required: true }]}>
                <Radio.Group className="full-width" style={{ display: 'grid', gap: 4 }}>
                  {mailboxAccessOptions.map((option) => (
                    <Radio key={option.value} value={option.value} style={{ alignItems: 'center', minHeight: 44 }}>
                      {option.label}
                    </Radio>
                  ))}
                </Radio.Group>
              </Form.Item>
              {selectedMailboxAccess === 'selected' ? (
                <Form.Item
                  name="mailboxIds"
                  label={t('tokens.mailboxIds')}
                  rules={[{ type: 'array', min: 1, required: true, message: t('tokens.mailboxIdsRequired') }]}
                >
                  <Select
                    mode="multiple"
                    allowClear
                    showSearch
                    optionFilterProp="label"
                    options={mailboxOptions}
                    placeholder={t('tokens.mailboxIdsPlaceholder')}
                    status={mailboxError ? 'error' : undefined}
                  />
                </Form.Item>
              ) : null}
              {mailboxError ? <Alert type="error" showIcon message={mailboxError} action={<Button size="small" onClick={() => void loadData()}>{t('common.refresh')}</Button>} /> : null}
            </>
          ) : null}
        </Form>
      </Drawer>

      <Drawer title={selectedToken?.name || t('nav.tokens')} width={600} open={Boolean(requestedTokenId)} onClose={closeTokenDetail}>
        {loading && !selectedToken ? <Skeleton active paragraph={{ rows: 6 }} /> : selectedToken ? (
          <Space direction="vertical" size={20} className="full-width">
            <Descriptions bordered column={1} size="small">
              <Descriptions.Item label={t('tokens.fullToken')}><TokenValue token={selectedToken} onCopy={copyValue} t={t} /></Descriptions.Item>
              <Descriptions.Item label={t('tokens.prefix')}><Typography.Text code>{formatApiTokenPrefix(selectedToken)}</Typography.Text></Descriptions.Item>
              <Descriptions.Item label={t('tokens.status')}><StatusPill tone={tokenStatusTone(selectedToken.status)}>{tokenStatusText(selectedToken.status, t)}</StatusPill></Descriptions.Item>
              <Descriptions.Item label={t('tokens.scopes')}><Space wrap>{selectedToken.scopes.map((scope) => <Tag key={scope}>{scope}</Tag>)}</Space></Descriptions.Item>
              <Descriptions.Item label={t('tokens.mailboxAccess')}>{mailboxAccessSummary(selectedToken, t)}</Descriptions.Item>
              {selectedToken.scopes.includes('messages:read') && selectedToken.mailboxAccess === 'selected' ? (
                <Descriptions.Item label={t('tokens.mailboxIds')}>
                  <Space size={[4, 4]} wrap>{selectedToken.mailboxIds.map((id) => <Tag key={id}>{mailboxes.find((mailbox) => mailbox.id === id)?.address || `#${id}`}</Tag>)}</Space>
                </Descriptions.Item>
              ) : null}
              <Descriptions.Item label={t('tokens.expiresAt')}>{formatOptionalTime(selectedToken.expiresAt)}</Descriptions.Item>
              <Descriptions.Item label={t('tokens.lastUsed')}>{selectedToken.lastUsedAt ? formatOptionalTime(selectedToken.lastUsedAt) : t('tokens.neverUsed')}</Descriptions.Item>
              <Descriptions.Item label={t('tokens.createdAt')}>{formatOptionalTime(selectedToken.createdAt)}</Descriptions.Item>
            </Descriptions>
            <Alert
              type={canCopyFullApiToken(selectedToken) ? 'success' : 'warning'}
              showIcon
              message={canCopyFullApiToken(selectedToken) ? t('tokens.secretAvailable') : t('tokens.secretUnavailable')}
              action={!canCopyFullApiToken(selectedToken) && selectedToken.status !== 'revoked' ? <RotateTokenConfirm token={selectedToken} loading={actionKey === `rotate:${selectedToken.id}`} onRotate={rotateToken} t={t} text /> : undefined}
            />
            <Button icon={<ReadOutlined />} onClick={() => openGuide()}>{t('tokens.docsTitle')}</Button>
          </Space>
        ) : loadError && requestedTokenId ? (
          <Alert type="error" showIcon message={loadError} action={<Button icon={<ReloadOutlined />} onClick={() => void loadData()}>{t('common.refresh')}</Button>} />
        ) : requestedTokenId ? <EmptyState description={t('common.notFound')} /> : null}
      </Drawer>

      <ApiGuideDrawer open={guideOpen} section={guideSection} config={config} onClose={closeGuide} onSectionChange={openGuide} onCopy={copyValue} />

      <Modal
        title={secretModalMode === 'rotated' ? t('tokens.rotatedTitle') : t('tokens.createdTitle')}
        open={Boolean(revealedToken)}
        closable={false}
        maskClosable={false}
        keyboard={false}
        destroyOnHidden
        footer={[
          <Button key="copy" icon={<CopyOutlined />} onClick={() => void copyValue(getCreatedApiTokenSecret(revealedToken || {}) || '')}>{t('tokens.copyCreated')}</Button>,
          <Button key="done" type="primary" onClick={() => setRevealedToken(null)}>{t('common.confirm')}</Button>
        ]}
      >
        {revealedToken ? (
          <Space direction="vertical" size={16} className="full-width">
            <Alert type={secretModalMode === 'rotated' ? 'warning' : 'info'} showIcon message={secretModalMode === 'rotated' ? t('tokens.rotatedWarning') : t('tokens.createdWarning')} />
            <CodeBlock value={getCreatedApiTokenSecret(revealedToken) || ''} onCopy={copyValue} />
          </Space>
        ) : null}
      </Modal>
    </Space>
  );
}

function TokenValue({ token, onCopy, t }: { token: ApiToken; onCopy: (value: string) => void; t: (key: string) => string }) {
  if (!canCopyFullApiToken(token)) return <StatusPill tone="warning">{t('tokens.unrecoverable')}</StatusPill>;
  return (
    <Space size={8} align="start" style={{ maxWidth: '100%' }}>
      <Typography.Text code style={{ overflowWrap: 'anywhere', wordBreak: 'break-all' }}>{token.token}</Typography.Text>
      <Button
        aria-label={`${t('tokens.copyFull')} ${token.name}`}
        icon={<CopyOutlined />}
        onClick={(event) => {
          event.stopPropagation();
          void onCopy(token.token || '');
        }}
        style={{ minHeight: 44, minWidth: 44 }}
      />
    </Space>
  );
}

function RotateTokenConfirm({ token, loading, onRotate, t, text = false }: { token: ApiToken; loading: boolean; onRotate: (token: ApiToken) => void; t: (key: string) => string; text?: boolean }) {
  return (
    <Popconfirm
      title={t('tokens.rotateConfirm')}
      description={t('tokens.rotateConfirmDescription')}
      okText={t('tokens.rotate')}
      okButtonProps={{ danger: true }}
      onConfirm={() => void onRotate(token)}
      disabled={token.status === 'revoked'}
    >
      <Button
        aria-label={`${t('tokens.rotate')} ${token.name}`}
        icon={<ReloadOutlined />}
        danger
        disabled={token.status === 'revoked'}
        loading={loading}
        style={{ minHeight: 44, minWidth: text ? undefined : 44 }}
      >
        {text ? t('tokens.rotate') : null}
      </Button>
    </Popconfirm>
  );
}

function ApiGuideDrawer({ open, section, config, onClose, onSectionChange, onCopy }: { open: boolean; section: GuideSection; config: RuntimeConfig | null; onClose: () => void; onSectionChange: (section: GuideSection) => void; onCopy: (value: string) => void }) {
  const { t } = useI18n();
  const baseUrl = secureApiBaseUrl(config?.appBaseUrl, window.location.origin);
  const endpoint = `${baseUrl}/api/send`;
  const mailboxEndpoint = `${baseUrl}/api/mailboxes`;
  const inboundMessagesEndpoint = `${baseUrl}/api/inbound-messages`;
  const inboundMailboxesEndpoint = `${baseUrl}/api/inbound-mailboxes`;
  const examples = useMemo(() => buildApiUsageExamples({ endpoint, token: '<USER_API_TOKEN>', from: 'noreply@example.com', to: 'user@example.com' }), [endpoint]);
  const mailboxExamples = useMemo(() => buildMailboxApiUsageExamples({ endpoint: mailboxEndpoint, token: '<MAILBOX_API_TOKEN>' }), [mailboxEndpoint]);
  const inboundExamples = useMemo(() => buildInboundMessageApiUsageExamples({ endpoint: inboundMessagesEndpoint, mailboxEndpoint: inboundMailboxesEndpoint, token: '<MESSAGES_API_TOKEN>' }), [inboundMailboxesEndpoint, inboundMessagesEndpoint]);
  return (
    <Drawer title={t('tokens.docsTitle')} width={760} open={open} onClose={onClose}>
      <Space direction="vertical" size={16} className="full-width">
        <Descriptions column={1} bordered size="small">
          <Descriptions.Item label={t('tokens.endpoint')}><Typography.Text code copyable={{ onCopy: () => onCopy(endpoint) }}>{endpoint}</Typography.Text></Descriptions.Item>
          <Descriptions.Item label={t('tokens.mailboxEndpoint')}><Typography.Text code copyable={{ onCopy: () => onCopy(mailboxEndpoint) }}>{mailboxEndpoint}</Typography.Text></Descriptions.Item>
          <Descriptions.Item label={t('tokens.messagesApi')}><Typography.Text code copyable={{ onCopy: () => onCopy(inboundMessagesEndpoint) }}>{inboundMessagesEndpoint}</Typography.Text></Descriptions.Item>
          <Descriptions.Item label={t('tokens.authHeader')}><Typography.Text code>{t('tokens.authHeaderValue')}</Typography.Text></Descriptions.Item>
        </Descriptions>
        <Collapse
          accordion
          activeKey={section}
          onChange={(key) => onSectionChange(normalizeGuideSection(Array.isArray(key) ? key[0] : key))}
          items={[
            {
              key: 'send',
              label: t('tokens.sendApi'),
              children: <Space direction="vertical" size={12} className="full-width"><Typography.Text strong>{t('tokens.curlExample')}</Typography.Text><CodeBlock value={examples.curl} onCopy={onCopy} /><Typography.Text strong>{t('tokens.requestExample')}</Typography.Text><CodeBlock value={examples.requestBody} onCopy={onCopy} /><Typography.Text strong>{t('tokens.responseExample')}</Typography.Text><CodeBlock value={examples.successResponse} onCopy={onCopy} /></Space>
            },
            {
              key: 'mailboxes',
              label: t('tokens.mailboxApi'),
              children: <Space direction="vertical" size={12} className="full-width"><Alert type="info" showIcon message={t('tokens.mailboxApiHint')} /><Typography.Text strong>{t('tokens.permanentMailbox')}</Typography.Text><CodeBlock value={mailboxExamples.permanentCurl} onCopy={onCopy} /><Typography.Text strong>{t('tokens.temporaryMailbox')}</Typography.Text><CodeBlock value={mailboxExamples.temporaryCurl} onCopy={onCopy} /><Typography.Text strong>{t('tokens.mailboxResponse')}</Typography.Text><CodeBlock value={mailboxExamples.successResponse} onCopy={onCopy} /></Space>
            },
            {
              key: 'messages',
              label: t('tokens.messagesApi'),
              children: (
                <Space direction="vertical" size={12} className="full-width">
                  <Alert type="info" showIcon message={t('tokens.messagesApiHint')} description={t('tokens.messagesAccess')} />
                  <Typography.Text>{t('tokens.messagesFilters')}</Typography.Text>
                  <Typography.Text strong>{t('tokens.messagesList')}</Typography.Text>
                  <CodeBlock value={inboundExamples.listCurl} onCopy={onCopy} />
                  <CodeBlock value={inboundExamples.listResponse} onCopy={onCopy} />
                  <Typography.Text strong>{t('tokens.messageDetail')}</Typography.Text>
                  <CodeBlock value={inboundExamples.detailCurl} onCopy={onCopy} />
                  <CodeBlock value={inboundExamples.detailResponse} onCopy={onCopy} />
                  <Typography.Text strong>{t('tokens.mailboxFolders')}</Typography.Text>
                  <CodeBlock value={inboundExamples.foldersCurl} onCopy={onCopy} />
                  <CodeBlock value={inboundExamples.foldersResponse} onCopy={onCopy} />
                </Space>
              )
            }
          ]}
        />
        <Alert type="warning" showIcon message={t('tokens.securityTipStore')} description={t('tokens.securityTipScopes')} />
      </Space>
    </Drawer>
  );
}

function toTokenPayload(values: TokenFormValues): ApiTokenInput {
  const messagesRead = values.scopes.includes('messages:read');
  const mailboxAccess = messagesRead ? values.mailboxAccess || 'owner' : 'owner';
  return {
    name: values.name.trim(),
    scopes: values.scopes,
    expiresAt: values.expiresAt ? new Date(values.expiresAt).toISOString() : null,
    mailboxAccess,
    mailboxIds: messagesRead && mailboxAccess === 'selected' ? values.mailboxIds || [] : []
  };
}

function mailboxAccessSummary(token: ApiToken, t: (key: string) => string) {
  if (!token.scopes.includes('messages:read')) return '—';
  if (token.mailboxAccess === 'all') return <StatusPill tone="warning">{t('tokens.mailboxAccessAll')}</StatusPill>;
  if (token.mailboxAccess === 'selected') return <StatusPill tone="info">{t('tokens.mailboxAccessSelected')} · {token.mailboxIds.length}</StatusPill>;
  return <StatusPill tone="neutral">{t('tokens.mailboxAccessOwner')}</StatusPill>;
}

function toDatetimeLocal(value?: string | null) {
  if (!value) return '';
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return '';
  const offset = date.getTimezoneOffset() * 60_000;
  return new Date(date.getTime() - offset).toISOString().slice(0, 16);
}

function tokenStatusTone(status?: string): StatusTone {
  if (status === 'active') return 'success';
  if (status === 'expired') return 'warning';
  if (status === 'revoked') return 'error';
  return 'neutral';
}

function tokenStatusText(status: string | undefined, t: (key: string) => string) {
  if (status === 'active') return t('tokens.statusActive');
  if (status === 'expired') return t('tokens.statusExpired');
  if (status === 'revoked') return t('tokens.statusRevoked');
  return '—';
}

function formatOptionalTime(value?: string | null) {
  return value ? new Date(value).toLocaleString() : '—';
}

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

function normalizeGuideSection(value: string | null | undefined): GuideSection {
  return value === 'mailboxes' || value === 'messages' ? value : 'send';
}

function secureApiBaseUrl(configuredValue: string | null | undefined, currentOrigin: string) {
  const current = parseUrl(currentOrigin);
  if (current?.protocol === 'https:') return current.origin;
  const configured = parseUrl(configuredValue);
  if (configured?.protocol === 'https:') return configured.origin;
  if (configured && !isLocalHostname(configured.hostname)) {
    configured.protocol = 'https:';
    return configured.origin;
  }
  return configured?.origin || current?.origin || '';
}

function parseUrl(value: string | null | undefined) {
  if (!value) return null;
  try {
    return new URL(value);
  } catch {
    return null;
  }
}

function isLocalHostname(hostname: string) {
  return hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1';
}
