import { DeleteOutlined, LinkOutlined, PlusOutlined, QrcodeOutlined, ReloadOutlined, SaveOutlined, StopOutlined, UnorderedListOutlined } from '@ant-design/icons';
import { Alert, App, Button, Card, Checkbox, Drawer, Empty, Flex, Form, Input, InputNumber, Modal, QRCode, Select, Space, Table, Tabs, Tag, Typography } from 'antd';
import { useEffect, useLayoutEffect, useMemo, useState, type Key, type MouseEvent as ReactMouseEvent } from 'react';
import { getReadyPlayAppEntries } from '../../views/play/apps/apps/appsRegistry';
import { copyTextToClipboard } from '../../utils/clipboard';
import { openExternalLinkInNewWindow } from './mainChatPanel/linkNavigation';
import { resolveChatPathForSession } from './chatSessionRouting';
import { useTokenAccess } from './tokenAccess';
import { confirmWithKeyboard } from './modalKeyboard';
import {
  deleteSharedResourceTokens,
  deleteSharedResourceToken,
  loadSharedResourceTokenDetail,
  revokeSharedResourceTokens,
  restoreSharedResourceToken,
  revokeSharedResourceToken,
  saveSharedResourceToken,
  useSharedResourceTokenRegistry,
  type SharedResourcePermission,
  type SharedResourceTokenActivityRecord,
  type SharedResourceTokenInput,
  type SharedResourceTokenRecord,
  type SharedResourceType,
} from './sharedResourceTokenAccess';
import { createInstallManifestObjectUrl, swapInstallDocumentMetadata } from './pwa/installManifest';
import './SharedResourceManagementPage.css';

const { Paragraph, Text, Title } = Typography;

const PERMISSION_OPTIONS: Array<{ value: SharedResourcePermission; label: string; description: string }> = [
  { value: 'view', label: '조회', description: '리소스 내용을 열람합니다.' },
  { value: 'download', label: '다운로드', description: '파일 또는 산출물을 내려받습니다.' },
  { value: 'comment', label: '의견등록', description: '댓글 또는 후속 응답을 남깁니다.' },
  { value: 'upload', label: '업로드', description: '첨부 파일과 대체 산출물을 올립니다.' },
  { value: 'manage', label: '관리', description: '권한 변경과 토큰 재발급을 허용합니다.' },
];

const RESOURCE_TYPE_OPTIONS: Array<{ value: SharedResourceType; label: string }> = [
  { value: 'directory', label: '폴더' },
  { value: 'file', label: '파일' },
  { value: 'document', label: '문서' },
  { value: 'chat-share', label: '공유 채팅' },
  { value: 'external-url', label: '외부 URL' },
];

const MANAGEMENT_APP_OPTIONS = [
  { value: 'chat-live', label: 'Codex Live', description: '채팅방 조회와 응답 흐름 진입', category: '관리' },
  { value: 'chat-room-settings', label: '채팅방 설정', description: 'Codex Live 채팅방 Context 설정 편집 접근', category: '관리' },
  { value: 'text-memo-widget', label: '메모', description: '공유채팅 Apps에서 메모 컴포넌트 실행', category: '관리' },
  { value: 'token-setting', label: '토큰관리 설정', description: '토큰 설정 목록과 상세 편집 접근', category: '관리' },
  { value: 'shared-resource', label: '공유 리소스 관리', description: '공유 링크와 권한, 활동 이력 관리', category: '관리' },
  { value: 'plan-board', label: '자동화 현황', description: '작업 현황과 요청 보드 접근', category: '관리' },
  { value: 'app-settings', label: '앱 설정', description: '헤더 설정, 알림, 업데이트 화면 접근', category: '관리' },
  { value: 'server-command', label: '서버관리', description: '서버 상태 확인과 재기동 예약/실행 접근', category: '관리' },
  { value: 'resource-manager', label: '리소스 관리', description: '세션 리소스와 파일 미리보기 접근', category: '관리' },
  { value: 'error-log', label: '에러 로그', description: '앱 로그와 장애 이력 조회', category: '관리' },
] as const;

const PLAY_APP_OPTIONS = getReadyPlayAppEntries().map((entry) => ({
  value: entry.id,
  label: entry.name,
  description: entry.searchDescription ?? `${entry.name} 앱 실행`,
  category: 'Play' as const,
}));

const APP_OPTIONS = [...MANAGEMENT_APP_OPTIONS, ...PLAY_APP_OPTIONS];
const APP_OPTION_LABEL_MAP = new Map(APP_OPTIONS.map((option) => [option.value, option.label] as const));
const ADMIN_PERMISSION_PRESET: SharedResourcePermission[] = ['view', 'download', 'comment', 'upload', 'manage'];
const ADMIN_ALLOWED_APP_PRESET = MANAGEMENT_APP_OPTIONS.map((option) => option.value);

type SharedResourceManagementSharedPreview = {
  managedResourceTokenId?: string | null;
  sharePath?: string | null;
  expiresAt?: string | null;
  tokenSetting?: {
    id: string;
    name: string;
    defaultExpiresInMinutes: number;
    allowedAppIds: string[];
  } | null;
};

type SharedResourceManagementSharedAccess = {
  shareToken: string;
  managedResourceTokenId?: string | null;
};

type ConversationDrawerState = {
  tokenId: string;
  tokenName: string;
  url: string;
};

function isChatShareToken<T extends Pick<SharedResourceTokenRecord, 'resourceType'>>(
  item: T | null | undefined,
): item is T & { resourceType: 'chat-share' } {
  return item?.resourceType === 'chat-share';
}

type SharedResourceTokenFormValue = {
  id?: string;
  name: string;
  description: string;
  tokenSettingId: string;
  resourcePath: string;
  resourceType: SharedResourceType;
  shareToken?: string;
  sharePath?: string;
  allowedAppIds: string[];
  permissions: SharedResourcePermission[];
  enabled: boolean;
  expiresAt?: string;
  usageLimit: number;
};

const SHARED_RESOURCE_INSTALL_THEME_COLOR = '#0f766e';
const SHARED_RESOURCE_INSTALL_BACKGROUND_COLOR = '#f3fbf9';
const SHARED_RESOURCE_INSTALL_TITLE = '공유 리소스 관리';

function buildSharedResourceInstallTitle(isSharedManageMode: boolean) {
  return isSharedManageMode ? '공유 리소스 관리 링크' : SHARED_RESOURCE_INSTALL_TITLE;
}

const EMPTY_FORM_VALUE: SharedResourceTokenFormValue = {
  name: '',
  description: '',
  tokenSettingId: '',
  resourcePath: '',
  resourceType: 'directory',
  shareToken: '',
  sharePath: '',
  allowedAppIds: [],
  permissions: ['view'],
  enabled: true,
  expiresAt: '',
  usageLimit: 0,
};

function formatDateTime(value: string | null | undefined) {
  if (!value) {
    return '미기록';
  }

  return new Date(value).toLocaleString('ko-KR', {
    timeZone: 'Asia/Seoul',
  });
}

function formatUsage(value: number) {
  return `${value.toLocaleString('ko-KR')}회`;
}

function formatTokenUsage(value: number) {
  return `${Math.max(0, Math.round(Number(value) || 0)).toLocaleString('ko-KR')} 토큰`;
}

function formatUnlimitedNumberInput(value: string | number | null | undefined, unit: string) {
  if (value === null || value === undefined || value === '') {
    return '';
  }

  const normalized = Number(String(value).replace(/[^\d.-]/g, ''));

  if (!Number.isFinite(normalized)) {
    return String(value);
  }

  if (normalized <= 0) {
    return '무제한';
  }

  return `${normalized.toLocaleString('ko-KR')} ${unit}`;
}

function parseUnlimitedNumberInput(value: string | undefined) {
  if (!value) {
    return '';
  }

  if (value.includes('무제한')) {
    return '0';
  }

  return value.replace(/[^\d]/g, '');
}

function formatPermissionLabel(permission: SharedResourcePermission) {
  return PERMISSION_OPTIONS.find((option) => option.value === permission)?.label ?? permission;
}

function formatAppLabel(appId: string) {
  return APP_OPTION_LABEL_MAP.get(appId) ?? appId;
}

function formatDurationMinutesLabel(totalMinutes: number | null | undefined) {
  const normalizedMinutes = Number(totalMinutes ?? 0);

  if (!Number.isFinite(normalizedMinutes)) {
    return '';
  }

  if (normalizedMinutes <= 0) {
    return '무제한';
  }

  const roundedMinutes = Math.max(1, Math.round(normalizedMinutes));
  const days = Math.floor(roundedMinutes / (24 * 60));
  const hours = Math.floor((roundedMinutes % (24 * 60)) / 60);
  const minutes = roundedMinutes % 60;
  const parts: string[] = [];

  if (days > 0) {
    parts.push(`${days}일`);
  }

  if (hours > 0) {
    parts.push(`${hours}시간`);
  }

  if (minutes > 0 || parts.length === 0) {
    parts.push(`${minutes}분`);
  }

  return parts.join(' ');
}

function formatRemainingTimeLabel(expiresAt: string, nowMs: number) {
  const expiresAtMs = new Date(expiresAt).getTime();

  if (!Number.isFinite(expiresAtMs)) {
    return '';
  }

  const diffMs = expiresAtMs - nowMs;

  if (diffMs <= 0) {
    return '남은시간 없음';
  }

  const totalMinutes = Math.floor(diffMs / (60 * 1000));
  const days = Math.floor(totalMinutes / (24 * 60));
  const hours = Math.floor((totalMinutes % (24 * 60)) / 60);
  const minutes = totalMinutes % 60;
  const parts: string[] = [];

  if (days > 0) {
    parts.push(`${days}일`);
  }

  if (hours > 0) {
    parts.push(`${hours}시간`);
  }

  if (minutes > 0 || parts.length === 0) {
    parts.push(`${minutes}분`);
  }

  return `남은시간 ${parts.join(' ')}`;
}

function formatExpirySummary(value: string | null | undefined, nowMs: number) {
  if (!value) {
    return '만료 미설정';
  }

  const remainingTime = formatRemainingTimeLabel(value, nowMs);

  if (remainingTime) {
    return remainingTime;
  }

  return '만료 시각 확인 필요';
}

function resolveEffectiveExpiresAt(item: SharedResourceTokenRecord) {
  const explicitExpiresAt = item.effectiveExpiresAt ?? item.expiresAt;

  if (explicitExpiresAt) {
    return explicitExpiresAt;
  }

  const defaultExpiresInMinutes = Number(item.tokenSettingSnapshot?.defaultExpiresInMinutes ?? 0);
  const createdAtMs = Date.parse(item.createdAt);

  if (!Number.isFinite(defaultExpiresInMinutes) || defaultExpiresInMinutes <= 0 || !Number.isFinite(createdAtMs)) {
    return null;
  }

  return new Date(createdAtMs + defaultExpiresInMinutes * 60 * 1000).toISOString();
}

function formatEffectiveExpirySummary(item: SharedResourceTokenRecord, nowMs: number) {
  const effectiveExpiresAt = resolveEffectiveExpiresAt(item);
  const baseSummary = formatExpirySummary(effectiveExpiresAt, nowMs);

  return baseSummary;
}

function resolveStatusMeta(item: SharedResourceTokenRecord) {
  if (item.revokedAt) {
    return { color: 'red', label: '회수됨' };
  }

  if (!item.enabled) {
    return { color: 'default', label: '비활성' };
  }

  const expiresAt = resolveEffectiveExpiresAt(item);

  if (expiresAt && Date.parse(expiresAt) < Date.now()) {
    return { color: 'orange', label: '만료' };
  }

  return { color: 'green', label: '사용중' };
}

function resolveLinkedSettingStatusMeta(item: SharedResourceTokenRecord) {
  if (item.tokenSettingSnapshot) {
    return { color: 'cyan', label: `${item.tokenSettingSnapshot.name} 스냅샷` };
  }

  if (!item.tokenSettingId) {
    return { color: 'default', label: '미연결' };
  }
  return { color: 'default', label: `${item.tokenSettingId} 기준 스냅샷 없음` };
}

function resolveFormAllowedAppIds(item: SharedResourceTokenRecord) {
  const effectiveAllowedAppIds = item.allowedAppIds.length > 0
    ? item.allowedAppIds
    : item.resourceAllowedAppIds.length > 0
      ? item.resourceAllowedAppIds
      : item.tokenSettingSnapshot?.allowedAppIds ?? [];

  return Array.from(new Set(effectiveAllowedAppIds.map((appId) => appId.trim()).filter(Boolean)));
}

function toFormValue(item: SharedResourceTokenRecord | null): SharedResourceTokenFormValue {
  if (!item) {
    return EMPTY_FORM_VALUE;
  }

  return {
    id: item.id,
    name: item.name,
    description: item.description,
    tokenSettingId: isChatShareToken(item) ? '' : item.tokenSettingId ?? '',
    resourcePath: item.resourcePath,
    resourceType: item.resourceType,
    shareToken: item.shareToken,
    sharePath: item.sharePath,
    allowedAppIds: resolveFormAllowedAppIds(item),
    permissions: item.permissions,
    enabled: item.enabled,
    expiresAt: item.expiresAt ?? '',
    usageLimit: item.usageLimit,
  };
}

function buildAbsoluteShareUrl(path: string | null | undefined) {
  const normalizedPath = path?.trim() ?? '';

  if (!normalizedPath) {
    return '-';
  }

  if (/^https?:\/\//i.test(normalizedPath)) {
    return normalizedPath;
  }

  if (typeof window === 'undefined') {
    return normalizedPath;
  }

  return new URL(normalizedPath, window.location.origin).toString();
}

function decodeBase64Url(value: string) {
  const normalized = value.replace(/-/g, '+').replace(/_/g, '/');
  const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4);

  if (typeof window === 'undefined' || typeof window.atob !== 'function') {
    return null;
  }

  try {
    return window.atob(padded);
  } catch {
    return null;
  }
}

function resolveChatShareSessionId(path: string | null | undefined) {
  const normalizedPath = path?.trim() ?? '';

  if (!normalizedPath) {
    return null;
  }

  try {
    const url =
      /^https?:\/\//i.test(normalizedPath) && typeof window !== 'undefined'
        ? new URL(normalizedPath)
        : new URL(normalizedPath, typeof window !== 'undefined' ? window.location.origin : 'https://preview.sm-home.cloud');
    const prefix = '/chat/share/';

    if (!url.pathname.startsWith(prefix)) {
      return null;
    }

    const encodedToken = decodeURIComponent(url.pathname.slice(prefix.length).trim());
    const delimiterIndex = encodedToken.lastIndexOf('.');

    if (delimiterIndex <= 0) {
      return null;
    }

    const payloadText = decodeBase64Url(encodedToken.slice(0, delimiterIndex));

    if (!payloadText) {
      return null;
    }

    const payload = JSON.parse(payloadText) as { sessionId?: unknown };
    return typeof payload.sessionId === 'string' && payload.sessionId.trim() ? payload.sessionId.trim() : null;
  } catch {
    return null;
  }
}

function buildChatConversationUrl(item: Pick<SharedResourceTokenRecord, 'resourceType' | 'sharePath' | 'resourcePath'> | null | undefined) {
  if (!isChatShareToken(item)) {
    return null;
  }

  const shareUrl = buildAbsoluteShareUrl(item.sharePath);

  if (shareUrl !== '-') {
    return shareUrl;
  }

  const sessionId = resolveChatShareSessionId(item.sharePath || item.resourcePath);

  if (!sessionId) {
    return null;
  }

  return buildAbsoluteShareUrl(`${resolveChatPathForSession(sessionId)}?sessionId=${encodeURIComponent(sessionId)}`);
}

function sanitizeActivityDetail(value: string | null | undefined) {
  const normalized = value?.trim() ?? '';

  if (!normalized) {
    return null;
  }

  const withoutAbsoluteUrls = normalized.replace(/https?:\/\/\S+/giu, '').trim();
  const withoutSharePaths = withoutAbsoluteUrls
    .replace(/(?:^|\s)(?:\/chat\/share\/|\/share\/resource\/)\S*/giu, ' ')
    .replace(/\s{2,}/g, ' ')
    .trim();

  return withoutSharePaths || null;
}

function SharedResourceQrPanel({
  shareUrl,
  title = '공유 QR',
}: {
  shareUrl: string;
  title?: string;
}) {
  return (
    <div className="shared-resource-management-page__qr-panel">
      <Text strong>{title}</Text>
      <div className="shared-resource-management-page__qr-code-wrap">
        <QRCode value={shareUrl} size={168} bordered={false} />
      </div>
      <Paragraph
        copyable={{ text: shareUrl }}
        ellipsis={{ rows: 2, tooltip: shareUrl }}
        className="shared-resource-management-page__qr-url"
      >
        {shareUrl}
      </Paragraph>
      <Text type="secondary">모바일 카메라로 바로 열 수 있습니다.</Text>
    </div>
  );
}

export function SharedResourceManagementPage({
  sharedPreview = null,
  sharedAccess = null,
  disableInstallMetadata = false,
}: {
  sharedPreview?: SharedResourceManagementSharedPreview | null;
  sharedAccess?: SharedResourceManagementSharedAccess | null;
  disableInstallMetadata?: boolean;
}) {
  const { message } = App.useApp();
  const { hasAccess } = useTokenAccess();
  const isSharedManageMode = !hasAccess && Boolean(sharedAccess?.shareToken);
  const { tokens, isLoading, errorMessage, refresh } = useSharedResourceTokenRegistry(
    isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
  );
  const [selectedTokenId, setSelectedTokenId] = useState<string | null>(null);
  const [detailMode, setDetailMode] = useState<'list' | 'detail'>('list');
  const [isCreating, setIsCreating] = useState(false);
  const [isSaving, setIsSaving] = useState(false);
  const [isDetailLoading, setIsDetailLoading] = useState(false);
  const [saveErrorMessage, setSaveErrorMessage] = useState('');
  const [detailData, setDetailData] = useState<{ token: SharedResourceTokenRecord; activities: SharedResourceTokenActivityRecord[] } | null>(null);
  const [nowMs, setNowMs] = useState(() => Date.now());
  const [activeDetailTab, setActiveDetailTab] = useState<'basic' | 'settings' | 'history'>('basic');
  const [selectedRowKeys, setSelectedRowKeys] = useState<Key[]>([]);
  const [qrPreviewTokenId, setQrPreviewTokenId] = useState<string | null>(null);
  const [conversationDrawer, setConversationDrawer] = useState<ConversationDrawerState | null>(null);
  const [conversationDrawerKey, setConversationDrawerKey] = useState(0);
  const [form] = Form.useForm<SharedResourceTokenFormValue>();
  const [modalApi, modalContextHolder] = Modal.useModal();

  useLayoutEffect(() => {
    if (disableInstallMetadata || typeof window === 'undefined') {
      return undefined;
    }

    const startPath = `${window.location.pathname}${window.location.search}${window.location.hash}`;
    const installTitle = buildSharedResourceInstallTitle(isSharedManageMode);
    const manifestObjectUrl = createInstallManifestObjectUrl({
      startPath,
      scope: window.location.pathname,
      name: installTitle,
      shortName: '공유 리소스',
      description: isSharedManageMode
        ? '공유 리소스 관리 링크를 홈 화면 앱으로 바로 엽니다.'
        : '공유 리소스 관리 화면을 홈 화면 앱으로 바로 엽니다.',
      themeColor: SHARED_RESOURCE_INSTALL_THEME_COLOR,
      backgroundColor: SHARED_RESOURCE_INSTALL_BACKGROUND_COLOR,
    });
    const restoreManifest = swapInstallDocumentMetadata({
      manifestHref: manifestObjectUrl,
      title: installTitle,
      themeColor: SHARED_RESOURCE_INSTALL_THEME_COLOR,
    });

    return () => {
      restoreManifest();
      if (manifestObjectUrl) {
        window.URL.revokeObjectURL(manifestObjectUrl);
      }
    };
  }, [disableInstallMetadata, isSharedManageMode]);

  useEffect(() => {
    const intervalId = window.setInterval(() => {
      setNowMs(Date.now());
    }, 60 * 1000);

    return () => window.clearInterval(intervalId);
  }, []);

  useEffect(() => {
    if (isSharedManageMode) {
      const nextSelectedTokenId = sharedAccess?.managedResourceTokenId?.trim() || tokens[0]?.id || null;
      setSelectedTokenId(nextSelectedTokenId);
      setDetailMode('detail');
      setIsCreating(false);
      return;
    }

    if (selectedTokenId && tokens.some((item) => item.id === selectedTokenId)) {
      return;
    }

    setSelectedTokenId(tokens[0]?.id ?? null);
  }, [isSharedManageMode, selectedTokenId, sharedAccess?.managedResourceTokenId, tokens]);

  useEffect(() => {
    if (selectedRowKeys.length === 0) {
      return;
    }

    const tokenIdSet = new Set(tokens.map((item) => item.id));
    const nextSelectedRowKeys = selectedRowKeys.filter((key) => tokenIdSet.has(typeof key === 'string' ? key : String(key)));

    if (nextSelectedRowKeys.length !== selectedRowKeys.length) {
      setSelectedRowKeys(nextSelectedRowKeys);
    }
  }, [selectedRowKeys, tokens]);

  useEffect(() => {
    if (detailMode !== 'detail') {
      return;
    }

    if (isCreating) {
      form.resetFields();
      form.setFieldsValue(EMPTY_FORM_VALUE);
      setDetailData(null);
      return;
    }

    if (!selectedTokenId) {
      setDetailData(null);
      return;
    }

    let cancelled = false;

    const loadDetail = async () => {
      setIsDetailLoading(true);
      setSaveErrorMessage('');

      try {
        const detail = await loadSharedResourceTokenDetail(
          selectedTokenId,
          isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
        );

        if (cancelled) {
          return;
        }

        setDetailData(detail);
        form.resetFields();
        form.setFieldsValue(toFormValue(detail.token));
      } catch (error) {
        if (!cancelled && !(error instanceof DOMException && error.name === 'AbortError')) {
          setSaveErrorMessage(error instanceof Error ? error.message : '상세 정보를 불러오지 못했습니다.');
        }
      } finally {
        if (!cancelled) {
          setIsDetailLoading(false);
        }
      }
    };

    void loadDetail();

    return () => {
      cancelled = true;
    };
  }, [detailMode, form, isCreating, isSharedManageMode, selectedTokenId, sharedAccess?.shareToken]);

  const summary = useMemo(() => {
    const activeCount = tokens.filter((item) => !item.revokedAt && item.enabled).length;
    const revokedCount = tokens.filter((item) => Boolean(item.revokedAt)).length;
    const usageTotal = tokens.reduce((sum, item) => sum + item.usageCount, 0);
    const tokenUsageTotal = tokens.reduce((sum, item) => sum + item.usageTokenTotal, 0);
    const activityTotal = tokens.reduce((sum, item) => sum + item.activityCount, 0);

    return {
      activeCount,
      revokedCount,
      usageTotal,
      tokenUsageTotal,
      activityTotal,
    };
  }, [tokens]);

  const selectedTokenIds = useMemo(
    () =>
      selectedRowKeys
        .map((value) => (typeof value === 'string' ? value : String(value)))
        .filter((value): value is string => Boolean(value)),
    [selectedRowKeys],
  );

  const selectedTokens = useMemo(
    () => tokens.filter((item) => selectedTokenIds.includes(item.id)),
    [selectedTokenIds, tokens],
  );

  const bulkRevocableTokenIds = useMemo(
    () => selectedTokens.filter((item) => !item.revokedAt).map((item) => item.id),
    [selectedTokens],
  );

  const bulkDeletableTokenIds = useMemo(() => selectedTokens.map((item) => item.id), [selectedTokens]);
  const qrPreviewToken = useMemo(() => tokens.find((item) => item.id === qrPreviewTokenId) ?? null, [qrPreviewTokenId, tokens]);
  const qrPreviewUrl = useMemo(
    () => (qrPreviewToken?.sharePath ? buildAbsoluteShareUrl(qrPreviewToken.sharePath) : ''),
    [qrPreviewToken],
  );
  const detailConversationUrl = useMemo(
    () => (detailData?.token ? buildChatConversationUrl(detailData.token) : null),
    [detailData],
  );
  const openConversationWindow = (url: string, event?: ReactMouseEvent<HTMLElement>) => {
    openExternalLinkInNewWindow(url, {
      event,
      allowSameTabFallback: false,
      onUnsupportedStandalone: (fallbackUrl) => {
        void copyTextToClipboard(fallbackUrl)
          .then(() => {
            message.info('현재 창은 유지하고 공유채팅 URL만 복사했습니다. 브라우저나 새 PWA 창에서 붙여 열어 주세요.');
          })
          .catch(() => {
            message.info('현재 창은 유지했습니다. 새 창 열기가 막히면 QR 코드나 URL 복사로 이어서 열어 주세요.');
          });
      },
    });
  };
  const openConversationDrawer = (tokenId: string, tokenName: string, url: string) => {
    setConversationDrawer({
      tokenId,
      tokenName,
      url,
    });
    setConversationDrawerKey((current) => current + 1);
  };

  const listColumns = useMemo(
    () => [
      {
        title: '리소스',
        key: 'resource',
        ellipsis: true,
        render: (_value: unknown, item: SharedResourceTokenRecord) => {
          const linkedSettingMeta = resolveLinkedSettingStatusMeta(item);

          return (
            <div className="shared-resource-management-page__table-primary">
              <div className="shared-resource-management-page__table-title-row">
                <Text strong ellipsis={{ tooltip: item.name }}>
                  {item.name}
                </Text>
                <Tag color={resolveStatusMeta(item).color}>{resolveStatusMeta(item).label}</Tag>
              </div>
              <Space size={[6, 4]} wrap>
                {item.resourceLabel && item.resourceLabel !== item.name ? (
                  <Text type="secondary" ellipsis={{ tooltip: item.resourceLabel }}>
                    {item.resourceLabel}
                  </Text>
                ) : null}
                <Tag>{RESOURCE_TYPE_OPTIONS.find((option) => option.value === item.resourceType)?.label ?? item.resourceType}</Tag>
                {item.tokenSettingId ? <Tag color={linkedSettingMeta.color}>{linkedSettingMeta.label}</Tag> : null}
              </Space>
              {item.linkedTokenSetting?.syncMessage ? (
                <Text type="danger" className="shared-resource-management-page__table-warning">
                  {item.linkedTokenSetting.syncMessage}
                </Text>
              ) : null}
            </div>
          );
        },
      },
      {
        title: '권한',
        key: 'permissions',
        width: 188,
        render: (_value: unknown, item: SharedResourceTokenRecord) => (
          <div className="shared-resource-management-page__table-tags">
            {item.permissions.map((permission) => (
              <Tag key={`${item.id}-${permission}`}>{formatPermissionLabel(permission)}</Tag>
            ))}
          </div>
        ),
      },
      {
        title: '사용',
        key: 'usage',
        width: 132,
        render: (_value: unknown, item: SharedResourceTokenRecord) => (
          <div className="shared-resource-management-page__table-metrics">
            <Text>{formatTokenUsage(item.usageTokenTotal)}</Text>
            <Text type="secondary">{`요청 ${item.usageRequestCount}건 · 사용 ${formatUsage(item.usageCount)}`}</Text>
          </div>
        ),
      },
      {
        title: '최근',
        key: 'recent',
        width: 220,
        render: (_value: unknown, item: SharedResourceTokenRecord) => (
          <div className="shared-resource-management-page__table-metrics">
            <Text>{formatDateTime(item.lastTokenUsedAt ?? item.lastActivityAt ?? item.updatedAt)}</Text>
            <Text
              type="secondary"
              ellipsis={{ tooltip: `${formatEffectiveExpirySummary(item, nowMs)}\n${item.description || item.sharePath || '-'}` }}
            >
              {item.usageCompletedRequestCount > 0
                ? `완료 ${item.usageCompletedRequestCount}건 · ${formatEffectiveExpirySummary(item, nowMs)}`
                : formatEffectiveExpirySummary(item, nowMs)}
            </Text>
          </div>
        ),
      },
      {
        title: '채팅',
        key: 'chat',
        width: 108,
        align: 'center' as const,
        render: (_value: unknown, item: SharedResourceTokenRecord) => {
          const conversationUrl = buildChatConversationUrl(item);

          return (
            <Button
              size="small"
              icon={<LinkOutlined />}
              disabled={!conversationUrl}
              onClick={(event) => {
                event.stopPropagation();

                if (!conversationUrl) {
                  return;
                }

                openConversationDrawer(item.id, item.name, conversationUrl);
              }}
            >
              열기
            </Button>
          );
        },
      },
      {
        title: 'QR',
        key: 'qr',
        width: 96,
        align: 'center' as const,
        render: (_value: unknown, item: SharedResourceTokenRecord) => (
          <Button
            size="small"
            icon={<QrcodeOutlined />}
            disabled={!item.sharePath}
            onClick={(event) => {
              event.stopPropagation();
              setQrPreviewTokenId(item.id);
            }}
          >
            QR
          </Button>
        ),
      },
    ],
    [nowMs],
  );

  const activityColumns = useMemo(
    () => [
      {
        title: '시각',
        dataIndex: 'createdAt',
        key: 'createdAt',
        render: (value: string) => formatDateTime(value),
      },
      {
        title: '유형',
        dataIndex: 'type',
        key: 'type',
        render: (value: SharedResourceTokenActivityRecord['type']) => <Tag>{value}</Tag>,
      },
      {
        title: '내용',
        dataIndex: 'summary',
        key: 'summary',
      },
      {
        title: '비고',
        dataIndex: 'detail',
        key: 'detail',
        render: (value: string | null) => sanitizeActivityDetail(value) ?? '-',
      },
      {
        title: '접속 정보',
        key: 'ip',
        render: (_value: unknown, item: SharedResourceTokenActivityRecord) => {
          const lines = [
            item.externalIp ? `외부 ${item.externalIp}` : null,
            item.clientIp ? `서버 ${item.clientIp}` : null,
            item.forwardedFor ? `XFF ${item.forwardedFor}` : null,
            item.clientId ? `client ${item.clientId}` : null,
          ].filter(Boolean);
          return lines.length > 0 ? (
            <Typography.Text style={{ whiteSpace: 'pre-line' }}>{lines.join('\n')}</Typography.Text>
          ) : '-';
        },
      },
      {
        title: '사용량',
        dataIndex: 'usageDelta',
        key: 'usageDelta',
        render: (value: number) => (value > 0 ? `+${value}` : '-'),
      },
    ],
    [],
  );

  const openCreateForm = () => {
    setIsCreating(true);
    setSelectedTokenId(null);
    setDetailMode('detail');
    setActiveDetailTab('basic');
    setDetailData(null);
    form.resetFields();
    form.setFieldsValue(EMPTY_FORM_VALUE);
  };

  const openDetail = (tokenId: string) => {
    setIsCreating(false);
    setSelectedTokenId(tokenId);
    setSelectedRowKeys([tokenId]);
    setDetailMode('detail');
  };

  const closeDetail = () => {
    setIsCreating(false);
    setDetailMode('list');
    setActiveDetailTab('basic');
    setDetailData(null);
  };

  const handleSave = async (values: SharedResourceTokenFormValue) => {
    setIsSaving(true);
    setSaveErrorMessage('');

    try {
      if (values.expiresAt?.trim() && Number.isNaN(Date.parse(values.expiresAt))) {
        throw new Error('만료 시각은 ISO 날짜 형식으로 입력해 주세요.');
      }

      const payload: SharedResourceTokenInput = {
        id: values.id ?? detailData?.token.id,
        name: values.name,
        description: values.description,
        tokenSettingId: values.tokenSettingId?.trim() || undefined,
        resourceLabel: values.name,
        resourcePath: values.resourcePath,
        resourceType: values.resourceType,
        shareToken: values.shareToken?.trim() || undefined,
        sharePath: values.sharePath?.trim() || undefined,
        resourceAllowedAppIds: Array.from(new Set(values.allowedAppIds.map((appId) => appId.trim()).filter(Boolean))),
        resourceAllowedAppIdsOverrideEnabled: true,
        permissions: values.permissions,
        enabled: values.enabled,
        expiresAt: values.expiresAt?.trim() ? new Date(values.expiresAt).toISOString() : null,
        usageLimit: values.usageLimit,
      };
      const saved = await saveSharedResourceToken(payload, isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined);
      setIsCreating(false);
      setSelectedTokenId(saved.token.id);
      setDetailData(saved);
      form.setFieldsValue(toFormValue(saved.token));
      await refresh();
    } catch (error) {
      setSaveErrorMessage(error instanceof Error ? error.message : '공유 리소스 토큰 저장에 실패했습니다.');
    } finally {
      setIsSaving(false);
    }
  };

  const handleRevoke = async () => {
    if (!detailData?.token) {
      return;
    }

    const confirmed = await confirmWithKeyboard(modalApi, {
      title: `"${detailData.token.name}" 공유 토큰을 회수할까요?`,
      okText: '회수',
      cancelText: '취소',
      okButtonProps: { danger: true },
    });

    if (!confirmed) {
      return;
    }

    setIsSaving(true);
    setSaveErrorMessage('');

    try {
      const saved = await revokeSharedResourceToken(
        detailData.token.id,
        '관리 화면에서 수동 회수',
        isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
      );
      setDetailData(saved);
      form.setFieldsValue(toFormValue(saved.token));
      await refresh();
    } catch (error) {
      setSaveErrorMessage(error instanceof Error ? error.message : '공유 토큰 회수에 실패했습니다.');
    } finally {
      setIsSaving(false);
    }
  };

  const handleRestore = async () => {
    if (!detailData?.token) {
      return;
    }

    setIsSaving(true);
    setSaveErrorMessage('');

    try {
      const saved = await restoreSharedResourceToken(
        detailData.token.id,
        isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
      );
      setDetailData(saved);
      form.setFieldsValue(toFormValue(saved.token));
      await refresh();
    } catch (error) {
      setSaveErrorMessage(error instanceof Error ? error.message : '공유 토큰 복원에 실패했습니다.');
    } finally {
      setIsSaving(false);
    }
  };

  const handleDelete = async () => {
    if (!detailData?.token) {
      return;
    }

    const confirmed = await confirmWithKeyboard(modalApi, {
      title: `"${detailData.token.name}" 공유 토큰을 삭제할까요?`,
      content: '삭제 후 되돌릴 수 없고 연결된 공유 토큰 이력도 함께 제거됩니다.',
      okText: '삭제',
      cancelText: '취소',
      okButtonProps: { danger: true },
    });

    if (!confirmed) {
      return;
    }

    setIsSaving(true);
    setSaveErrorMessage('');

    try {
      await deleteSharedResourceToken(
        detailData.token.id,
        isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
      );
      await refresh();
      closeDetail();
    } catch (error) {
      setSaveErrorMessage(error instanceof Error ? error.message : '공유 토큰 삭제에 실패했습니다.');
    } finally {
      setIsSaving(false);
    }
  };

  const handleBulkRevoke = async () => {
    if (bulkRevocableTokenIds.length === 0) {
      return;
    }

    const confirmed = await confirmWithKeyboard(modalApi, {
      title: `선택한 ${bulkRevocableTokenIds.length}개 공유 토큰을 일괄 회수할까요?`,
      content:
        selectedTokens.length > bulkRevocableTokenIds.length
          ? '이미 회수된 항목은 그대로 두고, 사용 중인 항목만 회수합니다.'
          : '선택한 항목의 공유 접근을 즉시 중단합니다.',
      okText: '일괄 회수',
      cancelText: '취소',
      okButtonProps: { danger: true },
    });

    if (!confirmed) {
      return;
    }

    setIsSaving(true);
    setSaveErrorMessage('');

    try {
      const result = await revokeSharedResourceTokens(
        bulkRevocableTokenIds,
        '관리 화면 목록에서 일괄 회수',
        isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
      );
      await refresh();
      setSelectedRowKeys(result.processedTokenIds);
    } catch (error) {
      setSaveErrorMessage(error instanceof Error ? error.message : '공유 토큰 일괄 회수에 실패했습니다.');
    } finally {
      setIsSaving(false);
    }
  };

  const handleBulkDelete = async () => {
    if (bulkDeletableTokenIds.length === 0) {
      return;
    }

    const confirmed = await confirmWithKeyboard(modalApi, {
      title: `선택한 ${bulkDeletableTokenIds.length}개 공유 토큰을 일괄 삭제할까요?`,
      content: '삭제 후 되돌릴 수 없고 연결된 공유 토큰 이력도 함께 제거됩니다.',
      okText: '일괄 삭제',
      cancelText: '취소',
      okButtonProps: { danger: true },
    });

    if (!confirmed) {
      return;
    }

    setIsSaving(true);
    setSaveErrorMessage('');

    try {
      const result = await deleteSharedResourceTokens(
        bulkDeletableTokenIds,
        isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
      );
      await refresh();
      setSelectedRowKeys((currentKeys) =>
        currentKeys.filter((key) => !result.processedTokenIds.includes(typeof key === 'string' ? key : String(key))),
      );

      if (selectedTokenId && result.processedTokenIds.includes(selectedTokenId)) {
        closeDetail();
      }
    } catch (error) {
      setSaveErrorMessage(error instanceof Error ? error.message : '공유 토큰 일괄 삭제에 실패했습니다.');
    } finally {
      setIsSaving(false);
    }
  };

  const sharedManageInfoAlert = isSharedManageMode ? (
    <Alert
      showIcon
      type="info"
      message="현재 공유 링크에 연결된 공유 토큰 상세를 직접 수정할 수 있습니다."
      description="앱 권한, 채팅방 설정 접근, 만료 시각, 사용 한도, 공유 토큰 값, 권한 묶음까지 현재 토큰 범위 안에서 바로 재설정합니다."
    />
  ) : null;
  const applyAdminPreset = () => {
    const currentAllowedAppIds = form.getFieldValue('allowedAppIds') as string[] | undefined;
    const currentPermissions = form.getFieldValue('permissions') as SharedResourcePermission[] | undefined;

    form.setFieldsValue({
      allowedAppIds: Array.from(new Set([...(currentAllowedAppIds ?? []), ...ADMIN_ALLOWED_APP_PRESET])),
      permissions: Array.from(new Set([...(currentPermissions ?? []), ...ADMIN_PERMISSION_PRESET])),
    });
  };

  if (!hasAccess && !isSharedManageMode) {
    if (sharedPreview) {
      return (
        <Card title="공유 리소스 관리" className="chat-type-management-page">
          <Alert
            showIcon
            type="info"
            message="공유 링크에서 허용된 리소스 관리 정보입니다."
            description="관리자 권한 없이 열었으므로 현재 공유 링크와 연결된 항목만 읽기 전용으로 표시합니다."
          />
          <Flex vertical gap={12} style={{ marginTop: 16 }}>
            <div className="shared-resource-management-page__detail-grid">
              <div className="shared-resource-management-page__detail-block">
                <Text strong>공유 링크</Text>
                <Paragraph
                  copyable={sharedPreview.sharePath ? { text: buildAbsoluteShareUrl(sharedPreview.sharePath) } : false}
                  ellipsis={sharedPreview.sharePath ? { rows: 1, tooltip: buildAbsoluteShareUrl(sharedPreview.sharePath) } : false}
                  style={{ marginTop: 10, marginBottom: 0 }}
                >
                  {buildAbsoluteShareUrl(sharedPreview.sharePath)}
                </Paragraph>
              </div>
              <div className="shared-resource-management-page__detail-block">
                <Text strong>발급 시점 토큰 정책</Text>
                <Paragraph style={{ marginTop: 10, marginBottom: 6 }}>
                  {sharedPreview.tokenSetting
                    ? `${sharedPreview.tokenSetting.name} (${sharedPreview.tokenSetting.id})`
                    : '스냅샷 정보 없음'}
                </Paragraph>
                <Paragraph style={{ marginBottom: 6 }}>
                  {sharedPreview.tokenSetting
                    ? `기본 유효시간 ${formatDurationMinutesLabel(sharedPreview.tokenSetting.defaultExpiresInMinutes)}`
                    : '기본 유효시간 정보 없음'}
                </Paragraph>
                <Paragraph style={{ marginBottom: 0 }}>
                  {sharedPreview.expiresAt ? formatExpirySummary(sharedPreview.expiresAt, nowMs) : '만료 미설정'}
                </Paragraph>
              </div>
            </div>
            <div className="shared-resource-management-page__detail-block">
              <Text strong>허용 앱</Text>
              <div className="shared-resource-management-page__detail-tags" style={{ marginTop: 10 }}>
                {(sharedPreview.tokenSetting?.allowedAppIds ?? []).length > 0 ? (
                  sharedPreview.tokenSetting?.allowedAppIds.map((appId) => <Tag key={appId}>{appId}</Tag>)
                ) : (
                  <Text type="secondary">등록된 허용 앱이 없습니다.</Text>
                )}
              </div>
              {sharedPreview.managedResourceTokenId ? (
                <Paragraph type="secondary" style={{ marginTop: 12, marginBottom: 0 }}>
                  관리 토큰 ID {sharedPreview.managedResourceTokenId}
                </Paragraph>
              ) : null}
            </div>
          </Flex>
        </Card>
      );
    }

    return (
      <Card title="공유 리소스 관리" className="chat-type-management-page">
        <Alert
          showIcon
          type="warning"
          message="관리 페이지는 토큰 등록 사용자만 사용할 수 있습니다."
          description="설정 > 토큰 관리에서 권한 토큰을 등록한 뒤 공유 토큰 URL과 활동 내역을 관리하세요."
        />
      </Card>
    );
  }

  return (
    <div
      className={`chat-type-management-page shared-resource-management-page${
        detailMode === 'detail' ? ' chat-type-management-page--detail' : ''
      }`}
    >
      {modalContextHolder}
      <Modal
        open={Boolean(qrPreviewToken && qrPreviewUrl)}
        title={qrPreviewToken ? `"${qrPreviewToken.name}" QR 코드` : '공유 QR 코드'}
        footer={null}
        onCancel={() => setQrPreviewTokenId(null)}
        centered
      >
        {qrPreviewToken && qrPreviewUrl ? (
          <SharedResourceQrPanel shareUrl={qrPreviewUrl} title="공유 URL QR" />
        ) : (
          <Empty description="QR 코드를 표시할 공유 URL이 없습니다." />
        )}
      </Modal>
      <Drawer
        open={Boolean(conversationDrawer)}
        title={conversationDrawer ? `${conversationDrawer.tokenName} 채팅` : '공유 채팅'}
        placement="right"
        width="100vw"
        rootClassName="shared-resource-management-page__conversation-drawer"
        onClose={() => {
          setConversationDrawer(null);
        }}
        extra={
          conversationDrawer ? (
            <Space size={8}>
              <Button onClick={() => setConversationDrawerKey((current) => current + 1)}>새로고침</Button>
              <Button onClick={(event) => openConversationWindow(conversationDrawer.url, event)}>새 창</Button>
            </Space>
          ) : null
        }
        styles={{
          body: {
            padding: 0,
          },
        }}
      >
        {conversationDrawer ? (
          <iframe
            key={`${conversationDrawer.tokenId}-${conversationDrawerKey}`}
            title={`${conversationDrawer.tokenName} 공유 채팅`}
            src={conversationDrawer.url}
            className="shared-resource-management-page__conversation-frame"
          />
        ) : null}
      </Drawer>
      {detailMode === 'list' ? (
        <Card
          title="공유 리소스 관리"
          className="chat-type-management-page__card shared-resource-management-page__card"
          extra={
            <Space size={8}>
              <Button icon={<ReloadOutlined />} onClick={() => void refresh()}>
                새로고침
              </Button>
              <Button type="primary" icon={<PlusOutlined />} onClick={openCreateForm} disabled={isSharedManageMode}>
                신규 토큰
              </Button>
            </Space>
          }
        >
          <div className="chat-type-management-page__list">
            <div className="chat-type-management-page__list-scroll">
              {sharedManageInfoAlert}
              <div className="shared-resource-management-page__summary-strip" aria-label="공유 리소스 요약">
                <div className="shared-resource-management-page__summary-intro">
                  <Text strong>목록 우선 보기</Text>
                </div>
                <div className="shared-resource-management-page__summary-pills">
                  <div className="shared-resource-management-page__summary-pill">
                    <span className="shared-resource-management-page__summary-label">사용중</span>
                    <span className="shared-resource-management-page__summary-value">{summary.activeCount}</span>
                  </div>
                  <div className="shared-resource-management-page__summary-pill">
                    <span className="shared-resource-management-page__summary-label">회수됨</span>
                    <span className="shared-resource-management-page__summary-value">{summary.revokedCount}</span>
                  </div>
                  <div className="shared-resource-management-page__summary-pill">
                    <span className="shared-resource-management-page__summary-label">누적 토큰</span>
                    <span className="shared-resource-management-page__summary-value">{formatTokenUsage(summary.tokenUsageTotal)}</span>
                  </div>
                  <div className="shared-resource-management-page__summary-pill">
                    <span className="shared-resource-management-page__summary-label">사용/활동</span>
                    <span className="shared-resource-management-page__summary-value">{`${formatUsage(summary.usageTotal)} · ${summary.activityTotal}건`}</span>
                  </div>
                </div>
              </div>
              {errorMessage ? <Alert showIcon type="error" message={errorMessage} /> : null}
              {saveErrorMessage ? <Alert showIcon type="error" message={saveErrorMessage} /> : null}
              <div className="chat-type-management-page__list-header">
                <Title level={5}>공유 토큰 목록</Title>
                <Space size={8} wrap>
                  <Text type="secondary">{isLoading ? '불러오는 중' : `${tokens.length}건`}</Text>
                  <Text type="secondary">행 더블클릭 시 상세 편집</Text>
                </Space>
              </div>
              <div className="shared-resource-management-page__bulk-toolbar">
                <Space size={8} wrap>
                  <Text strong>{selectedTokenIds.length > 0 ? `${selectedTokenIds.length}건 선택` : '선택 없음'}</Text>
                  {selectedTokenIds.length > 0 ? (
                    <Text type="secondary">
                      {bulkRevocableTokenIds.length > 0
                        ? `회수 가능 ${bulkRevocableTokenIds.length}건`
                        : '회수 가능한 항목 없음'}
                    </Text>
                  ) : null}
                </Space>
                <Space size={8} wrap>
                  <Button disabled={selectedTokenIds.length === 0 || isSaving} onClick={() => setSelectedRowKeys([])}>
                    선택 해제
                  </Button>
                  <Button
                    disabled={bulkRevocableTokenIds.length === 0 || isSaving}
                    icon={<StopOutlined />}
                    onClick={() => void handleBulkRevoke()}
                  >
                    일괄 회수
                  </Button>
                  <Button
                    danger
                    disabled={bulkDeletableTokenIds.length === 0 || isSaving}
                    icon={<DeleteOutlined />}
                    onClick={() => void handleBulkDelete()}
                  >
                    일괄 삭제
                  </Button>
                </Space>
              </div>
              {tokens.length > 0 ? (
                <Table<SharedResourceTokenRecord>
                  className="shared-resource-management-page__table"
                  rowKey="id"
                  size="small"
                  pagination={{ pageSize: 30, size: 'small', showSizeChanger: false, hideOnSinglePage: true }}
                  columns={listColumns}
                  dataSource={tokens}
                  loading={isLoading}
                  rowSelection={{
                    selectedRowKeys,
                    onChange: (nextSelectedRowKeys) => setSelectedRowKeys(nextSelectedRowKeys),
                    preserveSelectedRowKeys: true,
                  }}
                  onRow={(record) => ({
                    onDoubleClick: () => openDetail(record.id),
                  })}
                  rowClassName={(record) =>
                    record.id === selectedTokenId
                      ? 'shared-resource-management-page__table-row shared-resource-management-page__table-row--active'
                      : 'shared-resource-management-page__table-row'
                  }
                  locale={{
                    emptyText: <Empty description="등록된 공유 리소스 토큰이 없습니다." />,
                  }}
                  scroll={{ x: 900, y: 'calc(100dvh - 220px)' }}
                />
              ) : (
                <Empty description="등록된 공유 리소스 토큰이 없습니다." />
              )}
            </div>
          </div>
        </Card>
      ) : (
        <Card
          title={isCreating ? '공유 토큰 등록' : '공유 토큰 상세'}
          className="chat-type-management-page__card shared-resource-management-page__card"
          extra={
            <Space size={6} className="chat-type-management-page__header-actions" wrap>
              <Button
                type="primary"
                shape="circle"
                icon={<SaveOutlined />}
                loading={isSaving}
                aria-label={isCreating ? '등록' : '수정 저장'}
                onClick={() => void form.submit()}
              />
              <Button
                shape="circle"
                icon={<PlusOutlined />}
                disabled={isSaving || isSharedManageMode}
                aria-label="새 입력"
                onClick={openCreateForm}
              />
              {!isCreating && detailData?.token?.revokedAt ? (
                <Button shape="circle" icon={<ReloadOutlined />} disabled={isSaving} aria-label="복원" onClick={() => void handleRestore()} />
              ) : null}
              {!isCreating && detailData?.token && !detailData.token.revokedAt ? (
                <Button
                  shape="circle"
                  icon={<StopOutlined />}
                  disabled={isSaving}
                  aria-label="회수"
                  onClick={() => void handleRevoke()}
                />
              ) : null}
              {!isCreating && detailData?.token ? (
                <Button
                  danger
                  shape="circle"
                  icon={<DeleteOutlined />}
                  disabled={isSaving}
                  aria-label="삭제"
                  onClick={() => void handleDelete()}
                />
              ) : null}
              <Button shape="circle" icon={<UnorderedListOutlined />} aria-label="목록 가기" onClick={closeDetail} />
            </Space>
          }
        >
          <div className="chat-type-management-page__editor">
            {sharedManageInfoAlert}
            {errorMessage ? <Alert showIcon type="error" message={errorMessage} /> : null}
            {saveErrorMessage ? <Alert showIcon type="error" message={saveErrorMessage} /> : null}
            <Form<SharedResourceTokenFormValue>
              layout="vertical"
              form={form}
              initialValues={EMPTY_FORM_VALUE}
              onFinish={handleSave}
              className="chat-type-management-page__editor-form"
            >
              <Form.Item name="id" hidden>
                <Input />
              </Form.Item>
              <div className="chat-type-management-page__editor-scroll">
                <Tabs
                  activeKey={activeDetailTab}
                  onChange={(key) => setActiveDetailTab(key as 'basic' | 'settings' | 'history')}
                  className="shared-resource-management-page__detail-tabs"
                  items={[
                    {
                      key: 'basic',
                      label: '기본 정보',
                      children: (
                        <div className="shared-resource-management-page__section-scroll">
                          <div className="shared-resource-management-page__compact-panel">
                            <div className="shared-resource-management-page__compact-panel-main">
                              <Text strong>{isCreating ? '신규 공유 토큰 준비' : detailData?.token.name ?? '공유 토큰 상세'}</Text>
                              <Text type="secondary">
                                {isCreating
                                  ? '필수 입력을 한 화면에서 빠르게 등록하고 저장 후 운영 이력을 확인합니다.'
                                  : detailData
                                    ? [
                                        RESOURCE_TYPE_OPTIONS.find((option) => option.value === detailData.token.resourceType)?.label ??
                                          detailData.token.resourceType,
                                        detailData.token.resourceLabel !== detailData.token.name ? detailData.token.resourceLabel : '',
                                      ]
                                        .filter(Boolean)
                                        .join(' · ')
                                    : '선택한 토큰의 기본 정보와 운영 상태를 바로 편집합니다.'}
                              </Text>
                            </div>
                            <div className="shared-resource-management-page__compact-panel-side">
                              {!isCreating && detailData ? (
                                <>
                                  <Tag color={resolveStatusMeta(detailData.token).color}>{resolveStatusMeta(detailData.token).label}</Tag>
                                  <Tag>{formatEffectiveExpirySummary(detailData.token, nowMs)}</Tag>
                                  <Tag>{`사용 ${formatUsage(detailData.token.usageCount)}`}</Tag>
                                </>
                              ) : (
                                <>
                                  <Tag color="blue">입력 중</Tag>
                                  <Tag>저장 전</Tag>
                                </>
                              )}
                            </div>
                          </div>
                          <div className="shared-resource-management-page__compact-grid">
                            <div className="shared-resource-management-page__field-span-2">
                              <Form.Item label="공유 이름" name="name" rules={[{ required: true, message: '공유 이름을 입력하세요.' }]}>
                                <Input placeholder="예: 외주 검수용 리소스 링크" />
                              </Form.Item>
                            </div>
                            <Form.Item label="리소스 유형" name="resourceType" rules={[{ required: true }]}>
                              <Select options={RESOURCE_TYPE_OPTIONS} />
                            </Form.Item>
                            <div className="shared-resource-management-page__field-span-3">
                              <Form.Item
                                label="리소스 경로 / URL"
                                name="resourcePath"
                                rules={[{ required: true, message: '리소스 경로를 입력하세요.' }]}
                              >
                                <Input placeholder="resource/Codex Live/... 또는 https://..." />
                              </Form.Item>
                            </div>
                            <div className="shared-resource-management-page__field-span-3">
                              <Form.Item label="설명" name="description">
                                <Input.TextArea rows={3} placeholder="공유 목적, 대상자, 제한 조건을 적어 두세요." />
                              </Form.Item>
                            </div>
                          </div>
                          <div className="shared-resource-management-page__inline-option-row">
                            <Form.Item label={null} name="enabled" valuePropName="checked" className="shared-resource-management-page__inline-option-item">
                              <Checkbox>공유 URL을 바로 사용할 수 있게 유지</Checkbox>
                            </Form.Item>
                            <Text type="secondary">비활성으로 저장하면 링크는 유지되지만 즉시 접근은 차단됩니다.</Text>
                          </div>
                          {!isCreating && detailData ? (
                            <div className="shared-resource-management-page__compact-grid shared-resource-management-page__compact-grid--summary">
                              <div className="shared-resource-management-page__detail-block shared-resource-management-page__field-span-2">
                                <Text strong>현재 상태</Text>
                                <div className="shared-resource-management-page__status-row" style={{ marginTop: 10 }}>
                                  <Tag color={resolveStatusMeta(detailData.token).color}>{resolveStatusMeta(detailData.token).label}</Tag>
                                  <Tag>{`토큰 ${formatTokenUsage(detailData.token.usageTokenTotal)}`}</Tag>
                                  <Tag>{`요청 ${detailData.token.usageRequestCount}건`}</Tag>
                                  <Tag>{`사용 ${formatUsage(detailData.token.usageCount)} · 활동 ${detailData.token.activityCount}건`}</Tag>
                                </div>
                                {detailData.token.sharePath ? (
                                  <Button
                                    type="link"
                                    icon={<QrcodeOutlined />}
                                    style={{ paddingInline: 0, marginTop: 12 }}
                                    onClick={() => setQrPreviewTokenId(detailData.token.id)}
                                  >
                                    QR 코드 보기
                                  </Button>
                                ) : null}
                                {detailConversationUrl ? (
                                  <Button
                                    type="link"
                                    icon={<LinkOutlined />}
                                    style={{ paddingInline: 0, marginTop: 4 }}
                                    onClick={() => openConversationDrawer(detailData.token.id, detailData.token.name, detailConversationUrl)}
                                  >
                                    채팅창 열기
                                  </Button>
                                ) : null}
                              </div>
                              <div className="shared-resource-management-page__detail-block">
                                <Text strong>운영 요약</Text>
                                <Paragraph style={{ marginTop: 10, marginBottom: 6 }}>{`생성 ${formatDateTime(detailData.token.createdAt)}`}</Paragraph>
                                <Paragraph style={{ marginBottom: 6 }}>
                                  {`최근 토큰 사용 ${formatDateTime(detailData.token.lastTokenUsedAt ?? detailData.token.lastUsedAt)}`}
                                </Paragraph>
                                <Paragraph style={{ marginBottom: 6 }}>{`완료 요청 ${detailData.token.usageCompletedRequestCount}건`}</Paragraph>
                                <Paragraph style={{ marginBottom: 0 }}>{formatEffectiveExpirySummary(detailData.token, nowMs)}</Paragraph>
                              </div>
                              {detailData.token.sharePath ? (
                                <div className="shared-resource-management-page__detail-block">
                                  <SharedResourceQrPanel shareUrl={buildAbsoluteShareUrl(detailData.token.sharePath)} />
                                </div>
                              ) : null}
                            </div>
                          ) : null}
                        </div>
                      ),
                    },
                    {
                      key: 'settings',
                      label: '설정',
                      children: (
                        <div className="shared-resource-management-page__section-scroll">
                          <div className="shared-resource-management-page__compact-grid">
                            {!isChatShareToken(detailData?.token ?? { resourceType: form.getFieldValue('resourceType') }) ? (
                              <Form.Item label="연결 토큰 설정 ID" name="tokenSettingId">
                                <Input placeholder="예: chat-share-default" />
                              </Form.Item>
                            ) : (
                              <div className="shared-resource-management-page__field-span-2">
                                <Alert
                                  showIcon
                                  type="info"
                                  message="공유 채팅 토큰은 발급 시점 스냅샷만 유지합니다."
                                  description="생성 이후에는 원본 토큰 설정과 다시 연결하지 않습니다."
                                />
                              </div>
                            )}
                            <Form.Item label="만료 시각" name="expiresAt">
                              <Input placeholder="2026-05-22T14:30:00+09:00" />
                            </Form.Item>
                            <Form.Item label="사용 한도" name="usageLimit" extra="0이면 무제한으로 유지합니다.">
                              <InputNumber
                                min={0}
                                style={{ width: '100%' }}
                                formatter={(value) => formatUnlimitedNumberInput(value, '회')}
                                parser={((value: string | undefined) => Number(parseUnlimitedNumberInput(value) || 0)) as unknown as (displayValue: string | undefined) => 0}
                              />
                            </Form.Item>
                            <div className="shared-resource-management-page__field-span-2">
                              <Form.Item label="공유 URL 경로" name="sharePath">
                                <Input placeholder="/share/resource/..." />
                              </Form.Item>
                            </div>
                            <div className="shared-resource-management-page__field-span-3">
                              <Form.Item label="공유 토큰 값" name="shareToken">
                                <Input placeholder="비워두면 자동 생성" />
                              </Form.Item>
                            </div>
                          </div>
                          <Form.Item
                            label={`앱 권한 ${APP_OPTIONS.length}`}
                            name="allowedAppIds"
                            extra="공유 토큰 상세에서 최종 허용 앱 목록을 직접 저장합니다."
                          >
                            <Checkbox.Group style={{ width: '100%' }}>
                              <div className="shared-resource-management-page__permission-grid">
                                {APP_OPTIONS.map((option) => (
                                  <label key={option.value} className="shared-resource-management-page__permission-card">
                                    <div className="shared-resource-management-page__permission-card-header">
                                      <div className="shared-resource-management-page__permission-card-copy">
                                        <Text strong>{option.label}</Text>
                                        <Text type="secondary">{option.description}</Text>
                                      </div>
                                      <Checkbox value={option.value} />
                                    </div>
                                    <Text type="secondary">{option.value}</Text>
                                  </label>
                                ))}
                              </div>
                            </Checkbox.Group>
                          </Form.Item>
                          <div className="shared-resource-management-page__inline-option-row">
                            <Button onClick={applyAdminPreset}>관리자 권한 바로 추가</Button>
                            <Text type="secondary">
                              채팅방 설정, 토큰/공유 리소스 관리 등 운영용 앱과 전체 관리 권한을 한 번에 채웁니다.
                            </Text>
                          </div>
                          <Form.Item
                            label="권한"
                            name="permissions"
                            rules={[{ required: true, message: '최소 1개 권한을 선택하세요.' }]}
                          >
                            <Checkbox.Group style={{ width: '100%' }}>
                              <div className="shared-resource-management-page__permission-grid">
                                {PERMISSION_OPTIONS.map((option) => (
                                  <label key={option.value} className="shared-resource-management-page__permission-card">
                                    <div className="shared-resource-management-page__permission-card-header">
                                      <div className="shared-resource-management-page__permission-card-copy">
                                        <Text strong>{option.label}</Text>
                                        <Text type="secondary">{option.description}</Text>
                                      </div>
                                      <Checkbox value={option.value} />
                                    </div>
                                  </label>
                                ))}
                              </div>
                            </Checkbox.Group>
                          </Form.Item>
                        </div>
                      ),
                    },
                    {
                      key: 'history',
                      label: '이력',
                      children: (
                        <div className="shared-resource-management-page__section-scroll">
                          {isCreating ? (
                            <Alert
                              showIcon
                              type="info"
                              message="신규 등록 전에는 이력과 운영 데이터를 표시하지 않습니다."
                              description="먼저 기본 정보와 설정을 저장하면 공유 URL, 사용량, 활동 내역을 이 탭에서 확인할 수 있습니다."
                            />
                          ) : detailData ? (
                            <>
                              <div className="shared-resource-management-page__compact-grid shared-resource-management-page__compact-grid--summary">
                                <div className="shared-resource-management-page__detail-block">
                                  <Text strong>운영 정보</Text>
                                  <Paragraph style={{ marginTop: 10, marginBottom: 6 }}>
                                    {isChatShareToken(detailData.token)
                                      ? `발급 스냅샷 ${detailData.token.tokenSettingSnapshot
                                        ? `${detailData.token.tokenSettingSnapshot.name} (${detailData.token.tokenSettingSnapshot.id})`
                                        : '없음'}`
                                      : `발급 기준 ${
                                        detailData.token.tokenSettingSnapshot
                                          ? `${detailData.token.tokenSettingSnapshot.name} (${detailData.token.tokenSettingSnapshot.id})`
                                          : detailData.token.tokenSettingId ?? '미연결'
                                      }`}
                                  </Paragraph>
                                  <Paragraph style={{ marginBottom: 6 }}>{`권한 기준 ${resolveLinkedSettingStatusMeta(detailData.token).label}`}</Paragraph>
                                  <Paragraph style={{ marginBottom: 0 }}>{`수정 ${formatDateTime(detailData.token.updatedAt)}`}</Paragraph>
                                </div>
                                <div className="shared-resource-management-page__detail-block shared-resource-management-page__field-span-2">
                                  <Text strong>권한 묶음</Text>
                                  <div className="shared-resource-management-page__detail-tags" style={{ marginTop: 10 }}>
                                    {detailData.token.permissions.map((permission) => (
                                      <Tag key={`${detailData.token.id}-${permission}`}>{formatPermissionLabel(permission)}</Tag>
                                    ))}
                                  </div>
                                  <Text strong style={{ display: 'block', marginTop: 12 }}>앱 권한</Text>
                                  <div className="shared-resource-management-page__detail-tags" style={{ marginTop: 10 }}>
                                    {detailData.token.allowedAppIds.length > 0 ? (
                                      detailData.token.allowedAppIds.map((appId) => (
                                        <Tag key={`${detailData.token.id}-${appId}`}>{formatAppLabel(appId)}</Tag>
                                      ))
                                    ) : (
                                      <Text type="secondary">허용 앱이 없습니다.</Text>
                                    )}
                                  </div>
                                </div>
                              </div>
                              <Card title="활동 내역" bordered={false} className="shared-resource-management-page__activity-card">
                                {isDetailLoading ? (
                                  <Paragraph>불러오는 중...</Paragraph>
                                ) : detailData.activities.length > 0 ? (
                                  <Table
                                    size="small"
                                    rowKey="id"
                                    columns={activityColumns}
                                    dataSource={detailData.activities}
                                    pagination={{ pageSize: 8, hideOnSinglePage: true }}
                                    scroll={{ x: 760 }}
                                  />
                                ) : (
                                  <Empty description="기록된 활동 내역이 없습니다." />
                                )}
                              </Card>
                            </>
                          ) : isDetailLoading ? (
                            <Paragraph>불러오는 중...</Paragraph>
                          ) : (
                            <Empty description="표시할 이력이 없습니다." />
                          )}
                        </div>
                      ),
                    },
                  ]}
                />
              </div>
            </Form>
          </div>
        </Card>
      )}
    </div>
  );
}
