import { ScatterplotLayer, PathLayer, TextLayer, PolygonLayer } from '@deck.gl/layers';
import type { Layer as DeckLayer } from '@deck.gl/core';
import type { MeasurePoint, MeasureResult } from '../../store/mapStore';
import { formatDistance, formatArea } from '../../utils/geo';

const CYAN = [6, 182, 212, 220] as const;
const CYAN_FILL = [6, 182, 212, 60] as const;
const WHITE = [255, 255, 255, 255] as const;

function midpoint(a: MeasurePoint, b: MeasurePoint): [number, number] {
  return [(a.lon + b.lon) / 2, (a.lat + b.lat) / 2];
}

export function centroid(pts: MeasurePoint[]): [number, number] {
  const n = pts.length;
  return [pts.reduce((s, p) => s + p.lon, 0) / n, pts.reduce((s, p) => s + p.lat, 0) / n];
}

function toPos(pt: MeasurePoint): [number, number] {
  return [pt.lon, pt.lat];
}

export function midpointOf(a: MeasurePoint, b: MeasurePoint): [number, number] {
  return midpoint(a, b);
}

export function buildMeasureLayers(
  measureInProgress: MeasurePoint[],
  measureMode: 'distance' | 'area' | null,
  measurements: MeasureResult[],
): DeckLayer[] {
  const layers: DeckLayer[] = [];

  // 진행 중인 점들
  if (measureInProgress.length > 0) {
    layers.push(
      new ScatterplotLayer({
        id: 'measure-in-progress-points',
        data: measureInProgress,
        getPosition: (d: MeasurePoint) => toPos(d),
        getRadius: 6,
        getFillColor: [...CYAN],
        getLineColor: [...WHITE],
        getLineWidth: 2,
        radiusUnits: 'pixels',
        lineWidthUnits: 'pixels',
        stroked: true,
      }),
    );

    if (measureInProgress.length >= 2) {
      layers.push(
        new PathLayer({
          id: 'measure-in-progress-path',
          data: [{ path: measureInProgress.map(toPos) }],
          getPath: (d: { path: [number, number][] }) => d.path,
          getColor: [...CYAN],
          getWidth: 2,
          widthUnits: 'pixels',
        }),
      );
    }

    // 면적 모드: 첫 점으로 돌아가는 점선 미리보기
    if (measureMode === 'area' && measureInProgress.length >= 3) {
      const first = measureInProgress[0];
      const last = measureInProgress[measureInProgress.length - 1];
      layers.push(
        new PathLayer({
          id: 'measure-area-close-preview',
          data: [{ path: [toPos(last), toPos(first)] }],
          getPath: (d: { path: [number, number][] }) => d.path,
          getColor: [6, 182, 212, 100],
          getWidth: 2,
          widthUnits: 'pixels',
        }),
      );
    }
  }

  // 완료된 측정 결과들
  for (const m of measurements) {
    if (m.mode === 'distance') {
      layers.push(
        new PathLayer({
          id: `${m.id}-line`,
          data: [{ path: m.points.map(toPos) }],
          getPath: (d: { path: [number, number][] }) => d.path,
          getColor: [...CYAN],
          getWidth: 3,
          widthUnits: 'pixels',
        }),
        new ScatterplotLayer({
          id: `${m.id}-points`,
          data: m.points,
          getPosition: (d: MeasurePoint) => toPos(d),
          getRadius: 6,
          getFillColor: [...CYAN],
          getLineColor: [...WHITE],
          getLineWidth: 2,
          radiusUnits: 'pixels',
          lineWidthUnits: 'pixels',
          stroked: true,
        }),
        new TextLayer({
          id: `${m.id}-label`,
          data: [{ position: midpoint(m.points[0], m.points[1]), text: formatDistance(m.value) }],
          getPosition: (d: { position: [number, number] }) => d.position,
          getText: (d: { text: string }) => d.text,
          getSize: 14,
          getColor: [255, 255, 255, 255],
          getTextAnchor: 'middle',
          getAlignmentBaseline: 'center',
          fontFamily: 'Pretendard, sans-serif',
          fontWeight: 700,
          outlineWidth: 3,
          outlineColor: [0, 0, 0, 200],
          billboard: true,
        }),
      );
    } else {
      layers.push(
        new PolygonLayer({
          id: `${m.id}-polygon`,
          data: [{ polygon: m.points.map(toPos) }],
          getPolygon: (d: { polygon: [number, number][] }) => d.polygon,
          getFillColor: [...CYAN_FILL],
          getLineColor: [...CYAN],
          getLineWidth: 2,
          lineWidthUnits: 'pixels',
          stroked: true,
          filled: true,
        }),
        new TextLayer({
          id: `${m.id}-label`,
          data: [{ position: centroid(m.points), text: formatArea(m.value) }],
          getPosition: (d: { position: [number, number] }) => d.position,
          getText: (d: { text: string }) => d.text,
          getSize: 14,
          getColor: [255, 255, 255, 255],
          getTextAnchor: 'middle',
          getAlignmentBaseline: 'center',
          fontFamily: 'Pretendard, sans-serif',
          fontWeight: 700,
          outlineWidth: 3,
          outlineColor: [0, 0, 0, 200],
          billboard: true,
        }),
      );
    }
  }

  return layers;
}
