import { useMemo } from 'react';
import { ScatterplotLayer, TextLayer } from '@deck.gl/layers';
import type { Layer } from '@deck.gl/core';
import type { Ship, VesselAnalysisDto, RiskLevel } from '../types';
import { useFontScale } from './useFontScale';
import { FONT_MONO } from '../styles/fonts';
import { RISK_TO_ALERT, type AlertLevel } from '../constants/riskMapping';

interface AnalyzedShip {
  ship: Ship;
  dto: VesselAnalysisDto;
  alert: AlertLevel;
}

// AlertLevel 기반 충전색 (현장분석 팔레트 통일)
const ALERT_RGBA: Record<AlertLevel, [number, number, number, number]> = {
  CRITICAL: [255, 82, 82, 60],
  WATCH: [255, 215, 64, 50],
  MONITOR: [24, 255, 255, 40],
  NORMAL: [0, 230, 118, 30],
};

const ALERT_RGBA_BORDER: Record<AlertLevel, [number, number, number, number]> = {
  CRITICAL: [255, 82, 82, 230],
  WATCH: [255, 215, 64, 210],
  MONITOR: [24, 255, 255, 190],
  NORMAL: [0, 230, 118, 160],
};

const ALERT_SIZE: Record<AlertLevel, number> = {
  CRITICAL: 18,
  WATCH: 14,
  MONITOR: 12,
  NORMAL: 10,
};

const ALERT_LABEL: Record<AlertLevel, string> = {
  CRITICAL: '긴급',
  WATCH: '경고',
  MONITOR: '주의',
  NORMAL: '정상',
};

const ALERT_PRIORITY: Record<AlertLevel, number> = {
  CRITICAL: 0,
  WATCH: 1,
  MONITOR: 2,
  NORMAL: 3,
};

interface AnalysisData {
  riskData: AnalyzedShip[];
  darkData: AnalyzedShip[];
  spoofData: AnalyzedShip[];
}

/**
 * 분석 결과 기반 deck.gl 레이어를 반환하는 훅.
 * AnalysisOverlay DOM Marker 대체 — GPU 렌더링으로 성능 향상.
 */
export function useAnalysisDeckLayers(
  analysisMap: Map<string, VesselAnalysisDto>,
  ships: Ship[],
  activeFilter: string | null,
  sizeScale: number = 1.0,
): Layer[] {
  const { fontScale } = useFontScale();
  const afs = fontScale.analysis;
  // 데이터 준비: ships 필터/정렬/슬라이스 — sizeScale 변경 시 재실행 안 됨
  const { riskData, darkData, spoofData } = useMemo<AnalysisData>(() => {
    if (analysisMap.size === 0) {
      return { riskData: [], darkData: [], spoofData: [] };
    }

    const analyzedShips: AnalyzedShip[] = ships
      .filter(s => analysisMap.has(s.mmsi))
      .map(s => {
        const dto = analysisMap.get(s.mmsi)!;
        return { ship: s, dto, alert: RISK_TO_ALERT[dto.algorithms.riskScore.level as RiskLevel] };
      });

    const riskData = analyzedShips
      .filter(({ alert }) => alert !== 'NORMAL')
      .sort((a, b) => ALERT_PRIORITY[a.alert] - ALERT_PRIORITY[b.alert])
      .slice(0, 100);

    const darkData = analyzedShips.filter(({ dto }) => dto.algorithms.darkVessel.isDark);

    const spoofData = analyzedShips.filter(
      ({ dto }) => dto.algorithms.gpsSpoofing.spoofingScore > 0.5,
    );

    return { riskData, darkData, spoofData };
  }, [analysisMap, ships, activeFilter]);

  // 레이어 생성: sizeScale 변경 시에만 재실행 (데이터 연산 없음)
  return useMemo<Layer[]>(() => {
    if (riskData.length === 0 && darkData.length === 0 && spoofData.length === 0) return [];

    const layers: Layer[] = [];

    // 위험도 원형 마커
    layers.push(
      new ScatterplotLayer<AnalyzedShip>({
        id: 'risk-markers',
        data: riskData,
        getPosition: (d) => [d.ship.lng, d.ship.lat],
        getRadius: (d) => (ALERT_SIZE[d.alert] ?? 12) * sizeScale,
        getFillColor: (d) => ALERT_RGBA[d.alert] ?? [100, 100, 100, 40],
        getLineColor: (d) => ALERT_RGBA_BORDER[d.alert] ?? [100, 100, 100, 200],
        stroked: true,
        filled: true,
        radiusUnits: 'pixels',
        lineWidthUnits: 'pixels',
        getLineWidth: 2,
        updateTriggers: { getRadius: [sizeScale] },
      }),
    );

    // 위험도 라벨 (선박명 + 위험도 등급)
    layers.push(
      new TextLayer<AnalyzedShip>({
        id: 'risk-labels',
        data: riskData,
        getPosition: (d) => [d.ship.lng, d.ship.lat],
        getText: (d) => {
          const label = ALERT_LABEL[d.alert] ?? d.alert;
          const name = d.ship.name || d.ship.mmsi;
          return `${name}\n${label} ${d.dto.algorithms.riskScore.score}`;
        },
        getSize: 10 * sizeScale * afs,
        updateTriggers: { getSize: [sizeScale] },
        getColor: (d) => ALERT_RGBA_BORDER[d.alert] ?? [200, 200, 200, 255],
        getTextAnchor: 'middle',
        getAlignmentBaseline: 'top',
        getPixelOffset: [0, 16],
        fontFamily: FONT_MONO,
        fontSettings: { sdf: true },
        outlineWidth: 3,
        outlineColor: [0, 0, 0, 255],
        billboard: false,
        characterSet: 'auto',
      }),
    );

    // 다크베셀 (activeFilter === 'darkVessel' 일 때만)
    if (activeFilter === 'darkVessel' && darkData.length > 0) {
      layers.push(
        new ScatterplotLayer<AnalyzedShip>({
          id: 'dark-vessel-markers',
          data: darkData,
          getPosition: (d) => [d.ship.lng, d.ship.lat],
          getRadius: 12 * sizeScale,
          getFillColor: [168, 85, 247, 40],
          getLineColor: [168, 85, 247, 200],
          stroked: true,
          filled: true,
          radiusUnits: 'pixels',
          lineWidthUnits: 'pixels',
          getLineWidth: 2,
          updateTriggers: { getRadius: [sizeScale] },
        }),
      );

      // 다크베셀 gap 라벨
      layers.push(
        new TextLayer<AnalyzedShip>({
          id: 'dark-vessel-labels',
          data: darkData,
          getPosition: (d) => [d.ship.lng, d.ship.lat],
          getText: (d) => {
            const gap = d.dto.algorithms.darkVessel.gapDurationMin;
            return gap > 0 ? `AIS 소실 ${Math.round(gap)}분` : 'DARK';
          },
          getSize: 10 * sizeScale * afs,
          updateTriggers: { getSize: [sizeScale] },
          getColor: [168, 85, 247, 255],
          getTextAnchor: 'middle',
          getAlignmentBaseline: 'top',
          getPixelOffset: [0, 14],
          fontFamily: FONT_MONO,
          fontSettings: { sdf: true },
        outlineWidth: 3,
          outlineColor: [0, 0, 0, 255],
          billboard: false,
          characterSet: 'auto',
        }),
      );
    }

    // GPS 스푸핑 라벨
    if (spoofData.length > 0) {
      layers.push(
        new TextLayer<AnalyzedShip>({
          id: 'spoof-labels',
          data: spoofData,
          getPosition: (d) => [d.ship.lng, d.ship.lat],
          getText: (d) => `GPS ${Math.round(d.dto.algorithms.gpsSpoofing.spoofingScore * 100)}%`,
          getSize: 10 * sizeScale * afs,
          getColor: [239, 68, 68, 255],
          getTextAnchor: 'start',
          getPixelOffset: [12, -8],
          fontFamily: FONT_MONO,
          fontWeight: 700,
          fontSettings: { sdf: true },
        outlineWidth: 3,
          outlineColor: [0, 0, 0, 255],
          billboard: false,
          characterSet: 'auto',
        }),
      );
    }

    return layers;
  }, [riskData, darkData, spoofData, sizeScale, activeFilter, afs]);
}
