/**
 * 항적조회 전용 deck.gl 레이어 생성 유틸리티
 *
 * - PathLayer: 선종 색상 기반 항적 라인
 * - ScatterplotLayer: 포인트 표시 (클러스터링)
 * - IconLayer: 가상 선박 아이콘
 * - TextLayer: 선명 라벨
 */

import { PathLayer, ScatterplotLayer, IconLayer, TextLayer } from '@deck.gl/layers';
import { PathStyleExtension } from '@deck.gl/extensions';
import { getShipIconUrl } from './shipIconUtil';
import { getShipKindColor } from '../types/trackQuery.types';
import useShipStore from '../../stores/shipStore';
import { useMapStore, THEME_COLORS, THEME_TYPES } from '../../stores/mapStore';
import {
  ICON_ATLAS_MAPPING,
  ICON_MAPPING_KIND_MOVING,
} from '../../types/constants';
import atlasImg from '../../assets/img/icon/atlas.png';

/** 현재 테마 색상 가져오기 */
function getCurrentThemeColors() {
  const { getTheme } = useMapStore.getState();
  const theme = getTheme();
  return THEME_COLORS[theme] || THEME_COLORS[THEME_TYPES.LIGHT];
}

// ========== 줌 레벨별 포인트 밀도 설정 ==========

const POINT_DENSITY_CONFIGS = {
  5: { gridSizeMultiplier: 400, maxPointsPerCell: 1, minPointRadius: 2, maxPointRadius: 3 },
  6: { gridSizeMultiplier: 300, maxPointsPerCell: 2, minPointRadius: 2, maxPointRadius: 3 },
  7: { gridSizeMultiplier: 200, maxPointsPerCell: 3, minPointRadius: 2, maxPointRadius: 4 },
  8: { gridSizeMultiplier: 150, maxPointsPerCell: 5, minPointRadius: 2, maxPointRadius: 4 },
  9: { gridSizeMultiplier: 100, maxPointsPerCell: 8, minPointRadius: 3, maxPointRadius: 5 },
  10: { gridSizeMultiplier: 80, maxPointsPerCell: 12, minPointRadius: 3, maxPointRadius: 5 },
  11: { gridSizeMultiplier: 80, maxPointsPerCell: 15, minPointRadius: 3, maxPointRadius: 6 },
  12: { gridSizeMultiplier: 60, maxPointsPerCell: 20, minPointRadius: 4, maxPointRadius: 6 },
  13: { gridSizeMultiplier: 30, maxPointsPerCell: Infinity, minPointRadius: 4, maxPointRadius: 7 },
  14: { gridSizeMultiplier: 20, maxPointsPerCell: Infinity, minPointRadius: 4, maxPointRadius: 8 },
};

const getPointDensityConfig = (zoomLevel) => {
  const clampedZoom = Math.max(5, Math.min(14, Math.floor(zoomLevel)));
  return POINT_DENSITY_CONFIGS[clampedZoom] || POINT_DENSITY_CONFIGS[10];
};

// ========== 레이어 ID 상수 ==========

export const LAYER_IDS = {
  LOOP_SECTION_PATH: 'track-query-loop-section-path-layer',
  PATH: 'track-query-path-layer',
  POINTS: 'track-query-points-layer',
  VIRTUAL_SHIP_GLOW: 'track-query-virtual-ship-glow-layer',
  VIRTUAL_SHIP: 'track-query-virtual-ship-layer',
  VIRTUAL_SHIP_LABEL: 'track-query-virtual-ship-label-layer',
  LIVE_CONNECTION: 'track-query-live-connection-layer',
  TOOLTIP: 'track-query-tooltip-layer',
};

// ========== 데이터 생성 함수 ==========

/** 항적 라인 PathLayer 데이터 생성 */
export function createPathLayerData(tracks) {
  return tracks.map(track => ({
    path: track.geometry,
    color: getShipKindColor(track.shipKindCode),
    width: 3,
    vesselId: track.vesselId,
    shipKindCode: track.shipKindCode,
    shipName: track.shipName,
  }));
}

/** 포인트 ScatterplotLayer 데이터 생성 (클러스터링 적용) */
export function createPointsLayerData(tracks, zoomLevel) {
  const points = [];

  tracks.forEach(track => {
    const color = getShipKindColor(track.shipKindCode);
    const pointColor = [
      Math.min(255, color[0] + 30),
      Math.min(255, color[1] + 30),
      Math.min(255, color[2] + 30),
      255,
    ];

    track.geometry.forEach((coord, index) => {
      points.push({
        position: coord,
        color: pointColor,
        vesselId: track.vesselId,
        timestamp: track.timestampsMs[index],
        speed: track.speeds[index] || 0,
        index,
      });
    });
  });

  if (zoomLevel === undefined || points.length < 500) {
    return points;
  }

  return clusterTrackPoints(points, zoomLevel);
}

/** 항적 포인트 클러스터링 */
function clusterTrackPoints(points, zoomLevel) {
  const config = getPointDensityConfig(zoomLevel);

  if (config.maxPointsPerCell === Infinity) {
    return points;
  }

  const gridSize = Math.pow(2, -zoomLevel) * config.gridSizeMultiplier;
  const gridCells = new Map();

  for (const point of points) {
    const gridX = Math.floor(point.position[0] / gridSize);
    const gridY = Math.floor(point.position[1] / gridSize);
    const gridKey = `${gridX},${gridY}`;

    if (!gridCells.has(gridKey)) {
      gridCells.set(gridKey, []);
    }
    gridCells.get(gridKey).push(point);
  }

  const result = [];

  gridCells.forEach(cellPoints => {
    if (cellPoints.length <= config.maxPointsPerCell) {
      result.push(...cellPoints);
    } else {
      cellPoints.sort((a, b) => a.timestamp - b.timestamp);
      const step = cellPoints.length / config.maxPointsPerCell;
      for (let i = 0; i < config.maxPointsPerCell; i++) {
        const idx = Math.floor(i * step);
        result.push(cellPoints[idx]);
      }
    }
  });

  return result;
}

/** 가상 선박 IconLayer 데이터 생성 */
export function createVirtualShipData(positions) {
  return positions.map(pos => ({
    position: pos.position,
    icon: ICON_MAPPING_KIND_MOVING[pos.shipKindCode] || 'etcImg',
    size: 24,
    vesselId: pos.vesselId,
    heading: pos.heading,
    shipName: pos.shipName,
    speed: pos.speed,
    shipKindCode: pos.shipKindCode,
  }));
}

/** 가상 선박 글로우 효과 데이터 생성 */
export function createVirtualShipGlowData(positions) {
  return positions.map(pos => {
    const color = getShipKindColor(pos.shipKindCode);
    return {
      position: pos.position,
      color: [color[0], color[1], color[2], 120],
      vesselId: pos.vesselId,
    };
  });
}

/** 유효한 선명인지 확인 */
function isValidLabelShipName(name) {
  if (!name) return false;
  const trimmed = name.trim();
  if (!trimmed) return false;
  if (trimmed === '-') return false;
  if (/^\d+$/.test(trimmed)) return false;
  return true;
}

/** 선명 라벨 데이터 생성 */
export function createVirtualShipLabelData(positions) {
  return positions.map(pos => ({
    position: pos.position,
    text: isValidLabelShipName(pos.shipName) ? pos.shipName : pos.targetId,
    vesselId: pos.vesselId,
  }));
}

// ========== 레이어 생성 함수 ==========

/**
 * 경로 레이어 생성
 */
export function createPathLayers(tracks, options, onPathHover) {
  const layers = [];
  const { updateTrigger, highlightedVesselId = null } = options;

  if (tracks.length === 0) return layers;

  const pathData = createPathLayerData(tracks);

  const pathLayer = new PathLayer({
    id: LAYER_IDS.PATH,
    data: pathData,
    getPath: d => d.path,
    getColor: d => {
      if (highlightedVesselId && highlightedVesselId === d.vesselId) {
        return [255, 255, 0, 255];
      }
      return d.color;
    },
    getWidth: d => {
      if (highlightedVesselId && highlightedVesselId === d.vesselId) {
        return 6;
      }
      return d.width;
    },
    widthMinPixels: 2,
    widthMaxPixels: 8,
    pickable: true,
    autoHighlight: true,
    highlightColor: [255, 255, 0, 220],
    onHover: info => {
      if (onPathHover) {
        onPathHover(info.object?.vesselId ?? null);
      }
    },
    updateTriggers: {
      getColor: [updateTrigger, highlightedVesselId],
      getWidth: [updateTrigger, highlightedVesselId],
    },
  });
  layers.push(pathLayer);

  return layers;
}

/**
 * 포인트 레이어 생성 (클러스터링 포함)
 */
export function createPointsLayerOnly(tracks, options, onPointHover) {
  const { updateTrigger, zoomLevel } = options;

  if (tracks.length === 0) return null;

  const pointsData = createPointsLayerData(tracks, zoomLevel);
  const pointConfig = zoomLevel ? getPointDensityConfig(zoomLevel) : { minPointRadius: 3, maxPointRadius: 6 };

  return new ScatterplotLayer({
    id: LAYER_IDS.POINTS,
    data: pointsData,
    getPosition: d => d.position,
    getFillColor: d => d.color,
    getRadius: 4,
    radiusMinPixels: pointConfig.minPointRadius,
    radiusMaxPixels: pointConfig.maxPointRadius,
    pickable: true,
    onHover: info => {
      if (onPointHover) {
        if (info.object) {
          const point = info.object;
          onPointHover(
            {
              vesselId: point.vesselId,
              position: point.position,
              timestamp: point.timestamp,
              speed: point.speed,
              index: point.index,
            },
            info.x,
            info.y,
          );
        } else {
          onPointHover(null, 0, 0);
        }
      }
    },
    updateTriggers: {
      data: [updateTrigger, zoomLevel],
    },
  });
}

/**
 * 동적 레이어 생성 (가상 선박 아이콘, 라벨)
 * currentTime 변경 시마다 재생성
 */
export function createDynamicTrackLayers(positions, tracks, options, onIconHover) {
  const layers = [];
  const { showVirtualShip, showLabels = false, updateTrigger } = options;

  // 1. 가상 선박 글로우 효과
  if (showVirtualShip && positions.length > 0) {
    const glowData = createVirtualShipGlowData(positions);

    const glowLayer = new ScatterplotLayer({
      id: LAYER_IDS.VIRTUAL_SHIP_GLOW,
      data: glowData,
      getPosition: d => d.position,
      getFillColor: d => d.color,
      getRadius: 20,
      radiusMinPixels: 18,
      radiusMaxPixels: 28,
      pickable: false,
      updateTriggers: { getPosition: updateTrigger },
    });
    layers.push(glowLayer);

    // 2. IconLayer - 가상 선박
    const iconData = createVirtualShipData(positions);

    const iconLayer = new IconLayer({
      id: LAYER_IDS.VIRTUAL_SHIP,
      data: iconData,
      iconAtlas: atlasImg,
      iconMapping: ICON_ATLAS_MAPPING,
      getIcon: d => d.icon,
      getPosition: d => d.position,
      getSize: d => d.size,
      sizeUnits: 'pixels',
      getAngle: d => d.heading || 0,
      pickable: true,
      onHover: info => {
        if (onIconHover) {
          if (info.object) {
            onIconHover(info.object, info.x, info.y);
          } else {
            onIconHover(null, 0, 0);
          }
        }
      },
      updateTriggers: {
        getPosition: updateTrigger,
        getAngle: updateTrigger,
      },
    });
    layers.push(iconLayer);

    // 3. TextLayer - 선명 라벨
    if (showLabels) {
      const labelData = createVirtualShipLabelData(positions);
      const themeColors = getCurrentThemeColors();

      const labelLayer = new TextLayer({
        id: LAYER_IDS.VIRTUAL_SHIP_LABEL,
        data: labelData,
        getPosition: d => d.position,
        getText: d => d.text,
        getSize: 12,
        getColor: themeColors.shipLabel,
        getAngle: 0,
        getTextAnchor: 'start',
        getAlignmentBaseline: 'center',
        getPixelOffset: [14, 0],
        fontFamily: 'sans-serif',
        fontWeight: 'bold',
        outlineWidth: 2,
        outlineColor: themeColors.shipLabelOutline,
        characterSet: 'auto',
        pickable: false,
        updateTriggers: { getPosition: updateTrigger },
      });
      layers.push(labelLayer);
    }
  }

  return layers;
}

// ========== 포인트 정보 포맷팅 ==========

/** 포인트 정보 포맷팅 (호버 툴팁용) */
export function formatPointInfo(info) {
  const date = new Date(info.timestamp);
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  const day = String(date.getDate()).padStart(2, '0');
  const hours = String(date.getHours()).padStart(2, '0');
  const minutes = String(date.getMinutes()).padStart(2, '0');
  const seconds = String(date.getSeconds()).padStart(2, '0');
  const timeStr = `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;

  return {
    time: timeStr,
    position: `${info.position[1].toFixed(6)}, ${info.position[0].toFixed(6)}`,
    speed: `${info.speed.toFixed(1)} knots`,
  };
}

// ========== 라이브 연결선 (항적 끝점 ↔ 라이브 선박) ==========

/**
 * 마지막 항적점과 라이브 선박 사이 연결 데이터 생성
 * 항적의 마지막 점과 실시간 선박 위치를 점선으로 연결
 *
 * @param {Array} tracks - ProcessedTrack 배열
 * @returns {Array} 연결선 데이터 배열 [{ path, color, vesselId }]
 */
export function createLiveConnectionData(tracks) {
  const { features } = useShipStore.getState();
  const connections = [];

  if (tracks.length === 0) return connections;

  tracks.forEach(track => {
    if (track.geometry.length === 0) return;

    const lastPoint = track.geometry[track.geometry.length - 1];
    const color = getShipKindColor(track.shipKindCode);

    // 라이브 선박 좌표 조회: sigSrcCd + targetId = featureId
    const featureKey = `${track.sigSrcCd}${track.targetId}`;
    const liveShip = features.get(featureKey);

    if (!liveShip || !liveShip.longitude || !liveShip.latitude) return;

    const liveLon = Number(liveShip.longitude);
    const liveLat = Number(liveShip.latitude);

    if (isNaN(liveLon) || isNaN(liveLat)) return;

    // 항적 마지막 점과 라이브 선박 사이 거리가 너무 가까우면 스킵
    const dx = liveLon - lastPoint[0];
    const dy = liveLat - lastPoint[1];
    if (Math.abs(dx) < 0.00001 && Math.abs(dy) < 0.00001) return;

    connections.push({
      path: [lastPoint, [liveLon, liveLat]],
      color: [color[0], color[1], color[2], 180],
      vesselId: track.vesselId,
    });
  });

  return connections;
}

/**
 * 라이브 선박 연결선 레이어 생성 (점선 스타일)
 * 항적 마지막 점과 라이브 선박 위치를 점선으로 연결
 *
 * @param {Array} tracks - ProcessedTrack 배열
 * @param {number} updateTrigger - 업데이트 트리거
 * @returns {PathLayer|null} 연결선 레이어
 */
export function createLiveConnectionLayer(tracks, updateTrigger) {
  if (tracks.length === 0) return null;

  const connectionData = createLiveConnectionData(tracks);
  if (connectionData.length === 0) return null;

  return new PathLayer({
    id: LAYER_IDS.LIVE_CONNECTION,
    data: connectionData,
    getPath: d => d.path,
    getColor: d => d.color,
    getWidth: 2,
    widthMinPixels: 2,
    widthMaxPixels: 3,
    getDashArray: [6, 4],
    dashJustified: true,
    extensions: [new PathStyleExtension({ dash: true })],
    pickable: false,
    updateTriggers: {
      getPath: updateTrigger,
    },
  });
}

// ========== 전역 레이어 레지스트리 ==========

/** 전역 레이어 레지스트리에 레이어 등록 */
export function registerTrackQueryLayers(layers) {
  window.__trackQueryLayers__ = layers;
}

/** 전역 레이어 레지스트리에서 레이어 제거 */
export function unregisterTrackQueryLayers() {
  window.__trackQueryLayers__ = [];
}

/** 등록된 TrackQuery 레이어 가져오기 */
export function getTrackQueryLayers() {
  return window.__trackQueryLayers__ || [];
}
