import {
  CheckCircleFilled,
  ClockCircleFilled,
  CloseCircleFilled,
  CopyOutlined,
  ExclamationCircleFilled,
  ReloadOutlined,
  SyncOutlined,
} from '@ant-design/icons';
import { Alert, Button, Empty, Space, Tag, Typography, message } from 'antd';
import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react';
import { useTokenAccess } from '../../app/main/tokenAccess';
import { DataStatePanel } from '../../components/dataStatePanel';
import { copyText } from '../../app/main/mainChatPanel';
import {
  ServerCommandApiError,
  deployWorkServerCommand,
  deployTestServerCommand,
  fetchServerCommands,
  fetchServerRestartReservation,
  fetchTestServerDeploymentStatus,
  fetchWorkServerDeploymentStatus,
  restartServerCommand,
  scheduleServerRestartReservation,
} from './api';
import type {
  RestartReservationWorkloadSummary,
  ServerCommandItem,
  ServerCommandKey,
  ServerRestartReservation,
  ServerRestartReservationAutoFix,
  ServerRestartReservationExecutionPhase,
  ServerRestartReservationWorkItem,
  TestServerDeploymentPhase,
  TestServerDeploymentState,
  TestServerDeploymentStep,
  WorkServerDeploymentPhase,
  WorkServerDeploymentState,
  WorkServerDeploymentStep,
} from './types';
import './serverCommand.css';

const { Paragraph, Text, Title } = Typography;

type ServerCommandPageProps = {
  sharedAccess?: {
    shareToken: string;
    allowedKeys?: ServerCommandKey[];
  } | null;
};

type RestartErrorInfo = {
  tone: 'error' | 'warning';
  title: string;
  detail: string;
  missingScriptPath: string | null;
  canScheduleReservation: boolean;
};

type LastActionInfo = {
  output: string | null;
  executedAt: string;
  restartState: 'completed' | 'accepted';
};

type ServerActionKey = ServerCommandKey | 'test-deploy';

type SharedStatusTone =
  | 'online'
  | 'degraded'
  | 'offline'
  | 'latest'
  | 'update-available'
  | 'build-required'
  | 'unknown'
  | 'info';

type SharedStatusCard = {
  key: string;
  label: string;
  value: string;
  tone: SharedStatusTone;
  icon: ReactNode;
};

type ServerControlCard = {
  key: ServerActionKey;
  label: string;
  statusTone: SharedStatusTone;
  statusLabel: string;
  executedAt: string | null;
  updatedAt: string | null;
  progressLabel?: string | null;
  actionLabel: string;
  actionLoading: boolean;
  actionType: 'primary' | 'default';
  onAction: () => void;
};

const SHARED_SERVER_KEY_ORDER: ServerCommandKey[] = ['work-server', 'test', 'rel', 'prod', 'command-runner'];

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

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

function formatResponseTime(value: number | null | undefined) {
  if (typeof value !== 'number' || Number.isNaN(value)) {
    return '-';
  }

  return `${Math.max(0, Math.round(value))}ms`;
}

function formatStatusCode(value: number | null | undefined) {
  if (typeof value !== 'number' || Number.isNaN(value)) {
    return '-';
  }

  return `${value}`;
}

function resolveHostLabel(value: string | null | undefined) {
  if (!value) {
    return '내부 전용';
  }

  try {
    return new URL(value).host;
  } catch {
    return value;
  }
}

function resolveAvailabilityIcon(item: ServerCommandItem) {
  if (item.availability === 'online') {
    return <CheckCircleFilled />;
  }

  if (item.availability === 'degraded') {
    return <ExclamationCircleFilled />;
  }

  return <CloseCircleFilled />;
}

function resolveAvailabilityText(item: ServerCommandItem) {
  if (item.availability === 'online') {
    return '정상';
  }

  if (item.availability === 'degraded') {
    return '주의';
  }

  return '오프라인';
}

function resolveAvailabilityTone(item: ServerCommandItem) {
  if (item.availability === 'online') {
    return 'online';
  }

  if (item.availability === 'degraded') {
    return 'degraded';
  }

  return 'offline';
}

function resolveVersionTone(item: ServerCommandItem | null) {
  if (!item) {
    return 'unknown';
  }

  if (item.buildRequired) {
    return 'build-required';
  }

  if (item.updateAvailable) {
    return 'update-available';
  }

  return 'latest';
}

function resolveVersionStatusLabel(item: ServerCommandItem | null) {
  if (!item) {
    return '확인 필요';
  }

  if (item.buildRequired) {
    return '빌드 필요';
  }

  if (item.updateAvailable) {
    return '최신 반영 대기';
  }

  return '최신 실행 중';
}

function resolveWorkServerControlStatus(
  item: ServerCommandItem | null,
  deployment: WorkServerDeploymentState | null,
  isSubmitting: boolean,
): Pick<ServerControlCard, 'statusTone' | 'statusLabel'> {
  if (isSubmitting) {
    return {
      statusTone: 'online',
      statusLabel: '배포 요청 중',
    };
  }

  if (deployment?.status === 'running') {
    return {
      statusTone: 'online',
      statusLabel: '배포 진행 중',
    };
  }

  if (deployment?.status === 'failed') {
    return {
      statusTone: 'offline',
      statusLabel: '배포 실패',
    };
  }

  if (!item) {
    return {
      statusTone: 'unknown',
      statusLabel: '확인 필요',
    };
  }

  if (item.buildRequired) {
    return {
      statusTone: 'build-required',
      statusLabel: '빌드 필요',
    };
  }

  if (item.updateAvailable) {
    return {
      statusTone: 'update-available',
      statusLabel: '최신 반영 대기',
    };
  }

  if (item.availability === 'offline') {
    return {
      statusTone: 'offline',
      statusLabel: '응답 없음',
    };
  }

  if (item.availability === 'degraded') {
    return {
      statusTone: 'degraded',
      statusLabel: '상태 확인 필요',
    };
  }

  return {
    statusTone: 'online',
    statusLabel: '최신 실행 중',
  };
}

function resolveRestartButtonLabel() {
  return '재기동';
}

function resolveWorkServerDeploymentActionLabel() {
  return '배포';
}

function resolveServerDisplayLabel(item: ServerCommandItem) {
  if (item.key === 'test') {
    return 'PREVIEW';
  }

  if (item.key === 'work-server') {
    return 'WORK';
  }

  return item.label;
}

function resolvePrimaryActionLabel(item: ServerCommandItem) {
  if (item.key === 'test') {
    return 'PREVIEW 재기동';
  }

  if (item.key === 'work-server') {
    return 'WORK 재기동';
  }

  return resolveRestartButtonLabel();
}

function resolveAvailabilityShortLabel(item: ServerCommandItem) {
  if (item.availability === 'online') {
    return '정상';
  }

  if (item.availability === 'degraded') {
    return '주의';
  }

  return '장애';
}

function resolveReservationTone(status: ServerRestartReservation['status'] | 'idle'): SharedStatusTone {
  switch (status) {
    case 'ready':
    case 'executing':
    case 'recovering':
      return 'online';
    case 'waiting':
      return 'degraded';
    case 'failed':
      return 'offline';
    case 'completed':
      return 'latest';
    case 'cancelled':
      return 'unknown';
    default:
      return 'info';
  }
}

function resolveReservationStatusIcon(status: ServerRestartReservation['status'] | 'idle') {
  switch (status) {
    case 'ready':
      return <ClockCircleFilled />;
    case 'executing':
    case 'recovering':
      return <SyncOutlined spin />;
    case 'waiting':
      return <ClockCircleFilled />;
    case 'completed':
      return <CheckCircleFilled />;
    case 'failed':
      return <CloseCircleFilled />;
    case 'cancelled':
      return <ExclamationCircleFilled />;
    default:
      return <ClockCircleFilled />;
  }
}

function buildSharedReservationCard(reservation: ServerRestartReservation | null): SharedStatusCard {
  const isWorkTarget =
    reservation && (reservation.target === 'work-server' || reservation.target === 'all');
  const status = isWorkTarget ? reservation.status : 'idle';

  switch (status) {
    case 'waiting':
      return { key: 'reservation', label: '재기동 예약', value: '등록 대기', tone: resolveReservationTone(status), icon: resolveReservationStatusIcon(status) };
    case 'ready':
      return { key: 'reservation', label: '재기동 예약', value: '등록됨', tone: resolveReservationTone(status), icon: resolveReservationStatusIcon(status) };
    case 'executing':
      return { key: 'reservation', label: '재기동 예약', value: '실행 중', tone: resolveReservationTone(status), icon: resolveReservationStatusIcon(status) };
    case 'recovering':
      return { key: 'reservation', label: '재기동 예약', value: '자동 개선 중', tone: resolveReservationTone(status), icon: resolveReservationStatusIcon(status) };
    case 'completed':
      return { key: 'reservation', label: '재기동 예약', value: '최근 완료', tone: resolveReservationTone(status), icon: resolveReservationStatusIcon(status) };
    case 'failed':
      return { key: 'reservation', label: '재기동 예약', value: '실패', tone: resolveReservationTone(status), icon: resolveReservationStatusIcon(status) };
    case 'cancelled':
      return { key: 'reservation', label: '재기동 예약', value: '취소됨', tone: resolveReservationTone(status), icon: resolveReservationStatusIcon(status) };
    default:
      return { key: 'reservation', label: '재기동 예약', value: '미등록', tone: 'info', icon: <ClockCircleFilled /> };
  }
}

function buildRestartErrorInfo(targetLabel: string, detail: string): RestartErrorInfo {
  const missingScriptMatch = detail.match(/cannot open\s+([^\n:]+\.sh)\s*:\s*No such file/i);

  if (missingScriptMatch?.[1]) {
    const missingScriptPath = missingScriptMatch[1].trim();

    return {
      tone: 'error',
      title: `${targetLabel} 재기동 실패`,
      detail: `재기동 스크립트 파일이 서버에 없습니다.\n배치 경로: ${missingScriptPath}\n\n원본 오류:\n${detail}`,
      missingScriptPath,
      canScheduleReservation: false,
    };
  }

  return {
    tone: 'error',
    title: `${targetLabel} 재기동 실패`,
    detail,
    missingScriptPath: null,
    canScheduleReservation: false,
  };
}

function formatWorkloadSummary(summary: RestartReservationWorkloadSummary | null) {
  if (!summary) {
    return '진행 중 작업이 있어 즉시 재기동할 수 없습니다.';
  }

  return `Codex 실행 ${summary.codexRunningCount}건, Codex 대기 ${summary.codexQueuedCount}건, 자동화 실행 ${summary.automationRunningCount}건, 자동화 대기 ${summary.automationQueuedCount}건이 감지되었습니다.`;
}

function buildRestartReservationInfo(targetLabel: string, summary: RestartReservationWorkloadSummary | null, detail: string) {
  return {
    tone: 'warning' as const,
    title: `${targetLabel} 즉시 재기동 보류`,
    detail: `${detail}\n\n${formatWorkloadSummary(summary)}\n현재 화면에서는 전체 재기동 예약으로 이어서 처리할 수 있습니다.`,
    missingScriptPath: null,
    canScheduleReservation: true,
  };
}

function resolveReservationStatusTag(reservation: ServerRestartReservation) {
  switch (reservation.status) {
    case 'waiting':
      return <Tag color="gold">대기 중</Tag>;
    case 'ready':
      return <Tag color="blue">자동 실행 예정</Tag>;
    case 'executing':
      return <Tag color="processing">재기동 실행 중</Tag>;
    case 'recovering':
      return <Tag color="purple">Codex 자동 개선 중</Tag>;
    case 'completed':
      return <Tag color="success">완료</Tag>;
    case 'failed':
      return <Tag color="error">실패</Tag>;
    case 'cancelled':
      return <Tag>취소됨</Tag>;
    default:
      return <Tag>대기 없음</Tag>;
  }
}

function resolveWorkServerDeploymentPhaseLabel(phase: WorkServerDeploymentPhase) {
  switch (phase) {
    case 'build-target-slot':
      return '대기 슬롯 빌드';
    case 'verify-target-health':
      return '새 슬롯 health 확인';
    case 'switch-proxy':
      return '프록시 전환';
    case 'drain-previous-slot':
      return '이전 슬롯 이관';
    case 'rebuild-previous-slot':
      return '이전 슬롯 복구';
    case 'recover-interrupted-chat':
      return '중단 요청 복구 확인';
    case 'completed':
      return '배포 완료';
    case 'failed':
      return '배포 실패';
    default:
      return '대기';
  }
}

function resolveWorkServerDeploymentStatusTag(deployment: WorkServerDeploymentState) {
  switch (deployment.status) {
    case 'running':
      return <Tag color="processing">배포 진행 중</Tag>;
    case 'completed':
      return <Tag color="success">배포 완료</Tag>;
    case 'failed':
      return <Tag color="error">배포 실패</Tag>;
    default:
      return <Tag>대기</Tag>;
  }
}

function resolveWorkServerDeploymentStepLabel(step: WorkServerDeploymentStep) {
  return resolveWorkServerDeploymentPhaseLabel(step.key);
}

function resolveTestServerDeploymentPhaseLabel(phase: TestServerDeploymentPhase) {
  switch (phase) {
    case 'commit-main-worktree':
      return 'main 작업트리 커밋';
    case 'push-origin-main':
      return 'origin/main 푸시';
    case 'build-test-app':
      return '테스트 앱 빌드';
    case 'deploy-test-server':
      return '테스트 서버 배포';
    case 'completed':
      return '배포 완료';
    case 'failed':
      return '배포 실패';
    default:
      return '대기';
  }
}

function resolveTestServerDeploymentStatusTag(deployment: TestServerDeploymentState) {
  switch (deployment.status) {
    case 'running':
      return <Tag color="processing">배포 진행 중</Tag>;
    case 'completed':
      return <Tag color="success">배포 완료</Tag>;
    case 'failed':
      return <Tag color="error">배포 실패</Tag>;
    default:
      return <Tag>대기</Tag>;
  }
}

function resolveTestServerDeploymentStepLabel(step: TestServerDeploymentStep) {
  return resolveTestServerDeploymentPhaseLabel(step.key);
}

function resolveTestDeployControlStatus(
  item: ServerCommandItem | null,
  deployment: TestServerDeploymentState | null,
  isSubmitting: boolean,
): Pick<ServerControlCard, 'statusTone' | 'statusLabel'> {
  if (isSubmitting) {
    return {
      statusTone: 'online',
      statusLabel: '배포 요청 중',
    };
  }

  if (deployment?.status === 'running') {
    return {
      statusTone: 'online',
      statusLabel: '배포 진행 중',
    };
  }

  if (deployment?.status === 'failed') {
    return {
      statusTone: 'offline',
      statusLabel: '배포 실패',
    };
  }

  return {
    statusTone: resolveVersionTone(item),
    statusLabel: resolveVersionStatusLabel(item),
  };
}

function resolveWorkServerSlotLabel(slot: WorkServerDeploymentState['activeSlot']) {
  if (!slot) {
    return '-';
  }

  return slot.toUpperCase();
}

function getReservationTargetLabel(target: ServerRestartReservation['target']) {
  if (target === 'test') {
    return 'TEST 서버';
  }

  if (target === 'work-server') {
    return 'WORK 서버';
  }

  return 'TEST / WORK 서버';
}

function formatReservationWorkItemTag(item: ServerRestartReservationWorkItem) {
  if (item.kind === 'automation') {
    if (item.status === 'running') {
      return <Tag color="processing">자동화 실행</Tag>;
    }
    if (item.status === 'queued') {
      return <Tag color="blue">자동화 대기열</Tag>;
    }
    return <Tag color="gold">자동화 선행대기</Tag>;
  }

  if (item.status === 'running') {
    return <Tag color="processing">Codex 실행</Tag>;
  }
  if (item.status === 'queued') {
    return <Tag color="blue">Codex 대기열</Tag>;
  }
  return <Tag color="gold">Codex 대기</Tag>;
}

function resolveAutoFixTone(autoFix: ServerRestartReservationAutoFix) {
  if (autoFix.status === 'failed') {
    return 'error' as const;
  }

  if (autoFix.status === 'completed') {
    return 'success' as const;
  }

  return 'info' as const;
}

function formatAutoFixStatusLabel(status: ServerRestartReservationAutoFix['status']) {
  switch (status) {
    case 'queued':
      return '요청 대기';
    case 'running':
      return '개선 실행 중';
    case 'completed':
      return '개선 완료';
    case 'failed':
      return '개선 실패';
    default:
      return '대기 없음';
  }
}

function buildReservationExecutionSteps(
  phase: ServerRestartReservationExecutionPhase,
  target: ServerRestartReservation['target'],
) {
  const steps = [
    { label: 'main 작업트리 커밋', phaseKey: 'commit-main-worktree' },
    { label: 'TEST 재기동', phaseKey: 'restart-test' },
    { label: 'WORK 재기동', phaseKey: 'restart-work-server' },
    { label: '정상 기동 확인', phaseKey: 'verify-runtime' },
  ] as const;

  const filteredSteps = steps.filter((step) => {
    if (target === 'work-server' && step.label === 'TEST 재기동') {
      return false;
    }

    if (target === 'test' && step.label === 'WORK 재기동') {
      return false;
    }

    return true;
  });

  const activeIndex = filteredSteps.findIndex((step) => step.phaseKey === phase);

  return filteredSteps.map((step, index) => ({
    label: step.label,
    done: activeIndex > index,
    active: activeIndex === index,
  }));
}

function resolveToneTagColor(tone: SharedStatusTone) {
  if (tone === 'online' || tone === 'latest') {
    return 'blue';
  }

  if (tone === 'degraded' || tone === 'update-available') {
    return 'gold';
  }

  if (tone === 'offline' || tone === 'build-required') {
    return 'error';
  }

  return 'default';
}

function resolveServerNote(item: ServerCommandItem, lastAction: LastActionInfo | undefined) {
  if (item.errorMessage) {
    return item.errorMessage;
  }

  if (item.updateSummary) {
    return item.updateSummary;
  }

  if (item.composeDetails) {
    return item.composeDetails;
  }

  if (item.responsePreview) {
    return item.responsePreview;
  }

  if (lastAction?.executedAt) {
    return `${lastAction.restartState === 'accepted' ? '최근 요청' : '최근 완료'} ${formatDateTime(lastAction.executedAt)}`;
  }

  if (item.key === 'work-server') {
    return '빌드 성공 후 슬롯 전환';
  }

  if (item.key === 'test') {
    return '빌드 성공 후 preview 재기동';
  }

  return '-';
}

function resolveCardExecutedAt(item: ServerCommandItem | null, lastAction: LastActionInfo | undefined) {
  return lastAction?.executedAt || item?.startedAt || item?.checkedAt || null;
}

function resolveCardUpdatedAt(item: ServerCommandItem | null) {
  return item?.latestSourceChangeAt || item?.latestBuiltAt || item?.checkedAt || null;
}

export function ServerCommandPage({ sharedAccess = null }: ServerCommandPageProps) {
  const { hasAccess } = useTokenAccess();
  const isSharedManageMode = Boolean(sharedAccess?.shareToken);
  const allowedKeysKey = useMemo(
    () => (sharedAccess?.allowedKeys ?? []).join('|'),
    [sharedAccess?.allowedKeys],
  );
  const allowedKeysSet = useMemo(() => new Set(sharedAccess?.allowedKeys ?? []), [allowedKeysKey]);
  const [messageApi, contextHolder] = message.useMessage();
  const [items, setItems] = useState<ServerCommandItem[]>([]);
  const [loading, setLoading] = useState(true);
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
  const [reservation, setReservation] = useState<ServerRestartReservation | null>(null);
  const [workServerDeployment, setWorkServerDeployment] = useState<WorkServerDeploymentState | null>(null);
  const [testDeployment, setTestDeployment] = useState<TestServerDeploymentState | null>(null);
  const [runningActionKey, setRunningActionKey] = useState<ServerActionKey | null>(null);
  const [restartErrorInfo, setRestartErrorInfo] = useState<RestartErrorInfo | null>(null);
  const [copyingRestartError, setCopyingRestartError] = useState(false);
  const [schedulingReservation, setSchedulingReservation] = useState(false);
  const [lastActionByKey, setLastActionByKey] = useState<Record<ServerCommandKey, LastActionInfo>>({
    test: { output: null, executedAt: '', restartState: 'completed' },
    rel: { output: null, executedAt: '', restartState: 'completed' },
    prod: { output: null, executedAt: '', restartState: 'completed' },
    'work-server': { output: null, executedAt: '', restartState: 'completed' },
    'command-runner': { output: null, executedAt: '', restartState: 'completed' },
  });
  const workServerDeploymentNoticeKeyRef = useRef('');
  const testDeploymentNoticeKeyRef = useRef('');

  const loadItems = async (options?: { silent?: boolean }) => {
    if (!options?.silent) {
      setLoading(true);
      setErrorMessage(null);
    }

    try {
      const nextItems = await fetchServerCommands(isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined);
      setItems(
        isSharedManageMode && allowedKeysSet.size > 0
          ? nextItems.filter((item) => allowedKeysSet.has(item.key))
          : nextItems,
      );
    } catch (error) {
      if (!options?.silent) {
        setErrorMessage(error instanceof Error ? error.message : '서버 정보를 불러오지 못했습니다.');
      }
    } finally {
      if (!options?.silent) {
        setLoading(false);
      }
    }
  };

  const loadReservation = async (options?: { silent?: boolean }) => {
    try {
      const nextReservation = await fetchServerRestartReservation(isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined);
      setReservation(nextReservation);
      return nextReservation;
    } catch (error) {
      if (!options?.silent) {
        setErrorMessage(error instanceof Error ? error.message : '재기동 예약 상태를 불러오지 못했습니다.');
      }
      return null;
    }
  };

  const loadWorkServerDeployment = async (options?: { silent?: boolean }) => {
    try {
      const nextDeployment = await fetchWorkServerDeploymentStatus(
        isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
      );
      setWorkServerDeployment(nextDeployment);
      return nextDeployment;
    } catch (error) {
      if (!options?.silent) {
        setErrorMessage(error instanceof Error ? error.message : 'WORK 서버 배포 상태를 불러오지 못했습니다.');
      }
      return null;
    }
  };

  const loadTestDeployment = async (options?: { silent?: boolean }) => {
    try {
      const nextDeployment = await fetchTestServerDeploymentStatus(
        isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
      );
      setTestDeployment(nextDeployment);
      return nextDeployment;
    } catch (error) {
      if (!options?.silent) {
        setErrorMessage(error instanceof Error ? error.message : 'TEST 서버 배포 상태를 불러오지 못했습니다.');
      }
      return null;
    }
  };

  useEffect(() => {
    if (!hasAccess && !isSharedManageMode) {
      setItems([]);
      setLoading(false);
      setErrorMessage(null);
      setReservation(null);
      setWorkServerDeployment(null);
      setTestDeployment(null);
      return;
    }

    void Promise.all([loadItems(), loadReservation({ silent: true }), loadWorkServerDeployment({ silent: true }), loadTestDeployment({ silent: true })]);
  }, [allowedKeysKey, hasAccess, isSharedManageMode, sharedAccess?.shareToken]);

  useEffect(() => {
    if (!hasAccess && !isSharedManageMode) {
      return undefined;
    }

    const shouldTrackDeployment = runningActionKey === 'work-server'
      || runningActionKey === 'test-deploy'
      || workServerDeployment?.status === 'running'
      || testDeployment?.status === 'running';

    if (!shouldTrackDeployment) {
      return undefined;
    }

    let cancelled = false;

    const refresh = async () => {
      try {
        await Promise.all([
          loadItems({ silent: true }),
          loadReservation({ silent: true }),
          loadWorkServerDeployment({ silent: true }),
          loadTestDeployment({ silent: true }),
        ]);
      } catch {
        if (!cancelled) {
          // ignore polling errors and keep the latest visible state
        }
      }
    };

    void refresh();
    const intervalId = window.setInterval(() => {
      void refresh();
    }, 2000);

    return () => {
      cancelled = true;
      window.clearInterval(intervalId);
    };
  }, [hasAccess, isSharedManageMode, runningActionKey, sharedAccess?.shareToken, testDeployment?.status, workServerDeployment?.status]);

  useEffect(() => {
    if (!workServerDeployment || workServerDeployment.status === 'idle' || workServerDeployment.status === 'running') {
      return;
    }

    const noticeKey = `${workServerDeployment.status}:${workServerDeployment.completedAt ?? workServerDeployment.updatedAt ?? ''}`;
    if (workServerDeploymentNoticeKeyRef.current === noticeKey) {
      return;
    }
    workServerDeploymentNoticeKeyRef.current = noticeKey;

    if (runningActionKey === 'work-server') {
      setRunningActionKey(null);
    }

    if (workServerDeployment.status === 'completed') {
      void messageApi.success('WORK 서버 무중단 배포가 완료되었습니다.');
      return;
    }

    void messageApi.error('WORK 서버 배포가 실패했습니다.');
  }, [messageApi, runningActionKey, workServerDeployment]);

  useEffect(() => {
    if (!testDeployment || testDeployment.status === 'idle' || testDeployment.status === 'running') {
      return;
    }

    const noticeKey = `${testDeployment.status}:${testDeployment.completedAt ?? testDeployment.updatedAt ?? ''}`;
    if (testDeploymentNoticeKeyRef.current === noticeKey) {
      return;
    }
    testDeploymentNoticeKeyRef.current = noticeKey;

    if (runningActionKey === 'test-deploy') {
      setRunningActionKey(null);
    }

    if (testDeployment.status === 'completed') {
      setTestDeployment(null);
      void Promise.all([loadItems({ silent: true }), loadReservation({ silent: true })]);
      void messageApi.success('TEST 배포가 완료되었습니다.');
      return;
    }

    void messageApi.error('TEST 배포가 실패했습니다.');
  }, [messageApi, runningActionKey, testDeployment]);

  const visibleItems = useMemo(() => {
    const baseItems = isSharedManageMode
      ? [...items].sort((left, right) => {
          const leftIndex = SHARED_SERVER_KEY_ORDER.indexOf(left.key);
          const rightIndex = SHARED_SERVER_KEY_ORDER.indexOf(right.key);
          const normalizedLeft = leftIndex === -1 ? SHARED_SERVER_KEY_ORDER.length : leftIndex;
          const normalizedRight = rightIndex === -1 ? SHARED_SERVER_KEY_ORDER.length : rightIndex;
          return normalizedLeft - normalizedRight;
        })
      : items;

    return baseItems;
  }, [isSharedManageMode, items]);
  const manageableItems = useMemo(
    () => visibleItems.filter((item) => item.key === 'work-server' || item.key === 'test'),
    [visibleItems],
  );
  const workServerItem = manageableItems.find((item) => item.key === 'work-server') ?? null;
  const previewItem = manageableItems.find((item) => item.key === 'test') ?? null;
  const summary = useMemo(() => {
    return manageableItems.reduce(
      (result, item) => {
        result.total += 1;
        result[item.availability] += 1;
        return result;
      },
      { total: 0, online: 0, degraded: 0, offline: 0 },
    );
  }, [manageableItems]);

  const sharedReservationCard = useMemo(
    () => (isSharedManageMode ? buildSharedReservationCard(reservation) : null),
    [isSharedManageMode, reservation],
  );

  const hasDeploymentStatusPanel = Boolean(
    (testDeployment && (testDeployment.status === 'running' || testDeployment.status === 'failed'))
    || (workServerDeployment && (workServerDeployment.status === 'running' || workServerDeployment.status === 'failed'))
  );

  const handleRestart = async (key: ServerCommandKey) => {
    setRunningActionKey(key);
    setRestartErrorInfo(null);

    try {
      const result = await restartServerCommand(key, isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined);
      setItems((previous) => previous.map((item) => (item.key === result.item.key ? result.item : item)));
      void loadReservation({ silent: true });
      setLastActionByKey((previous) => ({
        ...previous,
        [result.item.key]: {
          output: result.commandOutput,
          executedAt: new Date().toISOString(),
          restartState: result.restartState,
        },
      }));
      void messageApi.open({
        type: result.restartState === 'accepted' ? 'info' : 'success',
        content:
          result.restartState === 'accepted'
            ? `${result.item.label} 재기동 요청이 접수되었습니다. 새 런타임 확인 전까지는 완료가 아닙니다.`
            : `${result.item.label} 재기동이 완료되었습니다.`,
      });
    } catch (error) {
      const targetLabel = items.find((item) => item.key === key)?.label ?? key.toUpperCase();
      if (error instanceof ServerCommandApiError && error.status === 409 && (key === 'test' || key === 'work-server')) {
        setRestartErrorInfo(buildRestartReservationInfo(targetLabel, error.workloadSummary, error.message));
        return;
      }

      const detail = error instanceof Error ? error.message : '서버 재기동에 실패했습니다.';
      setRestartErrorInfo(buildRestartErrorInfo(targetLabel, detail));
    } finally {
      setRunningActionKey(null);
    }
  };

  const handleDeployWorkServer = async () => {
    setRunningActionKey('work-server');
    setRestartErrorInfo(null);

    try {
      const result = await deployWorkServerCommand(isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined);
      setItems((previous) => previous.map((item) => (item.key === result.item.key ? result.item : item)));
      setWorkServerDeployment(result.deployment ?? result.item.deployment ?? null);
      void loadReservation({ silent: true });
      setLastActionByKey((previous) => ({
        ...previous,
        'work-server': {
          output: result.commandOutput,
          executedAt: new Date().toISOString(),
          restartState: result.restartState,
        },
      }));
      void messageApi.open({
        type: 'info',
        content: 'WORK 서버 무중단 배포를 시작했습니다. 빌드, 슬롯 전환, 이전 요청 이관 상태를 계속 확인합니다.',
      });
    } catch (error) {
      const detail = error instanceof Error ? error.message : 'WORK 서버 배포에 실패했습니다.';
      setRestartErrorInfo(buildRestartErrorInfo('WORK 서버 배포', detail));
      setRunningActionKey(null);
    }
  };

  const handleDeployTest = async () => {
    setRunningActionKey('test-deploy');
    setRestartErrorInfo(null);

    try {
      const result = await deployTestServerCommand(
        isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : undefined,
      );
      setTestDeployment(result.testDeployment ?? null);
      await Promise.all([loadItems(), loadReservation({ silent: true })]);
      setLastActionByKey((previous) => ({
        ...previous,
        test: {
          output: result.commandOutput,
          executedAt: new Date().toISOString(),
          restartState: result.restartState,
        },
      }));
      void messageApi.open({
        type: 'info',
        content: 'TEST 배포를 시작했습니다. origin/main 푸시, 테스트 빌드, 테스트 서버 배포 과정을 계속 확인합니다.',
      });
    } catch (error) {
      setRestartErrorInfo(
        buildRestartErrorInfo('TEST 반영', error instanceof Error ? error.message : 'TEST 반영에 실패했습니다.'),
      );
    } finally {
      setRunningActionKey(null);
    }
  };

  const handleCopyRestartError = async () => {
    if (!restartErrorInfo || copyingRestartError) {
      return;
    }

    setCopyingRestartError(true);

    try {
      await copyText(`${restartErrorInfo.title}\n${restartErrorInfo.detail}`);
      messageApi.success('에러 메시지를 복사했습니다.');
    } catch {
      messageApi.error('에러 메시지 복사에 실패했습니다.');
    } finally {
      setCopyingRestartError(false);
    }
  };

  const handleCopyDeploymentLog = async (title: string, detail: string | null | undefined) => {
    if (!detail?.trim()) {
      messageApi.error('복사할 배포 로그가 없습니다.');
      return;
    }

    try {
      await copyText(`${title}\n${detail}`);
      messageApi.success('배포 로그를 복사했습니다.');
    } catch {
      messageApi.error('배포 로그 복사에 실패했습니다.');
    }
  };

  const handleScheduleReservation = async () => {
    if (schedulingReservation) {
      return;
    }

    setSchedulingReservation(true);

    try {
      await scheduleServerRestartReservation(
        isSharedManageMode ? { target: 'work-server', shareToken: sharedAccess?.shareToken } : undefined,
      );
      setRestartErrorInfo(null);
      await loadReservation({ silent: true });
      messageApi.success(
        isSharedManageMode
          ? 'WORK 서버 재기동 예약을 등록했습니다. 진행 중 작업이 끝나면 자동으로 재기동합니다.'
          : '전체 재기동 예약을 등록했습니다. 진행 중 작업이 끝나면 자동으로 재기동합니다.',
      );
    } catch (error) {
      const detail = error instanceof Error ? error.message : '재기동 예약 등록에 실패했습니다.';
      setRestartErrorInfo(buildRestartErrorInfo('전체 서버', detail));
    } finally {
      setSchedulingReservation(false);
    }
  };

  const resolveControlCardProgressLabel = (key: ServerActionKey) => {
    if (key === 'test-deploy' && runningActionKey === 'test-deploy') {
      return 'TEST 배포 요청 중';
    }

    if (key === 'test-deploy' && testDeployment) {
      if (testDeployment.status === 'running') {
        return testDeployment.summary?.trim() || resolveTestServerDeploymentPhaseLabel(testDeployment.phase);
      }

      if (testDeployment.status === 'failed') {
        return '최근 배포 실패';
      }
    }

    if (key === 'test' && runningActionKey === 'test') {
      return 'TEST 재기동 요청 중';
    }

    if (key === 'work-server' && runningActionKey === 'work-server') {
      return 'WORK 배포 요청 중';
    }

    if (key === 'work-server' && workServerDeployment) {
      if (workServerDeployment.status === 'running') {
        return workServerDeployment.summary?.trim() || resolveWorkServerDeploymentPhaseLabel(workServerDeployment.phase);
      }

      if (workServerDeployment.status === 'failed') {
        return '최근 배포 실패';
      }
    }

    const matchesReservation = key === 'work-server'
      ? reservation && (reservation.target === 'work-server' || reservation.target === 'all')
      : (key === 'test' || key === 'test-deploy')
        ? reservation && (reservation.target === 'test' || reservation.target === 'all')
        : false;

    if (!matchesReservation) {
      return null;
    }

    if (reservation.status === 'recovering') {
      return reservation.autoFix.summary?.trim() || 'Codex 자동 개선 중';
    }

    if (reservation.status === 'executing') {
      if (reservation.executionPhase === 'commit-main-worktree') {
        return '재기동 실행 준비 중';
      }

      if (reservation.executionPhase === 'verify-runtime') {
        return '정상 기동 확인 중';
      }

      if (reservation.executionPhase === 'restart-work-server') {
        return 'WORK 배포 진행 중';
      }

      if (reservation.executionPhase === 'restart-test') {
        return 'TEST 재기동 진행 중';
      }

      return '재기동 진행 중';
    }

    if (reservation.status === 'ready') {
      return '자동 실행 대기 중';
    }

    if (reservation.status === 'waiting') {
      return '재기동 대기 중';
    }

    if (reservation.status === 'completed') {
      return '최근 재기동 완료';
    }

    if (reservation.status === 'failed') {
      return '최근 재기동 실패';
    }

    return null;
  };

  const controlCards = useMemo<ServerControlCard[]>(() => {
    const cards: ServerControlCard[] = [];
    const workServerControlStatus = resolveWorkServerControlStatus(
      workServerItem,
      workServerDeployment,
      runningActionKey === 'work-server',
    );
    const testDeployControlStatus = resolveTestDeployControlStatus(
      previewItem,
      testDeployment,
      runningActionKey === 'test-deploy',
    );

    if (workServerItem) {
      cards.push({
        key: 'work-server',
        label: 'Work서버 배포',
        statusTone: workServerControlStatus.statusTone,
        statusLabel: workServerControlStatus.statusLabel,
        executedAt: resolveCardExecutedAt(workServerItem, lastActionByKey['work-server']),
        updatedAt: resolveCardUpdatedAt(workServerItem),
        actionLabel: resolveWorkServerDeploymentActionLabel(),
        actionLoading: runningActionKey === 'work-server',
        progressLabel: resolveControlCardProgressLabel('work-server'),
        actionType: 'primary',
        onAction: () => {
          void handleDeployWorkServer();
        },
      });
    }

    if (previewItem) {
      cards.push({
        key: 'test',
        label: 'Preview재기동',
        statusTone: resolveVersionTone(previewItem),
        statusLabel: resolveVersionStatusLabel(previewItem),
        executedAt: resolveCardExecutedAt(previewItem, lastActionByKey.test),
        updatedAt: resolveCardUpdatedAt(previewItem),
        actionLabel: '재기동',
        actionLoading: runningActionKey === 'test',
        progressLabel: resolveControlCardProgressLabel('test'),
        actionType: 'default',
        onAction: () => {
          void handleRestart('test');
        },
      });

      cards.push({
        key: 'test-deploy',
        label: 'TEST배포',
        statusTone: testDeployControlStatus.statusTone,
        statusLabel: testDeployControlStatus.statusLabel,
        executedAt: lastActionByKey.test.executedAt || previewItem.latestBuiltAt || previewItem.checkedAt,
        updatedAt: resolveCardUpdatedAt(previewItem),
        actionLabel: '실행',
        actionLoading: runningActionKey === 'test-deploy',
        progressLabel: resolveControlCardProgressLabel('test-deploy'),
        actionType: 'default',
        onAction: () => {
          void handleDeployTest();
        },
      });
    }

    return cards;
    }, [isSharedManageMode, lastActionByKey, previewItem, reservation, runningActionKey, testDeployment, workServerDeployment, workServerItem]);

  if (!hasAccess && !isSharedManageMode) {
    return (
      <div className="server-command-page__surface">
        <Paragraph className="app-main-copy">
          토큰 등록 사용자 또는 허용된 공유채팅 참여자만 Server Command 메뉴를 사용할 수 있습니다.
        </Paragraph>
      </div>
    );
  }

  return (
    <Space direction="vertical" size={16} className="server-command-page">
      {contextHolder}

      <div className="server-command-page__surface server-command-page__surface--toolbar">
        <div className="server-command-page__toolbar">
          <div className="server-command-page__toolbar-copy">
            <Title level={4} className="server-command-page__title">
              서버관리
            </Title>
            <Paragraph className="server-command-page__copy">표로 확인하고 재기동</Paragraph>
          </div>
          <div className="server-command-page__toolbar-side">
            <div className="server-command-page__status-summary" aria-label="서버 상태 요약">
              <span className="server-command-page__status-summary-item" title={`전체 ${summary.total}대`}>
                <strong>{summary.total}</strong>
                <span>전체</span>
              </span>
              <span className="server-command-page__status-summary-item server-command-page__status-summary-item--online" title={`정상 ${summary.online}대`}>
                <CheckCircleFilled />
                <strong>{summary.online}</strong>
              </span>
              <span className="server-command-page__status-summary-item server-command-page__status-summary-item--degraded" title={`주의 ${summary.degraded}대`}>
                <ExclamationCircleFilled />
                <strong>{summary.degraded}</strong>
              </span>
              <span className="server-command-page__status-summary-item server-command-page__status-summary-item--offline" title={`장애 ${summary.offline}대`}>
                <CloseCircleFilled />
                <strong>{summary.offline}</strong>
              </span>
              {sharedReservationCard ? (
                <span
                  className={`server-command-page__status-summary-item server-command-page__status-summary-item--${sharedReservationCard.tone}`}
                  title={`재기동 예약 ${sharedReservationCard.value}`}
                >
                  {sharedReservationCard.icon}
                  <strong>{sharedReservationCard.value}</strong>
                </span>
              ) : null}
            </div>
            <Button
              icon={<ReloadOutlined />}
              onClick={() => {
                void Promise.all([
                  loadItems(),
                  loadReservation({ silent: true }),
                  loadWorkServerDeployment({ silent: true }),
                  loadTestDeployment({ silent: true }),
                ]);
              }}
              loading={loading}
            >
              새로고침
            </Button>
          </div>
        </div>
      </div>

      {restartErrorInfo && !hasDeploymentStatusPanel ? (
        <Alert
          showIcon
          type={restartErrorInfo.tone}
          message={restartErrorInfo.tone === 'warning' ? '재기동 예약 필요' : '재기동 에러'}
          description={
            <Space direction="vertical" size={8} className="server-command-page__alert-body">
              <Text strong>{restartErrorInfo.title}</Text>
              {restartErrorInfo.missingScriptPath ? (
                <Text code className="server-command-page__alert-code">
                  {restartErrorInfo.missingScriptPath}
                </Text>
              ) : null}
              <span className="server-command-page__alert-text">{restartErrorInfo.detail}</span>
            </Space>
          }
          action={
            <Space size={4}>
              {restartErrorInfo.canScheduleReservation ? (
                <Button size="small" type="primary" loading={schedulingReservation} onClick={() => void handleScheduleReservation()}>
                  재기동 예약
                </Button>
              ) : null}
              <Button
                type="text"
                size="small"
                icon={<CopyOutlined />}
                loading={copyingRestartError}
                aria-label="에러 메시지 복사"
                onClick={() => void handleCopyRestartError()}
              />
            </Space>
          }
        />
      ) : null}


      {testDeployment && (testDeployment.status === 'running' || testDeployment.status === 'failed') ? (
        <div className="server-command-page__surface server-command-page__reservation-panel">
          <Space direction="vertical" size={12} style={{ width: '100%' }}>
            <Space size={8} wrap>
              <Title level={5} className="server-command-page__server-title">
                TEST 배포 진행
              </Title>
              {resolveTestServerDeploymentStatusTag(testDeployment)}
            </Space>

            <Paragraph className="server-command-page__summary">
              {testDeployment.summary?.trim() || resolveTestServerDeploymentPhaseLabel(testDeployment.phase)}
            </Paragraph>

            <div className="server-command-page__compact-grid">
              <div className="server-command-page__compact-item">
                <Text type="secondary">시작</Text>
                <Text strong>{formatDateTime(testDeployment.startedAt)}</Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">마지막 갱신</Text>
                <Text strong>{formatDateTime(testDeployment.updatedAt)}</Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">완료</Text>
                <Text strong>{formatDateTime(testDeployment.completedAt)}</Text>
              </div>
            </div>

            <Space direction="vertical" size={8} className="server-command-page__work-list">
              <Text strong>실시간 배포 단계</Text>
              {testDeployment.steps.map((step) => (
                <div key={step.key} className="server-command-page__work-item">
                  <Space direction="vertical" size={4} style={{ width: '100%' }}>
                    <Space size={8} wrap>
                      <Tag color={step.status === 'running' ? 'processing' : step.status === 'completed' ? 'success' : step.status === 'failed' ? 'error' : 'default'}>
                        {step.status === 'running' ? '진행 중' : step.status === 'completed' ? '완료' : step.status === 'failed' ? '실패' : '대기'}
                      </Tag>
                      <Text strong={step.status === 'running' || step.status === 'completed'}>{resolveTestServerDeploymentStepLabel(step)}</Text>
                    </Space>
                    {step.detail ? (
                      <Text type="secondary" className="server-command-page__work-detail">
                        {step.detail}
                      </Text>
                    ) : null}
                    {step.updatedAt ? (
                      <Text type="secondary" className="server-command-page__work-detail">
                        갱신 {formatDateTime(step.updatedAt)}
                      </Text>
                    ) : null}
                  </Space>
                </div>
              ))}
            </Space>

            {testDeployment.logExcerpt ? (
              <div className="server-command-page__preview-block">
                <div className="server-command-page__preview-header">
                  <Text strong>배포 로그</Text>
                  <Button
                    type="text"
                    size="small"
                    icon={<CopyOutlined />}
                    aria-label="TEST 배포 로그 복사"
                    onClick={() => void handleCopyDeploymentLog('TEST 배포 로그', testDeployment.logExcerpt)}
                  >
                    복사
                  </Button>
                </div>
                <Text type={testDeployment.status === 'failed' ? 'danger' : undefined} className="server-command-page__preview">
                  {testDeployment.logExcerpt}
                </Text>
              </div>
            ) : null}
          </Space>
        </div>
      ) : null}
      {workServerDeployment && (workServerDeployment.status === 'running' || workServerDeployment.status === 'failed') ? (
        <div className="server-command-page__surface server-command-page__reservation-panel">
          <Space direction="vertical" size={12} style={{ width: '100%' }}>
            <Space size={8} wrap>
              <Title level={5} className="server-command-page__server-title">
                WORK 배포 진행
              </Title>
              {resolveWorkServerDeploymentStatusTag(workServerDeployment)}
            </Space>

            <Paragraph className="server-command-page__summary">
              {workServerDeployment.summary?.trim() || resolveWorkServerDeploymentPhaseLabel(workServerDeployment.phase)}
            </Paragraph>

            <div className="server-command-page__compact-grid">
              <div className="server-command-page__compact-item">
                <Text type="secondary">활성 슬롯</Text>
                <Text strong>{resolveWorkServerSlotLabel(workServerDeployment.activeSlot)}</Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">대상 슬롯</Text>
                <Text strong>{resolveWorkServerSlotLabel(workServerDeployment.targetSlot)}</Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">이전 슬롯</Text>
                <Text strong>{resolveWorkServerSlotLabel(workServerDeployment.previousSlot)}</Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">마지막 갱신</Text>
                <Text strong>{formatDateTime(workServerDeployment.updatedAt)}</Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">이관 대기</Text>
                <Text strong>
                  active {workServerDeployment.previousSlotActiveChatRequestCount ?? '-'} · queued {workServerDeployment.previousSlotQueuedChatRequestCount ?? '-'}
                </Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">복구 확인</Text>
                <Text strong>
                  session {workServerDeployment.recoveredSessionCount ?? '-'} · restarted {workServerDeployment.recoveredRestartedCount ?? '-'}
                </Text>
              </div>
            </div>

            <Space direction="vertical" size={8} className="server-command-page__work-list">
              <Text strong>실시간 배포 단계</Text>
              {workServerDeployment.steps.map((step) => (
                <div key={step.key} className="server-command-page__work-item">
                  <Space direction="vertical" size={4} style={{ width: '100%' }}>
                    <Space size={8} wrap>
                      <Tag color={step.status === 'running' ? 'processing' : step.status === 'completed' ? 'success' : step.status === 'failed' ? 'error' : 'default'}>
                        {step.status === 'running' ? '진행 중' : step.status === 'completed' ? '완료' : step.status === 'failed' ? '실패' : '대기'}
                      </Tag>
                      <Text strong={step.status === 'running' || step.status === 'completed'}>{resolveWorkServerDeploymentStepLabel(step)}</Text>
                    </Space>
                    {step.detail ? (
                      <Text type="secondary" className="server-command-page__work-detail">
                        {step.detail}
                      </Text>
                    ) : null}
                    {step.updatedAt ? (
                      <Text type="secondary" className="server-command-page__work-detail">
                        갱신 {formatDateTime(step.updatedAt)}
                      </Text>
                    ) : null}
                  </Space>
                </div>
              ))}
            </Space>

            {workServerDeployment.logExcerpt ? (
              <div className="server-command-page__preview-block">
                <div className="server-command-page__preview-header">
                  <Text strong>배포 로그</Text>
                  <Button
                    type="text"
                    size="small"
                    icon={<CopyOutlined />}
                    aria-label="WORK 배포 로그 복사"
                    onClick={() => void handleCopyDeploymentLog('WORK 배포 로그', workServerDeployment.logExcerpt)}
                  >
                    복사
                  </Button>
                </div>
                <Text type={workServerDeployment.status === 'failed' ? 'danger' : undefined} className="server-command-page__preview">
                  {workServerDeployment.logExcerpt}
                </Text>
              </div>
            ) : null}
          </Space>
        </div>
      ) : null}

      {reservation && !isSharedManageMode && (reservation.enabled || reservation.status !== 'idle' || reservation.autoFix.enabled) ? (
        <div className="server-command-page__surface server-command-page__reservation-panel">
          <Space direction="vertical" size={12} style={{ width: '100%' }}>
            <Space size={8} wrap>
              <Title level={5} className="server-command-page__server-title">
                재기동 예약 상태
              </Title>
              {resolveReservationStatusTag(reservation)}
            </Space>

            <Paragraph className="server-command-page__summary">
              {reservation.waitingReason?.trim()
                || (reservation.status === 'completed'
                  ? `예약된 ${getReservationTargetLabel(reservation.target)} 재기동이 완료되었습니다.`
                  : '예약 상태를 확인했습니다.')}
            </Paragraph>

            <div className="server-command-page__compact-grid">
              <div className="server-command-page__compact-item">
                <Text type="secondary">대상</Text>
                <Text strong>{getReservationTargetLabel(reservation.target)}</Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">요청</Text>
                <Text strong>{formatDateTime(reservation.requestedAt)}</Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">자동실행</Text>
                <Text strong>{formatDateTime(reservation.autoExecuteAt)}</Text>
              </div>
              <div className="server-command-page__compact-item">
                <Text type="secondary">갱신</Text>
                <Text strong>{formatDateTime(reservation.updatedAt)}</Text>
              </div>
            </div>

            {reservation.status === 'executing' ? (
              <Space direction="vertical" size={8} className="server-command-page__work-list">
                <Text strong>예약 실행 단계</Text>
                {buildReservationExecutionSteps(reservation.executionPhase, reservation.target).map((step) => (
                  <div key={step.label} className="server-command-page__work-item">
                    <Space size={8} wrap>
                      <Tag color={step.active ? 'processing' : step.done ? 'success' : 'default'}>
                        {step.active ? '진행 중' : step.done ? '완료' : '대기'}
                      </Tag>
                      <Text strong={step.active || step.done}>{step.label}</Text>
                    </Space>
                  </div>
                ))}
              </Space>
            ) : null}

            {reservation.workItems.length > 0 ? (
              <Space direction="vertical" size={8} className="server-command-page__work-list">
                <Text strong>현재 진행 작업</Text>
                {reservation.workItems.map((item, index) => (
                  <div key={`${item.kind}-${item.requestId ?? item.title}-${index}`} className="server-command-page__work-item">
                    <Space direction="vertical" size={4} style={{ width: '100%' }}>
                      <Space size={8} wrap>
                        {formatReservationWorkItemTag(item)}
                        <Text strong>{item.title}</Text>
                      </Space>
                      {item.detail ? (
                        <Text type="secondary" className="server-command-page__work-detail">
                          {item.detail}
                        </Text>
                      ) : null}
                    </Space>
                  </div>
                ))}
              </Space>
            ) : null}

            {reservation.autoFix.enabled ? (
              <Alert
                showIcon
                type={resolveAutoFixTone(reservation.autoFix)}
                message="Codex 자동 개선"
                description={
                  <Space direction="vertical" size={4} className="server-command-page__alert-body">
                    <Text strong>
                      {reservation.autoFix.summary?.trim() || '빌드 오류 자동 개선 상태를 추적 중입니다.'}
                    </Text>
                    {reservation.autoFix.detail ? <span className="server-command-page__alert-text">{reservation.autoFix.detail}</span> : null}
                    <Text type="secondary">
                      상태: {formatAutoFixStatusLabel(reservation.autoFix.status)}
                      {reservation.autoFix.targetKey ? ` · 대상 ${reservation.autoFix.targetKey.toUpperCase()}` : ''}
                    </Text>
                  </Space>
                }
              />
            ) : null}

            {reservation.lastError ? (
              <Text type="danger" className="server-command-page__preview">
                {reservation.lastError}
              </Text>
            ) : null}
          </Space>
        </div>
      ) : null}

      {loading ? (
        <DataStatePanel state="loading" title="서버 상태를 확인하는 중입니다." />
      ) : errorMessage ? (
        <DataStatePanel
          state="error"
          title="서버 명령 메뉴를 불러오지 못했습니다."
          description={errorMessage}
          actions={
            <Button type="primary" onClick={() => void Promise.all([loadItems(), loadReservation({ silent: true })])}>
              다시 시도
            </Button>
          }
        />
      ) : manageableItems.length === 0 ? (
        <div className="server-command-page__surface">
          <Empty description="표시할 서버가 없습니다." />
        </div>
      ) : (
        <div className="server-command-page__control-list" aria-label="서버 제어 목록">
          {controlCards.map((card) => (
            <div key={card.key} className="server-command-page__surface server-command-page__control-card">
              <div className="server-command-page__control-main">
                <div className="server-command-page__control-header">
                  <Text strong className="server-command-page__control-title">
                    {card.label}
                  </Text>
                  <span
                    className={`server-command-page__status-badge server-command-page__status-badge--${card.statusTone}`}
                    aria-label={`${card.label} 최신 상태 ${card.statusLabel}`}
                    title={`${card.label} 최신 상태 ${card.statusLabel}`}
                  >
                    {card.statusLabel}
                  </span>
                </div>
                <div className="server-command-page__control-meta">
                  <Text type="secondary">실행일</Text>
                  <Text>{formatDateTime(card.executedAt)}</Text>
                </div>
                <div className="server-command-page__control-meta">
                  <Text type="secondary">최근수정</Text>
                  <Text>{formatDateTime(card.updatedAt)}</Text>
                </div>
                {card.progressLabel ? (
                  <div className="server-command-page__control-meta">
                    <Text type="secondary">진행상태</Text>
                    <Text>{card.progressLabel}</Text>
                  </div>
                ) : null}
              </div>
              <Button
                className="server-command-page__restart-button server-command-page__control-button"
                type={card.actionType}
                icon={card.key === 'test-deploy' ? <SyncOutlined /> : <ReloadOutlined />}
                loading={card.actionLoading}
                onClick={card.onAction}
              >
                {card.actionLabel}
              </Button>
            </div>
          ))}
        </div>
      )}
    </Space>
  );
}
