import { IconLayer, TextLayer } from '@deck.gl/layers';
import type { VesselPosition } from '@/types/vessel';

export interface VesselLegendItem {
  code: string;
  type: string;
  color: string;
}

export const VESSEL_LEGEND: VesselLegendItem[] = [
  { code: '000020', type: '어선', color: '#f97316' },
  { code: '000021', type: '함정', color: '#64748b' },
  { code: '000022', type: '여객선', color: '#a855f7' },
  { code: '000023', type: '화물선', color: '#22c55e' },
  { code: '000024', type: '유조선', color: '#ef4444' },
  { code: '000025', type: '관공선', color: '#3b82f6' },
  { code: '000027', type: '기타', color: '#94a3b8' },
  { code: '000028', type: '부이', color: '#eab308' },
];

const DEFAULT_VESSEL_COLOR = '#94a3b8';

const SHIP_KIND_COLORS: Record<string, string> = VESSEL_LEGEND.reduce(
  (acc, { code, color }) => {
    acc[code] = color;
    return acc;
  },
  {} as Record<string, string>,
);

const SHIP_KIND_LABELS: Record<string, string> = VESSEL_LEGEND.reduce(
  (acc, { code, type }) => {
    acc[code] = type;
    return acc;
  },
  {} as Record<string, string>,
);

export function getShipKindColor(shipKindCode?: string): string {
  if (!shipKindCode) return DEFAULT_VESSEL_COLOR;
  return SHIP_KIND_COLORS[shipKindCode] ?? DEFAULT_VESSEL_COLOR;
}

export function getShipKindLabel(shipKindCode?: string): string | undefined {
  if (!shipKindCode) return undefined;
  return SHIP_KIND_LABELS[shipKindCode];
}

function makeTriangleSvg(color: string, isAccident: boolean): string {
  const opacity = isAccident ? '1' : '0.85';
  const glowOpacity = isAccident ? '0.9' : '0.75';
  const svgStr = [
    '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="20" viewBox="0 0 16 20">',
    '<defs><filter id="g" x="-50%" y="-50%" width="200%" height="200%">',
    '<feGaussianBlur stdDeviation="1.2"/></filter></defs>',
    `<polygon points="8,0 15,20 1,20" fill="${color}" opacity="${glowOpacity}" filter="url(#g)"/>`,
    `<polygon points="8,1 14,19 2,19" fill="${color}" opacity="${opacity}" stroke="${color}" stroke-width="0.5"/>`,
    '</svg>',
  ].join('');
  return `data:image/svg+xml;base64,${btoa(svgStr)}`;
}

export interface VesselLayerHandlers {
  onClick?: (vessel: VesselPosition, coordinate: [number, number]) => void;
  onHover?: (vessel: VesselPosition | null, x: number, y: number) => void;
}

export function buildVesselLayers(
  vessels: VesselPosition[],
  handlers: VesselLayerHandlers = {},
  zoom?: number,
) {
  if (!vessels.length) return [];
  const showLabels = zoom === undefined || zoom > 9;

  const iconLayer = new IconLayer({
    id: 'vessel-icons',
    data: vessels,
    getPosition: (d: VesselPosition) => [d.lon, d.lat],
    getIcon: (d: VesselPosition) => {
      const color = getShipKindColor(d.shipKindCode);
      const isAccident = (d.status ?? '').includes('사고');
      return {
        url: makeTriangleSvg(color, isAccident),
        width: 16,
        height: 20,
        anchorX: 8,
        anchorY: 10,
      };
    },
    getSize: 16,
    getAngle: (d: VesselPosition) => -(d.heading ?? d.cog ?? 0),
    sizeUnits: 'pixels',
    sizeScale: 1,
    pickable: true,
    onClick: (info: { object?: VesselPosition; coordinate?: number[] }) => {
      if (info.object && info.coordinate && handlers.onClick) {
        handlers.onClick(info.object, [info.coordinate[0], info.coordinate[1]]);
      }
    },
    onHover: (info: { object?: VesselPosition; x?: number; y?: number }) => {
      if (!handlers.onHover) return;
      if (info.object && info.x !== undefined && info.y !== undefined) {
        handlers.onHover(info.object, info.x, info.y);
      } else {
        handlers.onHover(null, 0, 0);
      }
    },
    updateTriggers: {
      getIcon: [vessels],
      getAngle: [vessels],
    },
  });

  const labelLayer = new TextLayer({
    id: 'vessel-labels',
    data: vessels.filter((v) => v.shipNm),
    visible: showLabels,
    getPosition: (d: VesselPosition) => [d.lon, d.lat],
    getText: (d: VesselPosition) => d.shipNm ?? '',
    getSize: 11,
    getColor: [255, 255, 255, 240],
    getPixelOffset: [0, -14],
    billboard: true,
    sizeUnits: 'pixels' as const,
    characterSet: 'auto',
    fontSettings: { sdf: true },
    outlineColor: [0, 0, 0, 230],
    outlineWidth: 2,
  });

  return [iconLayer, labelLayer];
}
