import { useRef, useEffect, useState, useCallback, useMemo } from 'react';
import { FONT_MONO } from '../../styles/fonts';
import { useGearReplayStore } from '../../stores/gearReplayStore';
import { useLocalStorage } from '../../hooks/useLocalStorage';
import { MODEL_COLORS } from './fleetClusterConstants';
import type { HistoryFrame } from './fleetClusterTypes';
import type { GearCorrelationItem } from '../../services/vesselAnalysis';
import { useReplayCenterPanelLayout } from './useReplayCenterPanelLayout';

interface HistoryReplayControllerProps {
  onClose: () => void;
  hasRightReviewPanel?: boolean;
}

const MIN_AB_GAP_MS = 2 * 3600_000;
const BASE_PLAYBACK_SPEED = 0.5;
const SPEED_MULTIPLIERS = [1, 2, 5, 10] as const;

interface ReplayUiPrefs {
  showTrails: boolean;
  showLabels: boolean;
  focusMode: boolean;
  show1hPolygon: boolean;
  show6hPolygon: boolean;
  abLoop: boolean;
  speedMultiplier: 1 | 2 | 5 | 10;
}

const DEFAULT_REPLAY_UI_PREFS: ReplayUiPrefs = {
  showTrails: true,
  showLabels: true,
  focusMode: false,
  show1hPolygon: true,
  show6hPolygon: false,
  abLoop: false,
  speedMultiplier: 1,
};

// 멤버 정보 + 소속 모델 매핑
interface TooltipMember {
  mmsi: string;
  name: string;
  isGear: boolean;
  isParent: boolean;
  sources: { label: string; color: string }[]; // 소속 (1h, 6h, 모델명)
}

function buildTooltipMembers(
  frame1h: HistoryFrame | null,
  frame6h: HistoryFrame | null,
  correlationByModel: Map<string, GearCorrelationItem[]>,
  enabledModels: Set<string>,
  enabledVessels: Set<string>,
): TooltipMember[] {
  const map = new Map<string, TooltipMember>();

  const addSource = (mmsi: string, name: string, isGear: boolean, isParent: boolean, label: string, color: string) => {
    const existing = map.get(mmsi);
    if (existing) {
      existing.sources.push({ label, color });
    } else {
      map.set(mmsi, { mmsi, name, isGear, isParent, sources: [{ label, color }] });
    }
  };

  // 1h 멤버
  if (frame1h) {
    for (const m of frame1h.members) {
      const isGear = m.role === 'GEAR';
      addSource(m.mmsi, m.name || m.mmsi, isGear, m.isParent, '1h', '#fbbf24');
    }
  }

  // 6h 멤버
  if (frame6h) {
    for (const m of frame6h.members) {
      const isGear = m.role === 'GEAR';
      addSource(m.mmsi, m.name || m.mmsi, isGear, m.isParent, '6h', '#93c5fd');
    }
  }

  // 활성 모델의 일치율 대상
  for (const [modelName, items] of correlationByModel) {
    if (modelName === 'identity') continue;
    if (!enabledModels.has(modelName)) continue;
    const color = MODEL_COLORS[modelName] ?? '#94a3b8';
    for (const c of items) {
      if (!enabledVessels.has(c.targetMmsi)) continue;
      const isGear = c.targetType === 'GEAR_BUOY';
      addSource(c.targetMmsi, c.targetName || c.targetMmsi, isGear, false, modelName, color);
    }
  }

  return [...map.values()];
}

const HistoryReplayController = ({ onClose, hasRightReviewPanel = false }: HistoryReplayControllerProps) => {
  const isPlaying = useGearReplayStore(s => s.isPlaying);
  const snapshotRanges = useGearReplayStore(s => s.snapshotRanges);
  const snapshotRanges6h = useGearReplayStore(s => s.snapshotRanges6h);
  const historyFrames = useGearReplayStore(s => s.historyFrames);
  const historyFrames6h = useGearReplayStore(s => s.historyFrames6h);
  const frameCount = historyFrames.length;
  const frameCount6h = historyFrames6h.length;
  const dataStartTime = useGearReplayStore(s => s.dataStartTime);
  const dataEndTime = useGearReplayStore(s => s.dataEndTime);
  const playbackSpeed = useGearReplayStore(s => s.playbackSpeed);
  const showTrails = useGearReplayStore(s => s.showTrails);
  const showLabels = useGearReplayStore(s => s.showLabels);
  const focusMode = useGearReplayStore(s => s.focusMode);
  const show1hPolygon = useGearReplayStore(s => s.show1hPolygon);
  const show6hPolygon = useGearReplayStore(s => s.show6hPolygon);
  const abLoop = useGearReplayStore(s => s.abLoop);
  const abA = useGearReplayStore(s => s.abA);
  const abB = useGearReplayStore(s => s.abB);
  const correlationByModel = useGearReplayStore(s => s.correlationByModel);
  const enabledModels = useGearReplayStore(s => s.enabledModels);
  const enabledVessels = useGearReplayStore(s => s.enabledVessels);
  const hoveredMmsi = useGearReplayStore(s => s.hoveredMmsi);
  const has6hData = frameCount6h > 0;

  const [hoveredTooltip, setHoveredTooltip] = useState<{ pos: number; time: number; frame1h: HistoryFrame | null; frame6h: HistoryFrame | null } | null>(null);
  const [pinnedTooltip, setPinnedTooltip] = useState<{ pos: number; time: number; frame1h: HistoryFrame | null; frame6h: HistoryFrame | null } | null>(null);
  const [dragging, setDragging] = useState<'A' | 'B' | null>(null);
  const [replayUiPrefs, setReplayUiPrefs] = useLocalStorage<ReplayUiPrefs>('gearReplayUiPrefs', DEFAULT_REPLAY_UI_PREFS);
  const trackRef = useRef<HTMLDivElement>(null);
  const progressIndicatorRef = useRef<HTMLDivElement>(null);
  const timeDisplayRef = useRef<HTMLSpanElement>(null);

  const store = useGearReplayStore;
  const speedMultiplier = SPEED_MULTIPLIERS.includes(replayUiPrefs.speedMultiplier)
    ? replayUiPrefs.speedMultiplier
    : 1;

  // currentTime → 진행 인디케이터
  useEffect(() => {
    const unsub = store.subscribe(
      s => s.currentTime,
      (currentTime) => {
        const { startTime, endTime } = store.getState();
        if (endTime <= startTime) return;
        const progress = (currentTime - startTime) / (endTime - startTime);
        if (progressIndicatorRef.current) progressIndicatorRef.current.style.left = `${progress * 100}%`;
        if (timeDisplayRef.current) {
          timeDisplayRef.current.textContent = new Date(currentTime).toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit' });
        }
      },
    );
    return unsub;
  }, [store]);

  // 재생 시작 시 고정 툴팁 해제
  useEffect(() => {
    if (isPlaying) setPinnedTooltip(null);
  }, [isPlaying]);

  useEffect(() => {
    const replayStore = store.getState();
    replayStore.setShowTrails(replayUiPrefs.showTrails);
    replayStore.setShowLabels(replayUiPrefs.showLabels);
    replayStore.setFocusMode(replayUiPrefs.focusMode);
    replayStore.setShow1hPolygon(replayUiPrefs.show1hPolygon);
    replayStore.setShow6hPolygon(has6hData ? replayUiPrefs.show6hPolygon : false);
  }, [
    has6hData,
    replayUiPrefs.focusMode,
    replayUiPrefs.show1hPolygon,
    replayUiPrefs.show6hPolygon,
    replayUiPrefs.showLabels,
    replayUiPrefs.showTrails,
    store,
  ]);

  useEffect(() => {
    store.getState().setAbLoop(replayUiPrefs.abLoop);
  }, [dataEndTime, dataStartTime, replayUiPrefs.abLoop, store]);

  useEffect(() => {
    const nextSpeed = BASE_PLAYBACK_SPEED * speedMultiplier;
    if (Math.abs(playbackSpeed - nextSpeed) > 1e-9) {
      store.getState().setPlaybackSpeed(nextSpeed);
    }
  }, [playbackSpeed, speedMultiplier, store]);

  const posToProgress = useCallback((clientX: number) => {
    const rect = trackRef.current?.getBoundingClientRect();
    if (!rect) return 0;
    return Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));
  }, []);

  const progressToTime = useCallback((p: number) => {
    const { startTime, endTime } = store.getState();
    return startTime + p * (endTime - startTime);
  }, [store]);

  // 특정 시간에 가장 가까운 1h/6h 프레임 찾기
  const findClosestFrames = useCallback((t: number) => {
    const { startTime, endTime } = store.getState();
    const threshold = (endTime - startTime) * 0.01;
    let f1h: HistoryFrame | null = null;
    let f6h: HistoryFrame | null = null;
    let minD1h = Infinity;
    let minD6h = Infinity;

    for (const f of historyFrames) {
      const d = Math.abs(new Date(f.snapshotTime).getTime() - t);
      if (d < minD1h && d < threshold) { minD1h = d; f1h = f; }
    }
    for (const f of historyFrames6h) {
      const d = Math.abs(new Date(f.snapshotTime).getTime() - t);
      if (d < minD6h && d < threshold) { minD6h = d; f6h = f; }
    }
    return { f1h, f6h };
  }, [store, historyFrames, historyFrames6h]);

  // 트랙 클릭 → seek + 일시정지 + 툴팁 고정/갱신
  const handleTrackClick = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
    if (dragging) return;
    const progress = posToProgress(e.clientX);
    const t = progressToTime(progress);
    store.getState().pause();
    store.getState().seek(t);

    // 가까운 프레임이 있으면 툴팁 고정
    const { f1h, f6h } = findClosestFrames(t);
    if (f1h || f6h) {
      setPinnedTooltip({ pos: progress, time: t, frame1h: f1h, frame6h: f6h });
      const mmsis = new Set<string>();
      if (f1h) f1h.members.forEach(m => mmsis.add(m.mmsi));
      if (f6h) f6h.members.forEach(m => mmsis.add(m.mmsi));
      for (const [mn, items] of correlationByModel) {
        if (mn === 'identity' || !enabledModels.has(mn)) continue;
        for (const c of items) {
          if (enabledVessels.has(c.targetMmsi)) mmsis.add(c.targetMmsi);
        }
      }
      store.getState().setPinnedMmsis(mmsis);
    } else {
      setPinnedTooltip(null);
      store.getState().setPinnedMmsis(new Set());
    }
  }, [store, posToProgress, progressToTime, findClosestFrames, dragging, correlationByModel, enabledModels, enabledVessels]);

  // 호버 → 1h+6h 프레임 동시 검색
  const handleTrackHover = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
    if (dragging || pinnedTooltip) return;
    const progress = posToProgress(e.clientX);
    const t = progressToTime(progress);
    const { f1h, f6h } = findClosestFrames(t);
    if (f1h || f6h) {
      setHoveredTooltip({ pos: progress, time: t, frame1h: f1h, frame6h: f6h });
    } else {
      setHoveredTooltip(null);
    }
  }, [posToProgress, progressToTime, findClosestFrames, dragging, pinnedTooltip]);

  // A-B 드래그
  const handleAbDown = useCallback((marker: 'A' | 'B') => (e: React.MouseEvent) => {
    if (isPlaying) return;
    e.stopPropagation();
    setDragging(marker);
  }, [isPlaying]);

  useEffect(() => {
    if (!dragging) return;
    const handleMove = (e: MouseEvent) => {
      const t = progressToTime(posToProgress(e.clientX));
      const { startTime, endTime } = store.getState();
      const s = store.getState();
      if (dragging === 'A') {
        store.getState().setAbA(Math.max(startTime, Math.min(s.abB - MIN_AB_GAP_MS, t)));
      } else {
        store.getState().setAbB(Math.min(endTime, Math.max(s.abA + MIN_AB_GAP_MS, t)));
      }
    };
    const handleUp = () => setDragging(null);
    window.addEventListener('mousemove', handleMove);
    window.addEventListener('mouseup', handleUp);
    return () => { window.removeEventListener('mousemove', handleMove); window.removeEventListener('mouseup', handleUp); };
  }, [dragging, store, posToProgress, progressToTime]);

  const abAPos = useMemo(() => {
    if (!abLoop || abA <= 0) return -1;
    const { startTime, endTime } = store.getState();
    return endTime > startTime ? (abA - startTime) / (endTime - startTime) : -1;
  }, [abLoop, abA, store]);

  const abBPos = useMemo(() => {
    if (!abLoop || abB <= 0) return -1;
    const { startTime, endTime } = store.getState();
    return endTime > startTime ? (abB - startTime) / (endTime - startTime) : -1;
  }, [abLoop, abB, store]);

  // 고정 툴팁 멤버 빌드
  const pinnedMembers = useMemo(() => {
    if (!pinnedTooltip) return [];
    return buildTooltipMembers(pinnedTooltip.frame1h, pinnedTooltip.frame6h, correlationByModel, enabledModels, enabledVessels);
  }, [pinnedTooltip, correlationByModel, enabledModels, enabledVessels]);

  // 호버 리치 멤버 목록 (고정 툴팁과 동일 형식)
  const hoveredMembers = useMemo(() => {
    if (!hoveredTooltip) return [];
    return buildTooltipMembers(hoveredTooltip.frame1h, hoveredTooltip.frame6h, correlationByModel, enabledModels, enabledVessels);
  }, [hoveredTooltip, correlationByModel, enabledModels, enabledVessels]);

  // 닫기 핸들러 (고정 해제 포함)
  const handleClose = useCallback(() => {
    setPinnedTooltip(null);
    store.getState().setPinnedMmsis(new Set());
    onClose();
  }, [store, onClose]);

  const btnStyle: React.CSSProperties = {
    background: 'none', border: '1px solid rgba(99,179,237,0.3)', borderRadius: 4,
    color: '#e2e8f0', cursor: 'pointer', padding: '2px 6px', fontSize: 10, fontFamily: FONT_MONO,
  };
  const btnActiveStyle: React.CSSProperties = {
    ...btnStyle, background: 'rgba(99,179,237,0.15)', color: '#93c5fd',
  };
  const layout = useReplayCenterPanelLayout({
    minWidth: 266,
    maxWidth: 966,
    hasRightReviewPanel,
  });

  return (
    <div style={{
      position: 'absolute', bottom: 20,
      left: `${layout.left}px`,
      width: `${layout.width}px`,
      background: 'rgba(12,24,37,0.95)', border: '1px solid rgba(99,179,237,0.25)',
      borderRadius: 8, padding: '8px 14px', display: 'flex', flexDirection: 'column', gap: 4,
      zIndex: 50, fontFamily: FONT_MONO, fontSize: 10, color: '#e2e8f0',
      boxShadow: '0 4px 16px rgba(0,0,0,0.5)', pointerEvents: 'auto',
    }}>
      {/* 프로그레스 트랙 */}
      <div
        ref={trackRef}
        style={{ position: 'relative', height: 18, cursor: 'pointer' }}
        onClick={handleTrackClick}
        onMouseMove={handleTrackHover}
        onMouseLeave={() => { if (!pinnedTooltip) setHoveredTooltip(null); }}
      >
        <div style={{ position: 'absolute', left: 0, right: 0, top: 5, height: 8, background: 'rgba(255,255,255,0.05)', borderRadius: 4 }} />

        {/* A-B 구간 */}
        {abLoop && abAPos >= 0 && abBPos >= 0 && (
          <div style={{
            position: 'absolute', left: `${abAPos * 100}%`, top: 5,
            width: `${(abBPos - abAPos) * 100}%`, height: 8,
            background: 'rgba(34,197,94,0.12)', borderRadius: 4, pointerEvents: 'none',
          }} />
        )}

        {snapshotRanges6h.map((pos, i) => (
          <div key={`6h-${i}`} style={{ position: 'absolute', left: `${pos * 100}%`, top: 9, width: 2, height: 4, background: 'rgba(147,197,253,0.4)' }} />
        ))}
        {snapshotRanges.map((pos, i) => (
          <div key={`1h-${i}`} style={{ position: 'absolute', left: `${pos * 100}%`, top: 5, width: 2, height: 4, background: 'rgba(251,191,36,0.5)' }} />
        ))}

        {/* A-B 마커 */}
        {abLoop && abAPos >= 0 && (
          <div onMouseDown={handleAbDown('A')} style={{
            position: 'absolute', left: `${abAPos * 100}%`, top: 0, width: 8, height: 18,
            transform: 'translateX(-50%)', cursor: isPlaying ? 'default' : 'ew-resize', zIndex: 5,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <div style={{ width: 2, height: 16, background: 'rgba(34,197,94,0.8)', borderRadius: 1 }} />
            <span style={{ position: 'absolute', top: -14, fontSize: 10, color: '#22c55e', fontWeight: 700, pointerEvents: 'none', background: 'rgba(0,0,0,0.7)', borderRadius: 2, padding: '0 3px', lineHeight: '14px' }}>A</span>
          </div>
        )}
        {abLoop && abBPos >= 0 && (
          <div onMouseDown={handleAbDown('B')} style={{
            position: 'absolute', left: `${abBPos * 100}%`, top: 0, width: 8, height: 18,
            transform: 'translateX(-50%)', cursor: isPlaying ? 'default' : 'ew-resize', zIndex: 5,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}>
            <div style={{ width: 2, height: 16, background: 'rgba(34,197,94,0.8)', borderRadius: 1 }} />
            <span style={{ position: 'absolute', top: -14, fontSize: 10, color: '#22c55e', fontWeight: 700, pointerEvents: 'none', background: 'rgba(0,0,0,0.7)', borderRadius: 2, padding: '0 3px', lineHeight: '14px' }}>B</span>
          </div>
        )}

        {/* 호버 하이라이트 */}
        {hoveredTooltip && !pinnedTooltip && (
          <div style={{
            position: 'absolute', left: `${hoveredTooltip.pos * 100}%`, top: 3, width: 4, height: 12,
            background: 'rgba(255,255,255,0.6)',
            borderRadius: 1, transform: 'translateX(-50%)', pointerEvents: 'none',
          }} />
        )}

        {/* 고정 마커 */}
        {pinnedTooltip && (
          <div style={{
            position: 'absolute', left: `${pinnedTooltip.pos * 100}%`, top: 1, width: 5, height: 16,
            background: 'rgba(255,255,255,0.9)', borderRadius: 1, transform: 'translateX(-50%)', pointerEvents: 'none',
          }} />
        )}

        {/* 진행 인디케이터 */}
        <div ref={progressIndicatorRef} style={{
          position: 'absolute', left: '0%', top: 3, width: 3, height: 12,
          background: '#fbbf24', borderRadius: 1, transform: 'translateX(-50%)', pointerEvents: 'none',
        }} />

        {/* 호버 리치 툴팁 (고정 아닌 상태) */}
        {hoveredTooltip && !pinnedTooltip && hoveredMembers.length > 0 && (
          <div style={{
            position: 'absolute',
            left: `${Math.min(hoveredTooltip.pos * 100, 85)}%`,
            top: -8, transform: 'translateY(-100%)',
            background: 'rgba(10,20,32,0.95)', border: '1px solid rgba(99,179,237,0.3)',
            borderRadius: 6, padding: '5px 7px', maxWidth: 300, maxHeight: 160, overflowY: 'auto',
            fontSize: 9, zIndex: 30, pointerEvents: 'none',
          }}>
            <div style={{ color: '#fbbf24', fontWeight: 600, marginBottom: 3 }}>
              {new Date(hoveredTooltip.time).toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit', second: '2-digit' })}
            </div>
            {hoveredMembers.map(m => (
              <div key={m.mmsi} style={{ display: 'flex', alignItems: 'center', gap: 4, padding: '1px 0' }}>
                <span style={{ color: m.isGear ? '#94a3b8' : '#fbbf24', fontSize: 8, width: 16, flexShrink: 0 }}>
                  {m.isGear ? '◇' : '△'}{m.isParent ? '★' : ''}
                </span>
                <span style={{ color: '#e2e8f0', flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                  {m.name}
                </span>
                <div style={{ display: 'flex', gap: 2, flexShrink: 0 }}>
                  {m.sources.map((s, si) => (
                    <span key={si} style={{
                      display: 'inline-block', width: s.label === '1h' || s.label === '6h' ? 'auto' : 6,
                      height: 6, borderRadius: s.label === '1h' || s.label === '6h' ? 2 : '50%',
                      background: s.color, fontSize: 7, color: '#000', fontWeight: 700,
                      padding: s.label === '1h' || s.label === '6h' ? '0 2px' : 0,
                      lineHeight: '6px', textAlign: 'center',
                    }}>
                      {(s.label === '1h' || s.label === '6h') ? s.label : ''}
                    </span>
                  ))}
                </div>
              </div>
            ))}
          </div>
        )}

        {/* 고정 리치 툴팁 */}
        {pinnedTooltip && pinnedMembers.length > 0 && (
          <div
            onClick={e => e.stopPropagation()}
            style={{
              position: 'absolute',
              left: `${Math.min(pinnedTooltip.pos * 100, 85)}%`,
              top: -8,
              transform: 'translateY(-100%)',
              background: 'rgba(10,20,32,0.97)', border: '1px solid rgba(99,179,237,0.4)',
              borderRadius: 6, padding: '6px 8px', maxWidth: 320, maxHeight: 200, overflowY: 'auto',
              fontSize: 9, zIndex: 40, pointerEvents: 'auto',
            }}>
            {/* 헤더 */}
            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 4 }}>
              <span style={{ color: '#fbbf24', fontWeight: 600 }}>
                {new Date(pinnedTooltip.time).toLocaleTimeString('ko-KR', { hour: '2-digit', minute: '2-digit', second: '2-digit' })}
              </span>
              <button type="button" onClick={(e) => { e.stopPropagation(); setPinnedTooltip(null); store.getState().setPinnedMmsis(new Set()); }}
                style={{ background: 'none', border: 'none', color: '#64748b', cursor: 'pointer', fontSize: 10, padding: 0 }}>
                ✕
              </button>
            </div>

            {/* 멤버 목록 (호버 → 지도 강조) */}
            {pinnedMembers.map(m => (
              <div
                key={m.mmsi}
                onMouseEnter={() => store.getState().setHoveredMmsi(m.mmsi)}
                onMouseLeave={() => store.getState().setHoveredMmsi(null)}
                style={{
                  display: 'flex', alignItems: 'center', gap: 4, padding: '2px 3px',
                  borderBottom: '1px solid rgba(255,255,255,0.04)', cursor: 'pointer',
                  borderRadius: 2,
                  background: hoveredMmsi === m.mmsi ? 'rgba(255,255,255,0.08)' : 'transparent',
                }}
              >
                <span style={{ color: m.isGear ? '#94a3b8' : '#fbbf24', fontSize: 8, width: 16, flexShrink: 0 }}>
                  {m.isGear ? '◇' : '△'}{m.isParent ? '★' : ''}
                </span>
                <span style={{
                  color: hoveredMmsi === m.mmsi ? '#ffffff' : '#e2e8f0',
                  fontWeight: hoveredMmsi === m.mmsi ? 600 : 400,
                  flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                }}>
                  {m.name}
                </span>
                <div style={{ display: 'flex', gap: 2, flexShrink: 0 }}>
                  {m.sources.map((s, si) => (
                    <span key={si} style={{
                      display: 'inline-block', width: s.label === '1h' || s.label === '6h' ? 'auto' : 6,
                      height: 6, borderRadius: s.label === '1h' || s.label === '6h' ? 2 : '50%',
                      background: s.color, fontSize: 7, color: '#000', fontWeight: 700,
                      padding: s.label === '1h' || s.label === '6h' ? '0 2px' : 0,
                      lineHeight: '6px', textAlign: 'center',
                    }}>
                      {(s.label === '1h' || s.label === '6h') ? s.label : ''}
                    </span>
                  ))}
                </div>
              </div>
            ))}
          </div>
        )}
      </div>

      {/* 컨트롤 행 */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 5, flexWrap: 'wrap' }}>
        <button type="button" onClick={() => { if (isPlaying) store.getState().pause(); else store.getState().play(); }}
          style={{ ...btnStyle, fontSize: 12 }}>{isPlaying ? '⏸' : '▶'}</button>
        <span ref={timeDisplayRef} style={{ color: '#fbbf24', minWidth: 36, textAlign: 'center' }}>--:--</span>
        <span style={{ color: '#475569' }}>|</span>
        <button type="button" onClick={() => setReplayUiPrefs(prev => ({ ...prev, showTrails: !prev.showTrails }))}
          style={showTrails ? btnActiveStyle : btnStyle} title="항적">항적</button>
        <button type="button" onClick={() => setReplayUiPrefs(prev => ({ ...prev, showLabels: !prev.showLabels }))}
          style={showLabels ? btnActiveStyle : btnStyle} title="이름">이름</button>
        <button type="button" onClick={() => setReplayUiPrefs(prev => ({ ...prev, focusMode: !prev.focusMode }))}
          style={focusMode ? { ...btnStyle, background: 'rgba(239,68,68,0.15)', color: '#f87171' } : btnStyle}
          title="집중 모드">집중</button>
        <span style={{ color: '#475569' }}>|</span>
        <button type="button" onClick={() => setReplayUiPrefs(prev => ({ ...prev, show1hPolygon: !prev.show1hPolygon }))}
          style={show1hPolygon ? { ...btnActiveStyle, background: 'rgba(251,191,36,0.15)', color: '#fbbf24', border: '1px solid rgba(251,191,36,0.4)' } : btnStyle}
          title="1h 폴리곤">1h</button>
        <button type="button" onClick={() => has6hData && setReplayUiPrefs(prev => ({ ...prev, show6hPolygon: !prev.show6hPolygon }))}
          style={!has6hData ? { ...btnStyle, opacity: 0.3, cursor: 'not-allowed' }
            : show6hPolygon ? { ...btnActiveStyle, background: 'rgba(147,197,253,0.15)', color: '#93c5fd', border: '1px solid rgba(147,197,253,0.4)' } : btnStyle}
          disabled={!has6hData} title="6h 폴리곤">6h</button>
        <span style={{ color: '#475569' }}>|</span>
        <button type="button" onClick={() => setReplayUiPrefs(prev => ({ ...prev, abLoop: !prev.abLoop }))}
          style={abLoop ? { ...btnStyle, background: 'rgba(34,197,94,0.15)', color: '#22c55e', border: '1px solid rgba(34,197,94,0.4)' } : btnStyle}
          title="A-B 구간 반복">A-B</button>
        <span style={{ color: '#475569' }}>|</span>
        <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
          {SPEED_MULTIPLIERS.map(multiplier => {
            const active = speedMultiplier === multiplier;
            return (
              <button
                key={multiplier}
                type="button"
                onClick={() => setReplayUiPrefs(prev => ({ ...prev, speedMultiplier: multiplier }))}
                style={active
                  ? { ...btnActiveStyle, background: 'rgba(250,204,21,0.16)', color: '#fde68a', border: '1px solid rgba(250,204,21,0.32)' }
                  : btnStyle}
                title={`재생 속도 x${multiplier}`}
              >
                x{multiplier}
              </button>
            );
          })}
        </div>
        <span style={{ flex: 1 }} />
        <span style={{ color: '#64748b', fontSize: 9 }}>
          <span style={{ color: '#fbbf24' }}>{frameCount}</span>
          {has6hData && <> / <span style={{ color: '#93c5fd' }}>{frameCount6h}</span></>} 건
        </span>
        <button type="button" onClick={handleClose}
          style={{ background: 'none', border: '1px solid rgba(239,68,68,0.3)', borderRadius: 4, color: '#ef4444', cursor: 'pointer', padding: '2px 6px', fontSize: 11, fontFamily: FONT_MONO }}>
          ✕
        </button>
      </div>
    </div>
  );
};

export default HistoryReplayController;
