/**
 * 선박 데이터 Zustand 스토어
 * 참조: mda-react-front/src/shared/model/deckStore.ts
 * 참조: mda-react-front/src/common/deck.ts
 */
import { create } from 'zustand';
import { subscribeWithSelector } from 'zustand/middleware';
import {
  SIGNAL_KIND_CODE_FISHING,
  SIGNAL_KIND_CODE_KCGV,
  SIGNAL_KIND_CODE_PASSENGER,
  SIGNAL_KIND_CODE_CARGO,
  SIGNAL_KIND_CODE_TANKER,
  SIGNAL_KIND_CODE_GOV,
  SIGNAL_KIND_CODE_NORMAL,
  SIGNAL_KIND_CODE_BUOY,
  SIGNAL_SOURCE_CODE_AIS,
  SIGNAL_SOURCE_CODE_VPASS,
  SIGNAL_SOURCE_CODE_ENAV,
  SIGNAL_SOURCE_CODE_VTS_AIS,
  SIGNAL_SOURCE_CODE_D_MF_HF,
  SIGNAL_SOURCE_CODE_RADAR,
  NATIONAL_CODE_KR,
  NATIONAL_CODE_CN,
  NATIONAL_CODE_JP,
  NATIONAL_CODE_KP,
  NATIONAL_CODE_OTHER,
  SOURCE_PRIORITY_RANK,
  SOURCE_TO_ACTIVE_KEY,
} from '../types/constants';

// =====================
// 국적 코드 매핑 (ShipBatchRenderer.js와 동일)
// =====================
function mapNationalCode(nationalCode) {
  if (!nationalCode) return 'OTHER';
  const code = nationalCode.toUpperCase();
  if (code === 'KR' || code === 'KOR' || code === '440') return 'KR';
  if (code === 'CN' || code === 'CHN' || code === '412' || code === '413' || code === '414') return 'CN';
  if (code === 'JP' || code === 'JPN' || code === '431' || code === '432') return 'JP';
  if (code === 'KP' || code === 'PRK' || code === '445') return 'KP';
  return 'OTHER';
}

// =====================
// 서버 수신시간 파싱 (receivedTime → ms timestamp)
// 형식: "YYYYMMDDHHmmss"
// =====================
function parseReceivedTime(receivedTime) {
  if (!receivedTime || receivedTime.length < 14) return Date.now();
  const y = receivedTime.slice(0, 4);
  const M = receivedTime.slice(4, 6);
  const d = receivedTime.slice(6, 8);
  const h = receivedTime.slice(8, 10);
  const m = receivedTime.slice(10, 12);
  const s = receivedTime.slice(12, 14);
  const ts = new Date(`${y}-${M}-${d}T${h}:${m}:${s}`).getTime();
  return isNaN(ts) ? Date.now() : ts;
}

// =====================
// 타임아웃 상수 (카운트 사이클에서 상태 전환/삭제 판정)
// =====================
//
// ■ 영해안 (LOST=0, Inshore)
//   국내 직접 수집수단(AIS 기지국, VTS 등)이 커버하는 해역.
//   수신 주기가 짧으므로(수 초~수 분) 12분 무수신 시 정상 이탈로 판단하여 삭제.
//
// ■ 영해밖 (LOST=1, Offshore)
//   직접 수집수단이 닿지 않아 위성 AIS(S-AIS) 등 간접 수단에 의존.
//   위성 AIS는 선박 위치·궤도에 따라 수신 간격이 30분~최대 1시간까지 벌어질 수 있어,
//   유효한 항해 중인 선박이 다크시그널로 오판되지 않도록 65분(3900초)으로 설정.
//
// ■ 레이더 (단독, 비통합)
//   레이더 신호는 실시간 회전 주기(수 초)에 맞춰 갱신되므로 타임아웃을 짧게 유지.
//   함정용은 /topic/ship-throttled-60s 채널 기반이므로 90초로 설정.
//
// 참조: mda-react-front/src/common/deck.ts
// 추후 사용자 설정 화면에서 커스텀 가능하도록 상수로 분리.
// =====================
const INSHORE_TIMEOUT_MS = 12 * 60 * 1000;   // 720초 (12분) — 영해안: LOST=0, 무수신 시 삭제
const OFFSHORE_TIMEOUT_MS = 65 * 60 * 1000;  // 3900초 (65분) — 영해밖: LOST=1, 무수신 시 다크시그널 전환
const RADAR_TIMEOUT_MS = 60 * 1000;           // 90초 — 단독 레이더 비통합, 무수신 시 삭제
const SIGNAL_SOURCE_RADAR = '000005';

// =====================
// 장비 활성 상태 판단
// 참조: mda-react-front/src/common/deck.ts - isAnyEquipmentActive
// AVETDR 6개 장비 중 하나라도 '1'(활성)이면 true
// =====================
const EQUIPMENT_KEYS = ['ais', 'vpass', 'enav', 'vtsAis', 'dMfHf', 'vtsRadar'];

function isAnyEquipmentActive(ship) {
  return EQUIPMENT_KEYS.some(key => ship[key] === '1');
}

/**
 * 동적 대표 Set 생성
 * 참조: mda-react-front/docs/dynamic-priority.md §4.1
 *
 * O(N) 단일 패스로 통합선박별 동적 대표 featureId의 Set 반환.
 * 통합선박(targetId에 '_' 포함)만 처리하며, 단독선박은 스킵.
 *
 * @param {Map} features - 전체 선박 feature 맵
 * @param {Set} enabledSources - 필터에서 ON된 신호원 코드 Set
 * @param {Set} darkSignalIds - 다크시그널 선박 ID Set
 * @returns {Set<string>} 동적 대표 featureId 집합
 */
function buildDynamicPrioritySet(features, enabledSources, darkSignalIds) {
  const bestByTargetId = new Map(); // targetId → { featureId, rank }

  features.forEach((ship, featureId) => {
    // 다크시그널 스킵
    if (darkSignalIds.has(featureId)) return;

    // 단독선박 스킵 (targetId에 '_' 없고 integrate 플래그도 없음)
    const targetId = ship.targetId;
    if (!targetId || (!targetId.includes('_') && !ship.integrate)) return;

    const sourceCode = ship.signalSourceCode;

    // is_active 체크
    const activeKey = SOURCE_TO_ACTIVE_KEY[sourceCode];
    if (!activeKey || ship[activeKey] !== '1') return;

    // 필터 체크
    if (!enabledSources.has(sourceCode)) return;

    const rank = SOURCE_PRIORITY_RANK[sourceCode] ?? 99;
    const existing = bestByTargetId.get(targetId);
    if (!existing || rank < existing.rank) {
      bestByTargetId.set(targetId, { featureId, rank });
    }
  });

  const result = new Set();
  bestByTargetId.forEach(({ featureId }) => result.add(featureId));
  return result;
}

/**
 * 초기 선박 종류별 카운트
 */
const initialKindCounts = {
  [SIGNAL_KIND_CODE_FISHING]: 0,
  [SIGNAL_KIND_CODE_KCGV]: 0,
  [SIGNAL_KIND_CODE_PASSENGER]: 0,
  [SIGNAL_KIND_CODE_CARGO]: 0,
  [SIGNAL_KIND_CODE_TANKER]: 0,
  [SIGNAL_KIND_CODE_GOV]: 0,
  [SIGNAL_KIND_CODE_NORMAL]: 0,
  [SIGNAL_KIND_CODE_BUOY]: 0,
};


/**
 * 초기 선박 종류별 표시 설정
 */
const initialKindVisibility = {
  [SIGNAL_KIND_CODE_FISHING]: true,
  [SIGNAL_KIND_CODE_KCGV]: true,
  [SIGNAL_KIND_CODE_PASSENGER]: true,
  [SIGNAL_KIND_CODE_CARGO]: true,
  [SIGNAL_KIND_CODE_TANKER]: true,
  [SIGNAL_KIND_CODE_GOV]: true,
  [SIGNAL_KIND_CODE_NORMAL]: true,
  [SIGNAL_KIND_CODE_BUOY]: true,
};

/**
 * 초기 신호원별 표시 설정
 */
const initialSourceVisibility = {
  [SIGNAL_SOURCE_CODE_AIS]: true,
  [SIGNAL_SOURCE_CODE_VPASS]: true,
  [SIGNAL_SOURCE_CODE_ENAV]: true,
  [SIGNAL_SOURCE_CODE_VTS_AIS]: true,
  [SIGNAL_SOURCE_CODE_D_MF_HF]: true,
  [SIGNAL_SOURCE_CODE_RADAR]: true,
};

/**
 * 초기 국적별 표시 설정
 */
const initialNationalVisibility = {
  [NATIONAL_CODE_KR]: true,
  [NATIONAL_CODE_CN]: true,
  [NATIONAL_CODE_JP]: true,
  [NATIONAL_CODE_KP]: true,
  [NATIONAL_CODE_OTHER]: true,
};

/**
 * 선박 스토어
 */
const useShipStore = create(subscribeWithSelector((set, get) => ({
  // =====================
  // 상태 (State)
  // =====================

  /** 선박 데이터 맵 (featureId -> shipData), featureId = signalSourceCode + targetId
   *  ※ immutable 패턴: 변경 시 new Map() 생성 → Zustand 참조 비교로 변경 감지
   *     (메인 프로젝트 동일 구조) */
  features: new Map(),

  /** 다크시그널 선박 ID Set (features와 별도 관리, 메인 프로젝트 동일 구조)
   *  참조: mda-react-front/src/shared/model/deckStore.ts - darkSignalIds
   *  ※ immutable 패턴: 변경 시 new Set() 생성 → Zustand 참조 비교로 변경 감지 */
  darkSignalIds: new Set(),

  /** 선박 종류별 카운트 */
  kindCounts: { ...initialKindCounts },

  /** 선박 종류별 표시 여부 */
  kindVisibility: { ...initialKindVisibility },

  /** 신호원별 표시 여부 */
  sourceVisibility: { ...initialSourceVisibility },

  /** 국적별 표시 여부 */
  nationalVisibility: { ...initialNationalVisibility },

  /** 선택된 선박 ID (단일 클릭용, 레거시) */
  selectedShipId: null,

  /** Ctrl+Drag 다중 선택된 featureId 배열 (제한 없음) */
  selectedShipIds: [],

  /** 컨텍스트 메뉴 상태 { x, y, ships: [] } | null */
  contextMenu: null,

  /** 호버 중인 선박 정보 { ship, x, y } | null */
  hoverInfo: null,

  /** 상세 모달 배열 (최대 3개) [{ ship, id, initialPos }] */
  detailModals: [],

  /** 마지막 모달 위치 (새 모달 초기 위치 계산용) */
  lastModalPos: null,

  /** 다크시그널(소실신호) 표시 여부 */
  darkSignalVisible: true,

  /** 다크시그널 선박 수 */
  darkSignalCount: 0,

  /** 선박 표시 On/Off */
  isShipVisible: true,

  /** 선박 통합 모드 (통합선박에서 isPriority만 표시) */
  isIntegrate: true,

  /** 선명표시 여부 (개발 중 기본 활성화) */
  showLabels: true,

  /** 선명표시 옵션 (개발 중 기본 모두 활성화) */
  labelOptions: {
    showShipName: true,     // 선박명
    showSpeedVector: true,  // 속도벡터
    showShipSize: true,     // 선박크기
    showSignalStatus: false, // 신호상태
  },

  /** STOMP 연결 상태 */
  isConnected: false,

  /** 범례 표시 여부 */
  showLegend: true,

  /** 변경된 선박 ID 추적 (렌더링 최적화용) */
  changedIds: new Set(),

  /** 총 선박 수 */
  totalCount: 0,

  // =====================
  // 액션 (Actions)
  // =====================

  /**
   * 여러 선박 데이터 병합 (bulk update)
   * 카운트는 ShipBatchRenderer의 렌더 사이클에서 계산 (메인 프로젝트 동일)
   * @param {Array} ships - 선박 데이터 배열
   */
  mergeFeatures: (ships) => {
    // ※ immutable 패턴: 배치 단위로 변경 후 1회만 new Map()/new Set() 생성
    const state = get();
    const newFeatures = new Map(state.features);
    const newDarkSignalIds = new Set(state.darkSignalIds);
    let darkChanged = false;

    ships.forEach((ship) => {
      const featureId = ship.featureId;
      if (!featureId) return;

      // 좌표가 없으면 스킵
      if (!ship.longitude || !ship.latitude) {
        return;
      }

      // 타임스탬프 비교: 기존 데이터보다 오래된 메시지는 무시
      // 참조: mda-react-front/src/shared/model/deckStore.ts - mergeFeatures (line 163)
      const newTimestamp = parseReceivedTime(ship.receivedTime);
      const currentFeature = newFeatures.get(featureId);
      if (currentFeature && newTimestamp < currentFeature.receivedTimestamp) {
        return; // 이전 시간대 데이터 → 무시
      }

      const hasActive = isAnyEquipmentActive(ship);

      // 규칙 1: LOST=0(영해 내) + 모든 장비 비활성 → 저장하지 않음 (완전 삭제)
      if (!ship.lost && !hasActive) {
        newFeatures.delete(featureId);
        if (newDarkSignalIds.delete(featureId)) darkChanged = true;
        return;
      }

      // 다크시그널 상태 판정
      if (hasActive) {
        if (newDarkSignalIds.delete(featureId)) darkChanged = true;
      } else {
        if (!newDarkSignalIds.has(featureId)) {
          newDarkSignalIds.add(featureId);
          darkChanged = true;
        }
      }

      newFeatures.set(featureId, { ...ship, receivedTimestamp: newTimestamp });
    });

    // immutable 참조 변경 → Zustand 감지
    set({
      features: newFeatures,
      ...(darkChanged ? { darkSignalIds: newDarkSignalIds } : {}),
    });
  },

  /**
   * 타임아웃 cleanup 적용 (ShipBatchRenderer에서 호출)
   * immutable 패턴으로 삭제 + 다크시그널 전환을 한 번에 처리
   * @param {Array<string>} deleteIds - 삭제할 featureId 배열
   * @param {Array<string>} darkSignalConvertIds - 다크시그널로 전환할 featureId 배열
   */
  applyCleanup: (deleteIds, darkSignalConvertIds) => {
    if (deleteIds.length === 0 && darkSignalConvertIds.length === 0) return;

    const state = get();
    const newFeatures = new Map(state.features);
    const newDarkSignalIds = new Set(state.darkSignalIds);

    deleteIds.forEach(id => {
      newFeatures.delete(id);
      newDarkSignalIds.delete(id);
    });

    darkSignalConvertIds.forEach(id => newDarkSignalIds.add(id));

    set({ features: newFeatures, darkSignalIds: newDarkSignalIds });
  },

  /**
   * 단일 선박 추가/업데이트
   * @param {Object} ship - 선박 데이터
   */
  addOrUpdateFeature: (ship) => {
    get().mergeFeatures([ship]);
  },

  /**
   * 선박 삭제
   * @param {string} featureId - 삭제할 선박 ID (signalSourceCode + targetId)
   */
  deleteFeatureById: (featureId) => {
    const state = get();
    const newFeatures = new Map(state.features);
    newFeatures.delete(featureId);
    const updates = { features: newFeatures };

    if (state.darkSignalIds.has(featureId)) {
      const newDark = new Set(state.darkSignalIds);
      newDark.delete(featureId);
      updates.darkSignalIds = newDark;
    }

    if (state.selectedShipId === featureId) {
      updates.selectedShipId = null;
    }

    set(updates);
  },

  /**
   * 여러 선박 삭제
   * @param {Array<string>} featureIds - 삭제할 선박 ID 배열 (signalSourceCode + targetId)
   */
  deleteFeaturesByIds: (featureIds) => {
    const state = get();
    const newFeatures = new Map(state.features);
    const newDarkSignalIds = new Set(state.darkSignalIds);
    let darkChanged = false;

    featureIds.forEach((featureId) => {
      newFeatures.delete(featureId);
      if (newDarkSignalIds.delete(featureId)) darkChanged = true;
    });

    set({
      features: newFeatures,
      ...(darkChanged ? { darkSignalIds: newDarkSignalIds } : {}),
      selectedShipId: featureIds.includes(state.selectedShipId) ? null : state.selectedShipId,
    });
  },

  /**
   * 선박 종류별 표시 토글
   * 필터 변경 → useShipLayer subscription → immediateRender → 카운트 재계산
   * @param {string} kindCode - 선박 종류 코드
   */
  toggleKindVisibility: (kindCode) => {
    set((state) => ({
      kindVisibility: {
        ...state.kindVisibility,
        [kindCode]: !state.kindVisibility[kindCode],
      },
    }));
  },

  /**
   * 신호원별 표시 토글
   * 필터 변경 → useShipLayer subscription → immediateRender → 카운트 재계산
   * @param {string} sourceCode - 신호원 코드
   */
  toggleSourceVisibility: (sourceCode) => {
    set((state) => ({
      sourceVisibility: {
        ...state.sourceVisibility,
        [sourceCode]: !state.sourceVisibility[sourceCode],
      },
    }));
  },

  /**
   * 국적별 표시 토글
   * 필터 변경 → useShipLayer subscription → immediateRender → 카운트 재계산
   * @param {string} nationalCode - 국적 코드
   */
  toggleNationalVisibility: (nationalCode) => {
    set((state) => ({
      nationalVisibility: {
        ...state.nationalVisibility,
        [nationalCode]: !state.nationalVisibility[nationalCode],
      },
    }));
  },

  /**
   * 다크시그널 표시 토글
   */
  toggleDarkSignalVisible: () => {
    set((state) => ({
      darkSignalVisible: !state.darkSignalVisible,
    }));
  },

  /**
   * 다크시그널 선박 일괄 삭제
   */
  clearDarkSignals: () => {
    const state = get();
    const newFeatures = new Map(state.features);
    state.darkSignalIds.forEach((fid) => {
      newFeatures.delete(fid);
    });
    set({ features: newFeatures, darkSignalIds: new Set() });
  },

  /**
   * 선박 표시 전체 On/Off
   */
  toggleShipVisible: () => {
    set((state) => ({
      isShipVisible: !state.isShipVisible,
    }));
  },

  /**
   * 선명표시 On/Off
   */
  toggleShowLabels: () => {
    set((state) => ({
      showLabels: !state.showLabels,
    }));
  },

  /**
   * 선명표시 옵션 설정
   * @param {string} optionKey - 옵션 키 (showShipName, showSpeedVector, showShipSize, showSignalStatus)
   */
  toggleLabelOption: (optionKey) => {
    set((state) => ({
      labelOptions: {
        ...state.labelOptions,
        [optionKey]: !state.labelOptions[optionKey],
      },
    }));
  },

  /**
   * 선명표시 옵션 직접 설정
   * @param {Object} options - 옵션 객체
   */
  setLabelOptions: (options) => {
    set((state) => ({
      labelOptions: {
        ...state.labelOptions,
        ...options,
      },
    }));
  },

  /**
   * 선박 통합 모드 토글
   * 통합 모드 On: isPriority=1인 선박만 표시
   * 통합 모드 Off: 모든 선박 표시
   */
  toggleIntegrate: () => {
    const newMode = !get().isIntegrate;
    get().syncSelectedWithIntegrateMode(newMode);
    set({ isIntegrate: newMode });
  },

  /**
   * 선박 선택
   * @param {string|null} featureId - 선택할 선박 ID (null이면 선택 해제, signalSourceCode + targetId)
   */
  selectShip: (featureId) => {
    set({ selectedShipId: featureId });
  },

  /**
   * Ctrl+Drag 다중 선택 설정
   * @param {Array<string>} ids - featureId 배열
   */
  setSelectedShipIds: (ids) => set({ selectedShipIds: ids }),

  /**
   * 다중 선택 해제
   */
  clearSelectedShips: () => set({ selectedShipIds: [] }),

  /**
   * 컨텍스트 메뉴 열기
   * @param {{ x: number, y: number, ships: Array }} info
   */
  openContextMenu: (info) => set({ contextMenu: info }),

  /**
   * 컨텍스트 메뉴 닫기
   */
  closeContextMenu: () => set({ contextMenu: null }),

  /**
   * 통합모드 전환 시 selectedShipIds 동기화
   * 참조: mda-react-front/src/shared/model/deckStore.ts - syncSelectedFeaturesWithIntegrateMode
   * @param {boolean} toIntegrateMode - 전환 후 통합모드 ON 여부
   */
  syncSelectedWithIntegrateMode: (toIntegrateMode) => {
    const { selectedShipIds, features } = get();
    if (selectedShipIds.length === 0) return;

    const EQUIPMENT_MAP = [
      { index: 0, signalSourceCode: '000001', dataKey: 'ais' },
      { index: 1, signalSourceCode: '000003', dataKey: 'vpass' },
      { index: 2, signalSourceCode: '000002', dataKey: 'enav' },
      { index: 3, signalSourceCode: '000004', dataKey: 'vtsAis' },
      { index: 4, signalSourceCode: '000016', dataKey: 'dMfHf' },
      // index 5 = VTS-Radar → 확장 시 제외
    ];

    if (toIntegrateMode) {
      // OFF → ON: 개별 장비 → 대표(isPriority) 선박으로 축소
      const newIds = [];
      const seenTargetIds = new Set();

      selectedShipIds.forEach((fid) => {
        const ship = features.get(fid);
        if (!ship) return;

        if (!ship.integrate) {
          newIds.push(fid);
          return;
        }

        const tid = ship.targetId;
        if (seenTargetIds.has(tid)) return;
        seenTargetIds.add(tid);

        let priorityFid = null;
        features.forEach((s, id) => {
          if (s.targetId === tid && s.isPriority) priorityFid = id;
        });
        newIds.push(priorityFid || fid);
      });

      set({ selectedShipIds: newIds });
    } else {
      // ON → OFF: 대표 선박 → isActive인 개별 장비로 확장
      const newIds = [];

      selectedShipIds.forEach((fid) => {
        const ship = features.get(fid);
        if (!ship) return;

        if (!ship.integrate || !ship.isPriority) {
          newIds.push(fid);
          return;
        }

        const parts = ship.targetId.split('_');
        let expanded = false;

        EQUIPMENT_MAP.forEach(({ index, signalSourceCode, dataKey }) => {
          const equipTargetId = parts[index];
          if (!equipTargetId) return;
          if (ship[dataKey] !== '1') return;

          const equipFeatureId = signalSourceCode + equipTargetId;
          if (features.has(equipFeatureId)) {
            newIds.push(equipFeatureId);
            expanded = true;
          }
        });

        if (!expanded) newIds.push(fid);
      });

      set({ selectedShipIds: newIds });
    }
  },

  /**
   * 호버 정보 설정
   * @param {Object|null} info - { ship, x, y } 또는 null
   */
  setHoverInfo: (info) => {
    set({ hoverInfo: info });
  },

  /**
   * 상세 모달 열기 (최대 3개, 4번째부터 FIFO 제거)
   * 새 모달은 마지막 모달의 현재 위치 기준 우측 140px 오프셋으로 생성
   * 참조: mda-react-front/src/shared/model/deckStore.ts - setAddDetailModal
   * @param {Object} ship - 선박 데이터
   */
  openDetailModal: (ship) => {
    set((state) => {
      let displayShip = ship;

      // 통합선박이고 신호원이 레이더인 경우, 비레이더 신호원으로 교체
      const isIntegrated = ship.targetId && (ship.targetId.includes('_') || ship.integrate);
      if (isIntegrated && ship.signalSourceCode === SIGNAL_SOURCE_CODE_RADAR) {
        // 같은 targetId의 비레이더 신호원 중 우선순위가 가장 높은 것 찾기
        const alternatives = Array.from(state.features.values())
          .filter(f =>
            f.targetId === ship.targetId &&
            f.signalSourceCode !== SIGNAL_SOURCE_CODE_RADAR
          )
          .sort((a, b) => {
            // 우선순위 정렬 (낮은 숫자 = 높은 우선순위)
            const rankA = SOURCE_PRIORITY_RANK[a.signalSourceCode] ?? 99;
            const rankB = SOURCE_PRIORITY_RANK[b.signalSourceCode] ?? 99;
            return rankA - rankB;
          });

        if (alternatives.length > 0) {
          displayShip = alternatives[0];
        }
      }

      // 이미 열린 동일 선박 모달이면 무시
      if (state.detailModals.some((m) => m.id === displayShip.featureId)) {
        return state;
      }

      // 새 모달 초기 위치: 마지막 모달 위치 + 140px 우측
      // 최초 모달은 화면 중앙 근처에서 시작 (가로: 화면 중앙 - 200px, 세로: 100px)
      const defaultX = typeof window !== 'undefined' ? Math.max(100, (window.innerWidth / 2) - 200) : 400;
      const basePos = state.lastModalPos || { x: defaultX - 140, y: 100 };
      const initialPos = { x: basePos.x + 140, y: basePos.y };

      const newModal = { ship: displayShip, id: displayShip.featureId, initialPos };
      let modals = [...state.detailModals, newModal];

      // 3개 초과 시 가장 오래된 모달 제거
      if (modals.length > 3) {
        modals = modals.slice(modals.length - 3);
      }

      return {
        detailModals: modals,
        lastModalPos: initialPos,
      };
    });
  },

  /**
   * 모달 위치 업데이트 (드래그 후 호출)
   * @param {string} modalId - 모달 ID
   * @param {{ x: number, y: number }} pos - 현재 위치
   */
  updateModalPos: (modalId, pos) => {
    set({ lastModalPos: pos });
  },

  /**
   * 특정 상세 모달 닫기
   * @param {string} modalId - 모달 ID (featureId)
   */
  closeDetailModal: (modalId) => {
    set((state) => ({
      detailModals: state.detailModals.filter((m) => m.id !== modalId),
    }));
  },

  /**
   * 모든 상세 모달 닫기
   */
  closeAllDetailModals: () => {
    set({ detailModals: [], lastModalPos: null });
  },

  /**
   * STOMP 연결 상태 설정
   * @param {boolean} connected - 연결 상태
   */
  setConnected: (connected) => {
    set({ isConnected: connected });
  },

  /**
   * 범례 표시 토글
   */
  toggleShowLegend: () => {
    set((state) => ({ showLegend: !state.showLegend }));
  },

  /**
   * 모든 선박 데이터 초기화
   */
  clearFeatures: () => {
    set({
      features: new Map(),
      darkSignalIds: new Set(),
      kindCounts: { ...initialKindCounts },
      selectedShipId: null,
      selectedShipIds: [],
      contextMenu: null,
      totalCount: 0,
      darkSignalCount: 0,
    });
  },

  /**
   * 변경 ID 초기화 (렌더링 후 호출)
   */
  clearChangedIds: () => {
    set({ changedIds: new Set() });
  },

  /**
   * 선박 종류별 카운트 직접 설정 (서버 count 토픽용)
   * @param {Object} counts - 종류별 카운트 객체
   */
  setKindCounts: (counts) => {
    const totalCount = Object.values(counts).reduce((sum, count) => sum + count, 0);
    set({
      kindCounts: { ...initialKindCounts, ...counts },
      totalCount,
    });
  },

  // =====================
  // 셀렉터 (Selectors)
  // =====================

  /**
   * 표시 가능한 선박 목록 (필터 적용)
   * @returns {Array} 필터링된 선박 배열
   */
  getVisibleShips: () => {
    const state = get();
    if (!state.isShipVisible) return [];

    const { features, darkSignalIds, kindVisibility, sourceVisibility, darkSignalVisible } = state;
    const result = [];

    features.forEach((ship, featureId) => {
      // 다크시그널은 독립 필터 (선종/신호원/국적 필터 무시)
      if (darkSignalIds.has(featureId)) {
        if (darkSignalVisible) result.push(ship);
        return;
      }

      // 선박 종류 필터
      if (!kindVisibility[ship.signalKindCode]) return;

      // 신호원 필터
      if (!sourceVisibility[ship.signalSourceCode]) return;

      result.push(ship);
    });

    return result;
  },

  /**
   * 선택된 선박 정보
   * @returns {Object|null} 선박 데이터 또는 null
   */
  getSelectedShip: () => {
    const { features, selectedShipId } = get();
    return selectedShipId ? features.get(selectedShipId) : null;
  },

  /**
   * 선택된 모든 선박 정보 (하이라이트 표시용)
   * selectedShipIds(박스선택) + detailModals(상세모달) 통합
   * @returns {Array} 선박 데이터 배열
   */
  getSelectedShips: () => {
    const { features, selectedShipIds, detailModals } = get();
    const result = [];
    const seen = new Set();

    selectedShipIds.forEach((fid) => {
      const ship = features.get(fid);
      if (ship && !seen.has(fid)) {
        result.push(ship);
        seen.add(fid);
      }
    });

    detailModals.forEach((m) => {
      if (!seen.has(m.id)) {
        // 라이브 데이터 우선 사용 (m.id === featureId === signalSourceCode + targetId)
        const liveShip = features.get(m.id);
        if (liveShip) {
          result.push(liveShip);
        } else if (m.ship) {
          result.push(m.ship);
        }
        seen.add(m.id);
      }
    });

    return result;
  },

  /**
   * CSV 다운로드용 선박 목록 (필터 적용)
   * - 레이더 항상 제외
   * - 통합 모드: isPriority만 포함
   * - 다크시그널: 독립 필터 적용
   * - 일반: 선종/신호원/국적 필터 적용
   * @returns {Array} 다운로드용 선박 배열 (downloadTargetId 포함)
   */
  getDownloadShips: () => {
    const state = get();
    const {
      features, darkSignalIds, kindVisibility, sourceVisibility, nationalVisibility,
      isIntegrate, darkSignalVisible,
    } = state;

    // 통합 모드: 동적 우선순위 Set 생성
    let dynamicPrioritySet = null;
    if (isIntegrate) {
      const enabledSources = new Set();
      Object.entries(sourceVisibility).forEach(([code, on]) => { if (on) enabledSources.add(code); });
      dynamicPrioritySet = buildDynamicPrioritySet(features, enabledSources, darkSignalIds);
    }

    const result = [];

    features.forEach((ship, featureId) => {
      // 레이더 항상 제외
      if (ship.signalSourceCode === '000005') return;

      // 통합 모드: 동적 대표만 포함
      if (isIntegrate && ship.targetId && ship.targetId.includes('_')) {
        if (!dynamicPrioritySet.has(featureId)) return;
      }

      const downloadTargetId = isIntegrate ? ship.targetId : ship.originalTargetId;

      // 다크시그널: 독립 필터
      if (darkSignalIds.has(featureId)) {
        if (darkSignalVisible) {
          result.push({ ...ship, downloadTargetId });
        }
        return;
      }

      // 선종 필터
      if (!kindVisibility[ship.signalKindCode]) return;
      // 신호원 필터
      if (!sourceVisibility[ship.signalSourceCode]) return;
      // 국적 필터
      const mapped = mapNationalCode(ship.nationalCode);
      if (!nationalVisibility[mapped]) return;

      result.push({ ...ship, downloadTargetId });
    });

    return result;
  },
})));

export {
  buildDynamicPrioritySet,
  isAnyEquipmentActive,
  mapNationalCode,
  initialKindCounts,
  INSHORE_TIMEOUT_MS,
  OFFSHORE_TIMEOUT_MS,
  RADAR_TIMEOUT_MS,
  SIGNAL_SOURCE_RADAR,
};
export default useShipStore;
