import {
  CheckCircleFilled,
  ClockCircleFilled,
  CloseCircleFilled,
  CopyOutlined,
  ExclamationCircleFilled,
  ReloadOutlined,
  SyncOutlined,
} from '@ant-design/icons';
import { Alert, Button, Card, Col, Descriptions, Empty, Row, Space, Statistic, Tag, Typography, message } from 'antd';
import { useEffect, useMemo, useState, type ReactNode } from 'react';
import { useTokenAccess } from '../../app/main/tokenAccess';
import { DataStatePanel } from '../../components/dataStatePanel';
import { copyText } from '../../app/main/mainChatPanel';
import {
  ServerCommandApiError,
  fetchServerCommands,
  fetchServerRestartReservation,
  restartServerCommand,
  scheduleServerRestartReservation,
} from './api';
import type {
  RestartReservationWorkloadSummary,
  ServerCommandItem,
  ServerCommandKey,
  ServerRestartReservation,
  ServerRestartReservationAutoFix,
  ServerRestartReservationExecutionPhase,
  ServerRestartReservationWorkItem,
} 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 SharedStatusTone =
  | 'online'
  | 'degraded'
  | 'offline'
  | 'latest'
  | 'update-available'
  | 'build-required'
  | 'unknown'
  | 'info';

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

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 formatContentType(value: string | null | undefined) {
  return value?.trim() || '-';
}

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

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

function resolveAvailabilityTag(item: ServerCommandItem) {
  if (item.availability === 'online') {
    return <Tag color="success">ONLINE</Tag>;
  }

  if (item.availability === 'degraded') {
    return <Tag color="warning">DEGRADED</Tag>;
  }

  return <Tag color="error">OFFLINE</Tag>;
}

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 resolveVersionLabel(item: ServerCommandItem | null) {
  const latestVersion = item?.latestVersion?.trim();
  const runningVersion = item?.runningVersion?.trim();

  return latestVersion || runningVersion || '확인 필요';
}

function resolveRestartButtonLabel(item: ServerCommandItem) {
  return item.key === 'work-server' ? '예약' : '재기동';
}

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 resolveAvailabilityStatusIcon(tone: ReturnType<typeof resolveAvailabilityTone>) {
  if (tone === 'online') {
    return <CheckCircleFilled />;
  }

  if (tone === 'degraded') {
    return <ExclamationCircleFilled />;
  }

  return <CloseCircleFilled />;
}

function resolveVersionStatusIcon(tone: ReturnType<typeof resolveVersionTone>) {
  if (tone === 'latest') {
    return <CheckCircleFilled />;
  }

  if (tone === 'update-available') {
    return <ClockCircleFilled />;
  }

  if (tone === 'build-required') {
    return <ExclamationCircleFilled />;
  }

  return <ExclamationCircleFilled />;
}

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 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((label) => {
    if (target === 'work-server' && label.label === 'TEST 재기동') {
      return false;
    }

    if (target === 'test' && label.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,
  }));
}

export function ServerCommandPage({ sharedAccess = null }: ServerCommandPageProps) {
  const { hasAccess } = useTokenAccess();
  const isSharedManageMode = Boolean(sharedAccess?.shareToken);
  const allowedKeysSet = useMemo(() => new Set(sharedAccess?.allowedKeys ?? []), [sharedAccess?.allowedKeys]);
  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 [restartingKey, setRestartingKey] = useState<ServerCommandKey | 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 loadItems = async () => {
    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) {
      setErrorMessage(error instanceof Error ? error.message : '서버 정보를 불러오지 못했습니다.');
    } finally {
      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;
    }
  };

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

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

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

    const shouldPoll =
      reservation?.enabled
      || reservation?.status === 'recovering'
      || reservation?.autoFix.enabled
      || restartingKey === 'test'
      || restartingKey === 'work-server';

    if (!shouldPoll) {
      return;
    }

    const timerId = window.setInterval(() => {
      void loadReservation({ silent: true });
    }, 4000);

    return () => {
      window.clearInterval(timerId);
    };
  }, [hasAccess, isSharedManageMode, reservation, restartingKey]);

  const summary = useMemo(() => {
    return items.reduce(
      (result, item) => {
        result.total += 1;
        result[item.availability] += 1;
        return result;
      },
      { total: 0, online: 0, degraded: 0, offline: 0 },
    );
  }, [items]);
  const sharedReservationCard = useMemo(
    () => (isSharedManageMode ? buildSharedReservationCard(reservation) : null),
    [isSharedManageMode, reservation],
  );
  const sharedItems = useMemo(() => {
    if (!isSharedManageMode) {
      return [];
    }

    return [...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;
    });
  }, [isSharedManageMode, items]);

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

    try {
      if (key === 'work-server') {
        await scheduleServerRestartReservation({
          target: 'work-server',
          ...(isSharedManageMode ? { shareToken: sharedAccess?.shareToken } : {}),
        });
        await loadReservation({ silent: true });
        messageApi.success('WORK-SERVER 무중단 재기동 예약을 등록했습니다.');
        return;
      }

      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,
        },
      }));
      messageApi.success(
        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 {
      setRestartingKey(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 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);
    }
  };

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

  return (
    <Space direction="vertical" size={16} className="server-command-page">
      {contextHolder}
      <Card
        className={`server-command-page__card${isSharedManageMode ? ' server-command-page__card--shared' : ''}`}
        bordered={false}
      >
        <Space direction="vertical" size={8}>
          <Title level={4} className="server-command-page__title">
            {isSharedManageMode ? '서버관리' : 'Server Command'}
          </Title>
          {isSharedManageMode ? (
            <div className="server-command-page__shared-toolbar">
              <Space wrap size={[8, 8]} className="server-command-page__shared-toolbar-chips">
                <span className="server-command-page__toolbar-chip">
                  <span className="server-command-page__toolbar-chip-value">{summary.total}</span>
                  <span className="server-command-page__toolbar-chip-label">ALL</span>
                </span>
                <span className="server-command-page__toolbar-chip server-command-page__toolbar-chip--online">
                  <CheckCircleFilled />
                  <span className="server-command-page__toolbar-chip-value">{summary.online}</span>
                </span>
                <span className="server-command-page__toolbar-chip server-command-page__toolbar-chip--degraded">
                  <ExclamationCircleFilled />
                  <span className="server-command-page__toolbar-chip-value">{summary.degraded}</span>
                </span>
                <span className="server-command-page__toolbar-chip server-command-page__toolbar-chip--offline">
                  <CloseCircleFilled />
                  <span className="server-command-page__toolbar-chip-value">{summary.offline}</span>
                </span>
                {sharedReservationCard ? (
                  <span
                    className={`server-command-page__toolbar-chip server-command-page__toolbar-chip--${sharedReservationCard.tone}`}
                  >
                    {sharedReservationCard.icon}
                    <span className="server-command-page__toolbar-chip-value">{sharedReservationCard.value}</span>
                  </span>
                ) : null}
              </Space>
            </div>
          ) : (
            <>
              <Paragraph className="server-command-page__copy">
                TEST, REL, PROD, WORK-SERVER, COMMAND-RUNNER 상태를 확인하고 허용된 재기동 명령만 실행합니다.
              </Paragraph>
              <Row gutter={[12, 12]} className="server-command-page__summary-grid">
                <Col xs={12} md={6}>
                  <Statistic title="전체" value={summary.total} />
                </Col>
                <Col xs={12} md={6}>
                  <Statistic title="ONLINE" value={summary.online} valueStyle={{ color: '#389e0d' }} />
                </Col>
                <Col xs={12} md={6}>
                  <Statistic title="DEGRADED" value={summary.degraded} valueStyle={{ color: '#d48806' }} />
                </Col>
                <Col xs={12} md={6}>
                  <Statistic title="OFFLINE" value={summary.offline} valueStyle={{ color: '#cf1322' }} />
                </Col>
              </Row>
            </>
          )}
          <Space wrap>
            <Button
              icon={<ReloadOutlined />}
              onClick={() => {
                void Promise.all([
                  loadItems(),
                  loadReservation({ silent: true }),
                ]);
              }}
              loading={loading}
            >
              새로고침
            </Button>
          </Space>
        </Space>
      </Card>

      {restartErrorInfo ? (
        <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}

      {reservation && !isSharedManageMode && (reservation.enabled || reservation.status !== 'idle' || reservation.autoFix.enabled) ? (
        <Card className="server-command-page__card server-command-page__reservation-card" bordered={false}>
          <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>

            {(
              <Descriptions
                size="small"
                column={1}
                className="server-command-page__meta"
                items={[
                  {
                    key: 'target',
                    label: '대상',
                    children: getReservationTargetLabel(reservation.target),
                  },
                  {
                    key: 'requested-at',
                    label: '요청시각',
                    children: formatDateTime(reservation.requestedAt),
                  },
                  {
                    key: 'auto-execute-at',
                    label: '자동실행',
                    children: formatDateTime(reservation.autoExecuteAt),
                  },
                  {
                    key: 'updated-at',
                    label: '마지막 갱신',
                    children: formatDateTime(reservation.updatedAt),
                  },
                ]}
              />
            )}

            {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>
        </Card>
      ) : 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>
          }
        />
      ) : items.length === 0 ? (
        <Card className="server-command-page__card" bordered={false}>
          <Empty description="표시할 서버가 없습니다." />
        </Card>
      ) : isSharedManageMode ? (
        <div className="server-command-page__shared-server-grid">
          {sharedItems.map((item) => {
            const availabilityTone = resolveAvailabilityTone(item);
            const versionTone = resolveVersionTone(item);
            const lastAction = lastActionByKey[item.key];

            return (
              <Card
                key={item.key}
                className={`server-command-page__server-card server-command-page__server-card--shared server-command-page__server-card--shared-compact server-command-page__server-card--${availabilityTone}`}
                bordered={false}
              >
                <Space direction="vertical" size={12} style={{ width: '100%' }}>
                  <div className="server-command-page__shared-server-head">
                    <Space size={8} wrap className="server-command-page__title-row">
                      <span
                        className={`server-command-page__status-dot server-command-page__status-dot--${availabilityTone}`}
                        aria-hidden="true"
                      />
                      <Title level={5} className="server-command-page__server-title">
                        {item.label}
                      </Title>
                    </Space>
                    <Button
                      className="server-command-page__restart-button server-command-page__restart-button--shared-compact"
                      type={item.key === 'work-server' ? 'primary' : 'default'}
                      icon={<ReloadOutlined />}
                      loading={restartingKey === item.key}
                      onClick={() => {
                        void handleRestart(item.key);
                      }}
                    >
                      {resolveRestartButtonLabel(item)}
                    </Button>
                  </div>

                  <div className="server-command-page__shared-server-meta">
                    <span
                      className={`server-command-page__shared-pill server-command-page__shared-pill--${availabilityTone}`}
                      title={`상태 ${item.availability}`}
                    >
                      {resolveAvailabilityStatusIcon(availabilityTone)}
                    </span>
                    <span
                      className={`server-command-page__shared-pill server-command-page__shared-pill--${versionTone}`}
                      title={`버전 ${resolveVersionLabel(item)}`}
                    >
                      {resolveVersionStatusIcon(versionTone)}
                    </span>
                    {item.key === 'work-server' && sharedReservationCard ? (
                      <span
                        className={`server-command-page__shared-pill server-command-page__shared-pill--${sharedReservationCard.tone}`}
                        title={`예약 ${sharedReservationCard.value}`}
                      >
                        {sharedReservationCard.icon}
                      </span>
                    ) : null}
                    {item.composeStatus ? <span className="server-command-page__shared-pill">{item.composeStatus}</span> : null}
                  </div>

                  <div className="server-command-page__shared-server-stats">
                    <div className="server-command-page__shared-stat">
                      <Text type="secondary">MS</Text>
                      <Text strong>{formatResponseTime(item.responseTimeMs)}</Text>
                    </div>
                    <div className="server-command-page__shared-stat">
                      <Text type="secondary">HTTP</Text>
                      <Text strong>{formatStatusCode(item.httpStatus)}</Text>
                    </div>
                    <div className="server-command-page__shared-stat">
                      <Text type="secondary">확인</Text>
                      <Text strong>{formatDateTime(item.checkedAt)}</Text>
                    </div>
                  </div>

                  <Text type="secondary" className="server-command-page__shared-server-summary">
                    {resolveHostLabel(item.publicUrl ?? item.checkUrl)}
                  </Text>

                  {lastAction?.executedAt ? (
                    <Text type="secondary" className="server-command-page__shared-server-footer">
                      {lastAction.restartState === 'accepted' ? '요청' : '완료'} {formatDateTime(lastAction.executedAt)}
                    </Text>
                  ) : null}
                </Space>
              </Card>
            );
          })}
        </div>
      ) : (
        <div className="server-command-page__grid">
          {items.map((item) => (
            <Card
              key={item.key}
              className="server-command-page__server-card"
              bordered={false}
              title={
                <Space size={8} wrap className="server-command-page__title-row">
                  <Title level={5} className="server-command-page__server-title">
                    {item.label}
                  </Title>
                  {resolveAvailabilityTag(item)}
                  {item.composeStatus ? <Tag color="blue">{item.composeStatus}</Tag> : null}
                </Space>
              }
              extra={
                <Button
                  className="server-command-page__restart-button"
                  type="primary"
                  icon={<ReloadOutlined />}
                  loading={restartingKey === item.key}
                  onClick={() => {
                    void handleRestart(item.key);
                  }}
                >
                  {item.key === 'work-server' ? `${item.label} 무중단 예약` : `${item.label} 재기동`}
                </Button>
              }
            >
              <Space direction="vertical" size={14} style={{ width: '100%' }}>
                <Paragraph className="server-command-page__summary">{item.summary}</Paragraph>
                <Descriptions
                  size="small"
                  column={1}
                  className="server-command-page__meta"
                  items={[
                    {
                      key: 'environment',
                      label: '환경',
                      children: item.environment,
                    },
                    {
                      key: 'started-at',
                      label: '시작일시',
                      children: formatDateTime(item.startedAt),
                    },
                    {
                      key: 'response-time',
                      label: '응답시간',
                      children: formatResponseTime(item.responseTimeMs),
                    },
                    {
                      key: 'http-status',
                      label: 'HTTP',
                      children: formatStatusCode(item.httpStatus),
                    },
                    {
                      key: 'checked-at',
                      label: '확인시각',
                      children: formatDateTime(item.checkedAt),
                    },
                    {
                      key: 'latest-source-change-at',
                      label: '소스 수정일',
                      children: formatDateTime(item.latestSourceChangeAt),
                    },
                    {
                      key: 'latest-source-change-path',
                      label: '최근 소스 경로',
                      children: item.latestSourceChangePath?.trim() || '-',
                    },
                    {
                      key: 'latest-build-at',
                      label: '최신 빌드',
                      children: formatDateTime(item.latestBuiltAt),
                    },
                    {
                      key: 'content-type',
                      label: 'Content-Type',
                      children: formatContentType(item.contentType),
                    },
                    {
                      key: 'service',
                      label: '서비스',
                      children: item.serviceName,
                    },
                    {
                      key: 'compose-file',
                      label: 'Compose',
                      children: item.composeFile,
                    },
                    {
                      key: 'command-script',
                      label: 'Script',
                      children: item.commandScript,
                    },
                    {
                      key: 'working-directory',
                      label: '작업경로',
                      children: item.commandWorkingDirectory,
                    },
                    {
                      key: 'host',
                      label: '호스트',
                      children: resolveHostLabel(item.publicUrl ?? item.checkUrl),
                    },
                    {
                      key: 'public-url',
                      label: 'URL',
                      children: item.publicUrl ? (
                        <Typography.Link href={item.publicUrl} target="_blank" rel="noreferrer">
                          {item.publicUrl}
                        </Typography.Link>
                      ) : (
                        <Text type="secondary">내부 전용</Text>
                      ),
                    },
                    {
                      key: 'check-url',
                      label: '체크',
                      children: item.checkUrl,
                    },
                  ]}
                />

                {item.composeDetails ? (
                  <Text type="secondary" className="server-command-page__preview">
                    {item.composeDetails}
                  </Text>
                ) : null}

                {item.updateSummary ? (
                  <Text type="secondary" className="server-command-page__preview">
                    {item.updateSummary}
                  </Text>
                ) : null}

                {item.responsePreview ? (
                  <Text type="secondary" className="server-command-page__preview">
                    {item.responsePreview}
                  </Text>
                ) : null}

                {item.errorMessage ? (
                  <Text type="danger" className="server-command-page__preview">
                    {item.errorMessage}
                  </Text>
                ) : null}

                <Text code className="server-command-page__command">
                  {item.lastCommand}
                </Text>

                {lastActionByKey[item.key]?.executedAt ? (
                  <Text type="secondary" className="server-command-page__preview">
                    {lastActionByKey[item.key].restartState === 'accepted' ? '최근 재기동 요청' : '최근 재기동 완료'}:{' '}
                    {formatDateTime(lastActionByKey[item.key].executedAt)}
                  </Text>
                ) : null}

                {lastActionByKey[item.key]?.output ? (
                  <Text className="server-command-page__command">
                    {lastActionByKey[item.key].output}
                  </Text>
                ) : null}
              </Space>
            </Card>
          ))}
        </div>
      )}
    </Space>
  );
}
