/**
 * 항적조회 뷰어 컴포넌트
 *
 * 선박 모달 항적조회에서 사용
 * - 프로그레스 바 기반 시간 이동
 * - 선종 색상 기반 항적 레이어
 * - 포인트 호버 정보
 * - 가상 선박 아이콘
 */

import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { useTrackQueryStore } from '../stores/trackQueryStore';
import { useTrackQueryAnimationStore } from '../stores/trackQueryAnimationStore';
import {
  createPathLayers,
  createPointsLayerOnly,
  createDynamicTrackLayers,
  createLiveConnectionLayer,
  registerTrackQueryLayers,
  unregisterTrackQueryLayers,
  formatPointInfo,
  LAYER_IDS,
} from '../utils/trackQueryLayerUtils';
import { getShipKindName, getSignalSourceName } from '../types/trackQuery.types';
import { TRACK_QUERY_MAX_DAYS, TRACK_QUERY_DEFAULT_DAYS } from '../../types/constants';
import { showToast } from '../../components/common/Toast';
import { useTrackHighlight } from '../hooks/useTrackHighlight';
import { TrackQueryTimeline } from './TrackQueryTimeline';
import { useEquipmentFilter } from '../hooks/useEquipmentFilter';
import { shipBatchRenderer } from '../../map/ShipBatchRenderer';
import { fromLonLat } from 'ol/proj';

import ShipTooltip from '../../components/ship/ShipTooltip';
import './TrackQueryViewer.scss';

/** 일 단위를 밀리초로 변환 */
const DAYS_TO_MS = 24 * 60 * 60 * 1000;

/** datetime-local 입력용 포맷 */
function toDateTimeLocal(date) {
  const pad = (n) => String(n).padStart(2, '0');
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
}

/**
 * 유효한 선명인지 확인하고 포맷팅
 */
function formatShipName(name, fallback = '선명 없음') {
  if (!name) return fallback;
  const trimmed = name.trim();
  if (!trimmed) return fallback;
  if (trimmed === '-') return fallback;
  if (/^\d+$/.test(trimmed)) return fallback;
  return trimmed;
}

/**
 * 메모이제이션된 선박 목록 아이템
 */
const TrackQueryShipItem = React.memo(
  ({
    vesselId,
    shipName,
    targetId,
    shipKindCode,
    sigSrcCd,
    isEnabled,
    isActive,
    isHighlighted,
    speed,
    onToggle,
    onMouseEnter,
    onMouseLeave,
    onContextMenu,
  }) => (
    <div
      className={`ship-info-item ${isActive ? 'active' : ''} ${!isEnabled ? 'disabled' : ''} ${isHighlighted ? 'highlighted' : ''}`}
      onClick={() => onToggle(vesselId)}
      onMouseEnter={() => onMouseEnter(vesselId)}
      onMouseLeave={onMouseLeave}
      onContextMenu={e => onContextMenu(vesselId, e)}
      title={isEnabled ? '좌클릭: 비활성화 | 우클릭: 위치로 이동' : '좌클릭: 활성화 | 우클릭: 위치로 이동'}
    >
      <span className="ship-name">{formatShipName(shipName, targetId)}</span>
      <span className="ship-kind">{getShipKindName(shipKindCode)}</span>
      <span className="ship-signal">{getSignalSourceName(sigSrcCd)}</span>
      {speed !== null ? (
        <span className="ship-speed">{speed.toFixed(1)} kn</span>
      ) : (
        <span className="ship-status">{isEnabled ? '범위 외' : 'OFF'}</span>
      )}
    </div>
  ),
  (prev, next) =>
    prev.isActive === next.isActive &&
    prev.isEnabled === next.isEnabled &&
    prev.isHighlighted === next.isHighlighted &&
    prev.speed === next.speed,
);

/**
 * 항적조회 뷰어 메인 컴포넌트
 *
 * @param {Object} props
 * @param {boolean} [props.compact] 컴팩트 모드
 * @param {Function} [props.onClose] 닫기 핸들러
 * @param {boolean} [props.modalMode] 선박 모달 모드
 * @param {boolean} [props.isIntegrated] 통합선박 여부
 * @param {Object} [props.timeRange] 시간 범위 { fromDate, toDate }
 * @param {Function} [props.onTimeRangeChange] 시간 범위 변경 핸들러
 * @param {Function} [props.onQuery] 조회 버튼 클릭 핸들러
 * @param {boolean} [props.isQuerying] 조회 중 상태
 * @param {boolean} [props.showPlayback] 재생 컨트롤 표시 여부
 */
export const TrackQueryViewer = ({
  compact = false,
  onClose,
  modalMode = false,
  isIntegrated = false,
  timeRange,
  onTimeRangeChange,
  onQuery,
  isQuerying = false,
  showPlayback = false,
}) => {
  // 스토어 상태
  const tracks = useTrackQueryStore(state => state.tracks);
  const currentTime = useTrackQueryStore(state => state.currentTime);
  const dataStartTime = useTrackQueryStore(state => state.dataStartTime);
  const dataEndTime = useTrackQueryStore(state => state.dataEndTime);
  const storeError = useTrackQueryStore(state => state.error);
  const showPoints = useTrackQueryStore(state => state.showPoints);
  const showVirtualShip = useTrackQueryStore(state => state.showVirtualShip);
  const hideLiveShips = useTrackQueryStore(state => state.hideLiveShips);
  const showLabels = useTrackQueryStore(state => state.showLabels);
  const disabledVesselIds = useTrackQueryStore(state => state.disabledVesselIds);
  const setProgressByRatio = useTrackQueryStore(state => state.setProgressByRatio);
  const setShowPoints = useTrackQueryStore(state => state.setShowPoints);
  const setShowVirtualShip = useTrackQueryStore(state => state.setShowVirtualShip);
  const setHideLiveShips = useTrackQueryStore(state => state.setHideLiveShips);
  const setShowLabels = useTrackQueryStore(state => state.setShowLabels);
  const toggleVesselEnabled = useTrackQueryStore(state => state.toggleVesselEnabled);
  const getEnabledTracks = useTrackQueryStore(state => state.getEnabledTracks);
  const getCurrentPositions = useTrackQueryStore(state => state.getCurrentPositions);
  const getProgress = useTrackQueryStore(state => state.getProgress);

  // 포인트 호버 상태 (스토어에서 직접 구독)
  const storeHoveredPoint = useTrackQueryStore(state => state.hoveredPoint);
  const storeHoveredPointPosition = useTrackQueryStore(state => state.hoveredPointPosition);

  // 애니메이션 스토어 (구간반복 상태, 재생 상태)
  const isPlaying = useTrackQueryAnimationStore(state => state.isPlaying);
  const loop = useTrackQueryAnimationStore(state => state.loop);
  const loopStart = useTrackQueryAnimationStore(state => state.loopStart);
  const loopEnd = useTrackQueryAnimationStore(state => state.loopEnd);

  // 하이라이트 훅 (선박 목록 ↔ 지도 항적 양방향 연동)
  const { highlightedVesselId, handleListItemHover, handlePathHover, isHighlighted, clearHighlight } = useTrackHighlight();

  // 장비 필터 훅 (통합선박 modalMode 전용)
  const {
    equipments,
    enabledEquipments,
    toggleEquipment,
    enableAll,
    resetToDefault,
    hasMultipleEquipments,
  } = useEquipmentFilter(tracks);

  // 로컬 상태
  const [hoveredPoint, setHoveredPoint] = useState(null);
  const [hoveredShip, setHoveredShip] = useState(null);
  const [tooltipPosition, setTooltipPosition] = useState({ x: 0, y: 0 });
  const [shipTooltipPosition, setShipTooltipPosition] = useState({ x: 0, y: 0 });
  const [isDragging, setIsDragging] = useState(false);
  const [zoomLevel, setZoomLevel] = useState(undefined);
  const [staticLayerVersion, setStaticLayerVersion] = useState(0);
  const progressBarRef = useRef(null);
  const panelRef = useRef(null);
  const pathTriggerRef = useRef(0);
  const pointsTriggerRef = useRef(0);
  const dynamicTriggerRef = useRef(0);
  const pathLayersRef = useRef([]);
  const pointsLayerRef = useRef(null);
  const liveConnectionLayerRef = useRef(null);
  const liveConnectionTriggerRef = useRef(0);

  // 줌 레벨 변경 감지 (클러스터링용) - tracks 변경 시 재시도
  useEffect(() => {
    const mapInstance = window.__mainMap__;
    if (!mapInstance) return;

    const view = mapInstance.getView();
    if (!view) return;

    const initialZoom = view.getZoom();
    if (initialZoom !== undefined) {
      setZoomLevel(Math.floor(initialZoom));
    }

    const handleZoomChange = () => {
      const newZoom = view.getZoom();
      if (newZoom !== undefined) {
        const flooredZoom = Math.floor(newZoom);
        setZoomLevel(prev => (prev !== flooredZoom ? flooredZoom : prev));
      }
    };

    view.on('change:resolution', handleZoomChange);

    return () => {
      view.un('change:resolution', handleZoomChange);
    };
  }, [tracks.length]);

  // 컴포넌트 unmount 시 애니메이션 스토어 초기화
  useEffect(() => {
    return () => {
      useTrackQueryAnimationStore.getState().reset();
    };
  }, []);

  // 패널 드래그 상태
  const [isDraggingPanel, setIsDraggingPanel] = useState(false);
  const [dragDelta, setDragDelta] = useState({ x: 0, y: 0 });
  const dragStartRef = useRef({ x: 0, y: 0, deltaX: 0, deltaY: 0 });

  // 활성화된 항적만 가져오기
  const enabledTracks = useMemo(() => {
    const baseEnabledTracks = getEnabledTracks();
    if (modalMode && isIntegrated && hasMultipleEquipments) {
      return baseEnabledTracks.filter(track => enabledEquipments.has(track.sigSrcCd));
    }
    return baseEnabledTracks;
  }, [tracks, disabledVesselIds, getEnabledTracks, modalMode, isIntegrated, hasMultipleEquipments, enabledEquipments]);

  // 현재 위치 계산 (활성화된 선박만)
  const currentPositions = useMemo(() => {
    const allPositions = getCurrentPositions();
    if (modalMode && isIntegrated && hasMultipleEquipments) {
      const enabledVesselIds = new Set(enabledTracks.map(t => t.vesselId));
      return allPositions.filter(pos => enabledVesselIds.has(pos.vesselId));
    }
    return allPositions;
  }, [currentTime, tracks, disabledVesselIds, getCurrentPositions, modalMode, isIntegrated, hasMultipleEquipments, enabledTracks]);

  // 현재 시간에 활성 상태인 선박 ID Set
  const activeVesselIds = useMemo(() => {
    const active = new Set();
    tracks.forEach(track => {
      if (track.timestampsMs.length === 0) return;
      const firstTime = track.timestampsMs[0];
      const lastTime = track.timestampsMs[track.timestampsMs.length - 1];
      if (currentTime >= firstTime && currentTime <= lastTime) {
        active.add(track.vesselId);
      }
    });
    return active;
  }, [tracks, currentTime]);

  // 현재 시간의 선박 속도 Map
  const vesselSpeedMap = useMemo(() => {
    const speedMap = new Map();
    currentPositions.forEach(pos => {
      speedMap.set(pos.vesselId, pos.speed ?? null);
    });
    return speedMap;
  }, [currentPositions]);

  // 진행률 계산
  const progress = useMemo(() => {
    return getProgress();
  }, [currentTime, dataStartTime, dataEndTime, getProgress]);

  // 라이브 선박 토글 핸들러
  const handleToggleLiveShips = useCallback(() => {
    const newHideState = !hideLiveShips;
    setHideLiveShips(newHideState);
    shipBatchRenderer.immediateRender();
  }, [hideLiveShips, setHideLiveShips]);

  // 닫기 핸들러
  const handleClose = useCallback(() => {
    useTrackQueryAnimationStore.getState().reset();
    setHideLiveShips(false);
    if (onClose) {
      onClose();
    }
  }, [setHideLiveShips, onClose]);

  // 포인트 호버 핸들러
  const handlePointHover = useCallback((info, x, y) => {
    setHoveredPoint(info);
    setTooltipPosition({ x, y });
  }, []);

  // 가상 선박 아이콘 호버 핸들러
  const handleIconHover = useCallback((shipData, x, y) => {
    if (shipData) {
      // ShipTooltip 형식에 맞게 변환
      setHoveredShip({
        shipName: shipData.shipName,
        targetId: shipData.vesselId?.split('_').pop() || shipData.vesselId,
        signalKindCode: shipData.shipKindCode,
        sog: shipData.speed || 0,
        cog: shipData.heading || 0,
      });
      setShipTooltipPosition({ x, y });
      // 하이라이트도 설정
      handlePathHover(shipData.vesselId);
    } else {
      setHoveredShip(null);
      clearHighlight();
    }
  }, [handlePathHover, clearHighlight]);

  // 선박 목록 우클릭 핸들러 (해당 위치로 지도 중심 이동)
  const handleShipContextMenu = useCallback(
    (vesselId, e) => {
      e.preventDefault();

      const mapInstance = window.__mainMap__;
      if (!mapInstance) return;

      const track = tracks.find(t => t.vesselId === vesselId);
      if (!track || !track.geometry || track.geometry.length === 0) return;

      let targetLon;
      let targetLat;

      const currentPos = currentPositions.find(p => p.vesselId === vesselId);
      if (currentPos) {
        targetLon = currentPos.position[0];
        targetLat = currentPos.position[1];
      } else {
        if (!track.timestampsMs || track.timestampsMs.length === 0) return;
        const firstTime = track.timestampsMs[0];
        const lastTime = track.timestampsMs[track.timestampsMs.length - 1];

        if (currentTime < firstTime) {
          targetLon = track.geometry[0][0];
          targetLat = track.geometry[0][1];
        } else {
          const lastIdx = track.geometry.length - 1;
          targetLon = track.geometry[lastIdx][0];
          targetLat = track.geometry[lastIdx][1];
        }
      }

      const view = mapInstance.getView();
      view.animate({
        center: fromLonLat([targetLon, targetLat]),
        duration: 300,
      });
    },
    [tracks, currentPositions, currentTime],
  );

  // 포인트 레이어 업데이트 (클러스터링)
  useEffect(() => {
    if (tracks.length === 0 || !showPoints) {
      if (pointsLayerRef.current !== null) {
        pointsLayerRef.current = null;
        setStaticLayerVersion(v => v + 1);
      }
      return;
    }

    pointsTriggerRef.current += 1;

    const pointsLayer = createPointsLayerOnly(
      enabledTracks,
      {
        updateTrigger: pointsTriggerRef.current,
        zoomLevel,
      },
      handlePointHover,
    );

    pointsLayerRef.current = pointsLayer;
    setStaticLayerVersion(v => v + 1);
  }, [tracks, enabledTracks, showPoints, zoomLevel, handlePointHover]);

  // 경로 레이어 업데이트
  useEffect(() => {
    if (tracks.length === 0) {
      pathLayersRef.current = [];
      return;
    }

    pathTriggerRef.current += 1;

    const effectiveLoop = showPlayback && loop;

    const pathLayers = createPathLayers(
      enabledTracks,
      {
        updateTrigger: pathTriggerRef.current,
        highlightedVesselId,
        loop: effectiveLoop,
        loopStart: effectiveLoop ? loopStart : 0,
        loopEnd: effectiveLoop ? loopEnd : 0,
      },
      handlePathHover,
    );

    pathLayersRef.current = pathLayers;
    setStaticLayerVersion(v => v + 1);
  }, [tracks, enabledTracks, highlightedVesselId, loop, loopStart, loopEnd, showPlayback, handlePathHover]);

  // unmount 시에만 레이어 해제
  useEffect(() => {
    return () => {
      unregisterTrackQueryLayers();
      shipBatchRenderer.immediateRender();
    };
  }, []);

  // 라이브 연결선 업데이트 (항적 끝점 ↔ 라이브 선박 점선)
  // showPlayback 모드에서는 표시하지 않음
  useEffect(() => {
    if (tracks.length === 0 || showPlayback) {
      liveConnectionLayerRef.current = null;
      return;
    }

    // 초기 생성
    liveConnectionTriggerRef.current += 1;
    liveConnectionLayerRef.current = createLiveConnectionLayer(
      enabledTracks,
      liveConnectionTriggerRef.current,
    );

    // 1초 주기로 라이브 선박 위치 갱신
    const intervalId = setInterval(() => {
      liveConnectionTriggerRef.current += 1;
      const newLayer = createLiveConnectionLayer(
        enabledTracks,
        liveConnectionTriggerRef.current,
      );
      liveConnectionLayerRef.current = newLayer;

      // __trackQueryLayers__에서 라이브 연결선 레이어만 교체
      const currentLayers = window.__trackQueryLayers__ || [];
      const updatedLayers = currentLayers.filter(
        layer => layer?.id !== LAYER_IDS.LIVE_CONNECTION
      );
      if (newLayer) {
        updatedLayers.push(newLayer);
      }
      registerTrackQueryLayers(updatedLayers);
      shipBatchRenderer.immediateRender();
    }, 1000);

    return () => {
      clearInterval(intervalId);
      liveConnectionLayerRef.current = null;
    };
  }, [tracks, enabledTracks, showPlayback]);

  // 동적 레이어 업데이트 (가상 선박 아이콘, 라벨)
  useEffect(() => {
    if (tracks.length === 0) {
      unregisterTrackQueryLayers();
      shipBatchRenderer.immediateRender();
      return;
    }

    dynamicTriggerRef.current += 1;

    const dynamicLayers = createDynamicTrackLayers(
      currentPositions,
      enabledTracks,
      {
        showVirtualShip,
        showLabels,
        updateTrigger: dynamicTriggerRef.current,
      },
      handleIconHover,
    );

    const allLayers = [
      ...pathLayersRef.current,
      ...(pointsLayerRef.current ? [pointsLayerRef.current] : []),
      ...dynamicLayers,
      ...(liveConnectionLayerRef.current ? [liveConnectionLayerRef.current] : []),
    ];
    registerTrackQueryLayers(allLayers);

    // deck.gl 렌더링 트리거
    shipBatchRenderer.immediateRender();
  }, [tracks.length, enabledTracks, currentPositions, currentTime, isPlaying, showVirtualShip, showLabels, staticLayerVersion, handleIconHover]);

  // 프로그레스 바 드래그 핸들러
  const handleProgressMouseDown = useCallback((e) => {
    setIsDragging(true);
    updateProgressFromMouse(e);
  }, []);

  const handleProgressMouseMove = useCallback(
    (e) => {
      if (isDragging) {
        updateProgressFromMouse(e);
      }
    },
    [isDragging],
  );

  const handleProgressMouseUp = useCallback(() => {
    setIsDragging(false);
  }, []);

  const updateProgressFromMouse = useCallback(
    (e) => {
      if (!progressBarRef.current) return;

      const rect = progressBarRef.current.getBoundingClientRect();
      const x = e.clientX - rect.left;
      const ratio = Math.max(0, Math.min(1, x / rect.width));
      setProgressByRatio(ratio);
    },
    [setProgressByRatio],
  );

  // 프로그레스 바 마우스 이벤트 리스너
  useEffect(() => {
    if (isDragging) {
      window.addEventListener('mousemove', handleProgressMouseMove);
      window.addEventListener('mouseup', handleProgressMouseUp);
    }

    return () => {
      window.removeEventListener('mousemove', handleProgressMouseMove);
      window.removeEventListener('mouseup', handleProgressMouseUp);
    };
  }, [isDragging, handleProgressMouseMove, handleProgressMouseUp]);

  // 패널 드래그 핸들러
  const handlePanelDragStart = useCallback((e) => {
    if (e.target.closest('button')) return;

    e.preventDefault();
    dragStartRef.current = {
      x: e.clientX,
      y: e.clientY,
      deltaX: dragDelta.x,
      deltaY: dragDelta.y,
    };

    setIsDraggingPanel(true);
  }, [dragDelta]);

  // 패널 드래그 마우스 이벤트 리스너
  useEffect(() => {
    if (!isDraggingPanel) return;

    const handleMouseMove = (e) => {
      const newDeltaX = dragStartRef.current.deltaX + (e.clientX - dragStartRef.current.x);
      const newDeltaY = dragStartRef.current.deltaY + (e.clientY - dragStartRef.current.y);
      setDragDelta({ x: newDeltaX, y: newDeltaY });
    };

    const handleMouseUp = () => {
      setIsDraggingPanel(false);
    };

    window.addEventListener('mousemove', handleMouseMove);
    window.addEventListener('mouseup', handleMouseUp);

    return () => {
      window.removeEventListener('mousemove', handleMouseMove);
      window.removeEventListener('mouseup', handleMouseUp);
    };
  }, [isDraggingPanel]);

  // 시간 포맷팅
  const formatTime = useCallback((timestamp) => {
    if (!timestamp) return '--:--:--';
    const date = new Date(timestamp);
    return date.toLocaleTimeString('ko-KR', {
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit',
    });
  }, []);

  const formatDate = useCallback((timestamp) => {
    if (!timestamp) return '----.--.--';
    const date = new Date(timestamp);
    return date.toLocaleDateString('ko-KR', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
    });
  }, []);

  // 조회 기간 검증 및 자동 조정 (blur 시 실행)
  const validateAndAdjustTimeRange = useCallback((changedField) => {
    if (!timeRange || !onTimeRangeChange) return;

    const fromDate = new Date(timeRange.fromDate);
    const toDate = new Date(timeRange.toDate);

    // 유효하지 않은 날짜면 무시
    if (isNaN(fromDate.getTime()) || isNaN(toDate.getTime())) return;

    const diffDays = (toDate - fromDate) / DAYS_TO_MS;

    if (changedField === 'from') {
      // 시작일이 종료일보다 뒤인 경우 → 종료일을 시작일 + 기본조회기간으로 조정
      if (diffDays < 0) {
        const adjustedTo = new Date(fromDate.getTime() + TRACK_QUERY_DEFAULT_DAYS * DAYS_TO_MS);
        onTimeRangeChange({ ...timeRange, toDate: toDateTimeLocal(adjustedTo) });
        showToast(`종료일이 시작일보다 앞서 기본 조회기간 ${TRACK_QUERY_DEFAULT_DAYS}일로 자동 설정됩니다.`);
      }
      // 최대 조회기간 초과 시 종료일 자동 조정
      else if (diffDays > TRACK_QUERY_MAX_DAYS) {
        const adjustedTo = new Date(fromDate.getTime() + TRACK_QUERY_MAX_DAYS * DAYS_TO_MS);
        onTimeRangeChange({ ...timeRange, toDate: toDateTimeLocal(adjustedTo) });
        showToast(`최대 조회기간 ${TRACK_QUERY_MAX_DAYS}일로 자동 설정됩니다.`);
      }
    } else {
      // 종료일이 시작일보다 앞인 경우 → 시작일을 종료일 - 기본조회기간으로 조정
      if (diffDays < 0) {
        const adjustedFrom = new Date(toDate.getTime() - TRACK_QUERY_DEFAULT_DAYS * DAYS_TO_MS);
        onTimeRangeChange({ ...timeRange, fromDate: toDateTimeLocal(adjustedFrom) });
        showToast(`시작일이 종료일보다 뒤서 기본 조회기간 ${TRACK_QUERY_DEFAULT_DAYS}일로 자동 설정됩니다.`);
      }
      // 최대 조회기간 초과 시 시작일 자동 조정
      else if (diffDays > TRACK_QUERY_MAX_DAYS) {
        const adjustedFrom = new Date(toDate.getTime() - TRACK_QUERY_MAX_DAYS * DAYS_TO_MS);
        onTimeRangeChange({ ...timeRange, fromDate: toDateTimeLocal(adjustedFrom) });
        showToast(`최대 조회기간 ${TRACK_QUERY_MAX_DAYS}일로 자동 설정됩니다.`);
      }
    }
  }, [timeRange, onTimeRangeChange]);

  // 조회 버튼 클릭 핸들러 (검증 포함)
  const handleQueryClick = useCallback(() => {
    if (!timeRange || !onQuery) return;

    const fromDate = new Date(timeRange.fromDate);
    const toDate = new Date(timeRange.toDate);

    // 유효성 검사
    if (isNaN(fromDate.getTime()) || isNaN(toDate.getTime())) {
      showToast('올바른 날짜/시간을 입력해주세요.');
      return;
    }
    if (fromDate >= toDate) {
      showToast('종료 시간은 시작 시간보다 이후여야 합니다.');
      return;
    }

    onQuery();
  }, [timeRange, onQuery]);

  // 데이터가 없으면 렌더링하지 않음 (모달 모드에서는 시간 입력 폼을 위해 허용)
  if (tracks.length === 0 && !modalMode) {
    return null;
  }

  const hasTracks = tracks.length > 0;

  // 단일 선박이면 너비를 줄임
  const isSingleVessel = tracks.length === 1;
  const singleVessel = isSingleVessel ? tracks[0] : null;

  // 패널 스타일 (드래그 위치 적용)
  const panelStyle =
    dragDelta.x !== 0 || dragDelta.y !== 0
      ? {
          transform: `translateX(calc(-50% + ${dragDelta.x}px)) translateY(${dragDelta.y}px)`,
        }
      : {};

  return (
    <div
      ref={panelRef}
      className={`track-query-viewer ${compact ? 'compact' : ''} ${isSingleVessel ? 'single-vessel' : ''} ${modalMode ? 'modal-mode' : ''} ${isDraggingPanel ? 'dragging' : ''}`}
      style={panelStyle}
    >
      {/* 헤더 (선명, TargetId, 버튼) - 드래그 핸들 */}
      <div
        className="track-query-header draggable"
        onMouseDown={handlePanelDragStart}
      >
        <div className="header-info">
          {modalMode && hasTracks ? (
            <>
              <span className="vessel-name">{formatShipName(tracks[0]?.shipName)}</span>
              <span className="vessel-id">{tracks[0]?.targetId}</span>
              <span className="vessel-kind">{getShipKindName(tracks[0]?.shipKindCode)}</span>
            </>
          ) : modalMode && !hasTracks ? (
            <span className="vessel-count">항적조회</span>
          ) : singleVessel ? (
            <>
              <span className="vessel-name">{formatShipName(singleVessel.shipName)}</span>
              <span className="vessel-id">{singleVessel.targetId}</span>
              <span className="vessel-signal">{getSignalSourceName(singleVessel.sigSrcCd)}</span>
            </>
          ) : (
            <span className="vessel-count">항적조회 ({tracks.length}척)</span>
          )}
        </div>
        <div className="header-actions">
          <button
            type="button"
            className={`live-ship-toggle ${hideLiveShips ? 'off' : 'on'}`}
            onClick={handleToggleLiveShips}
            title={hideLiveShips ? '라이브 선박 표시' : '라이브 선박 숨김'}
          >
            {hideLiveShips ? '라이브 OFF' : '라이브 ON'}
          </button>
          {onClose && (
            <button
              type="button"
              className="close-btn"
              onClick={handleClose}
              title="항적조회 닫기"
            >
              ✕
            </button>
          )}
        </div>
      </div>

      {/* 프로그레스 바 섹션 (항적 데이터가 있을 때만) */}
      {hasTracks && (
        <div className="track-query-progress-section">
          {/* 기존 프로그레스 바 (showPlayback이 false일 때만 표시) */}
          {!showPlayback && (
            <>
              <div className="track-query-time-info">
                <span className="start-time">
                  {formatDate(dataStartTime)} {formatTime(dataStartTime)}
                </span>
                <span className="current-time">
                  {formatDate(currentTime)} {formatTime(currentTime)}
                </span>
                <span className="end-time">
                  {formatDate(dataEndTime)} {formatTime(dataEndTime)}
                </span>
              </div>

              <div
                ref={progressBarRef}
                className="track-query-progress-bar"
                onMouseDown={handleProgressMouseDown}
              >
                <div className="progress-track">
                  <div className="progress-fill" style={{ width: `${progress}%` }} />
                  <div
                    className="progress-handle"
                    style={{ left: `${progress}%` }}
                  />
                </div>
              </div>
            </>
          )}

          {/* 옵션 토글 */}
          <div className="track-query-options">
            <label className="option-toggle">
              <input
                type="checkbox"
                checked={showPoints}
                onChange={e => setShowPoints(e.target.checked)}
              />
              <span>포인트</span>
            </label>
            <label className="option-toggle">
              <input
                type="checkbox"
                checked={showVirtualShip}
                onChange={e => setShowVirtualShip(e.target.checked)}
              />
              <span>선박 아이콘</span>
            </label>
            {tracks.length > 1 && (
              <label className="option-toggle">
                <input
                  type="checkbox"
                  checked={showLabels}
                  onChange={e => setShowLabels(e.target.checked)}
                />
                <span>선명 표시</span>
              </label>
            )}
          </div>

          {/* 재생 컨트롤 (showPlayback이 true일 때만 표시) */}
          {showPlayback && dataStartTime > 0 && dataEndTime > dataStartTime && (
            <TrackQueryTimeline
              startTime={dataStartTime}
              endTime={dataEndTime}
              compact={compact}
            />
          )}
        </div>
      )}

      {/* 선박 모달 모드: 시간 입력 폼 */}
      {modalMode && timeRange && onTimeRangeChange && (
        <div className="track-query-time-form">
          <div className="time-form-row">
            <label htmlFor="track-from-date">조회 기간</label>
            <div className="time-inputs">
              <input
                type="datetime-local"
                id="track-from-date"
                value={timeRange.fromDate}
                onChange={e => onTimeRangeChange({ ...timeRange, fromDate: e.target.value })}
                onBlur={() => validateAndAdjustTimeRange('from')}
              />
              <span className="time-separator">~</span>
              <input
                type="datetime-local"
                id="track-to-date"
                value={timeRange.toDate}
                onChange={e => onTimeRangeChange({ ...timeRange, toDate: e.target.value })}
                onBlur={() => validateAndAdjustTimeRange('to')}
              />
            </div>
            <button
              type="button"
              className="query-btn"
              onClick={handleQueryClick}
              disabled={isQuerying}
            >
              {isQuerying ? '조회 중...' : '조회'}
            </button>
          </div>
        </div>
      )}

      {/* 모달 모드: 로딩/에러 상태 */}
      {modalMode && !hasTracks && (isQuerying || storeError) && (
        <div className="track-query-status">
          {isQuerying && <span className="status-loading">항적 데이터 조회 중...</span>}
          {!isQuerying && storeError && <span className="status-error">{storeError}</span>}
        </div>
      )}

      {/* 통합선박 장비 필터 (modalMode + 다중 장비) */}
      {modalMode && isIntegrated && hasMultipleEquipments && (
        <div className="track-query-equipment-filter">
          <span className="filter-title">장비별 항적</span>
          <div className="filter-actions">
            <button type="button" className="filter-action-btn" onClick={enableAll} title="모두 선택">
              전체
            </button>
            <button type="button" className="filter-action-btn" onClick={resetToDefault} title="기본값">
              기본
            </button>
          </div>
          <div className="equipment-filter-list">
            {equipments.map(eq => (
              <button
                key={eq.signalSourceCode}
                type="button"
                className={`equipment-toggle ${eq.isEnabled ? 'enabled' : 'disabled'}`}
                onClick={() => toggleEquipment(eq.signalSourceCode)}
                title={`${eq.name} (${eq.trackCount}건)`}
              >
                <span
                  className="equipment-badge"
                  style={{ backgroundColor: eq.isEnabled ? eq.background : '#999' }}
                >
                  {eq.key}
                </span>
              </button>
            ))}
          </div>
        </div>
      )}

      {/* 선박 목록 (우클릭 모드에서 2척 이상일 때만 표시) */}
      {!modalMode && tracks.length > 1 && (
        <div className="track-query-ship-info">
          {tracks.map(track => (
            <TrackQueryShipItem
              key={`${track.integrationTargetId || 'standalone'}_${track.vesselId}`}
              vesselId={track.vesselId}
              shipName={track.shipName}
              targetId={track.targetId}
              shipKindCode={track.shipKindCode}
              sigSrcCd={track.sigSrcCd}
              isEnabled={!disabledVesselIds.has(track.vesselId)}
              isActive={!disabledVesselIds.has(track.vesselId) && activeVesselIds.has(track.vesselId)}
              isHighlighted={isHighlighted(track.vesselId)}
              speed={vesselSpeedMap.get(track.vesselId) ?? null}
              onToggle={toggleVesselEnabled}
              onMouseEnter={handleListItemHover}
              onMouseLeave={clearHighlight}
              onContextMenu={handleShipContextMenu}
            />
          ))}
        </div>
      )}

      {/* 가상 선박 아이콘 호버 툴팁 */}
      {hoveredShip && createPortal(
        <ShipTooltip
          ship={hoveredShip}
          x={shipTooltipPosition.x}
          y={shipTooltipPosition.y}
        />,
        document.body
      )}

      {/* 포인트 호버 툴팁 */}
      {storeHoveredPoint && createPortal(
        <div
          className="track-query-tooltip"
          style={{
            left: storeHoveredPointPosition.x + 10,
            top: storeHoveredPointPosition.y - 10,
          }}
        >
          {(() => {
            const formatted = formatPointInfo(storeHoveredPoint);
            return (
              <>
                <div className="tooltip-row">
                  <span className="label">시간:</span>
                  <span className="value">{formatted.time}</span>
                </div>
                <div className="tooltip-row">
                  <span className="label">위치:</span>
                  <span className="value">{formatted.position}</span>
                </div>
                <div className="tooltip-row">
                  <span className="label">속도:</span>
                  <span className="value">{formatted.speed}</span>
                </div>
              </>
            );
          })()}
        </div>,
        document.body
      )}
    </div>
  );
};

export default TrackQueryViewer;
