import type { GeoJsonPolygon } from "@/lib/api-types";

const DEFAULT_WIDTH = 400;
const DEFAULT_HEIGHT = 280;
const DEFAULT_PADDING = 48;

type Position = [number, number];

function getPolygonBounds(ring: Position[]) {
  const lngs = ring.map((c) => c[0]);
  const lats = ring.map((c) => c[1]);
  return {
    minLng: Math.min(...lngs),
    maxLng: Math.max(...lngs),
    minLat: Math.min(...lats),
    maxLat: Math.max(...lats),
  };
}

export function projectPolygonPoint(
  lng: number,
  lat: number,
  bounds: ReturnType<typeof getPolygonBounds>,
  width = DEFAULT_WIDTH,
  height = DEFAULT_HEIGHT,
  padding = DEFAULT_PADDING,
): { x: number; y: number } {
  const lngRange = bounds.maxLng - bounds.minLng || 0.001;
  const latRange = bounds.maxLat - bounds.minLat || 0.001;
  const innerW = width - padding * 2;
  const innerH = height - padding * 2;
  return {
    x: padding + ((lng - bounds.minLng) / lngRange) * innerW,
    y: padding + (1 - (lat - bounds.minLat) / latRange) * innerH,
  };
}

/** Project GeoJSON polygon coordinates into SVG path for static map overlay. */
export function polygonToSvgPath(
  polygon: GeoJsonPolygon,
  width = DEFAULT_WIDTH,
  height = DEFAULT_HEIGHT,
  padding = DEFAULT_PADDING,
): { path: string; viewBox: string; bounds: ReturnType<typeof getPolygonBounds> | null } {
  const ring = polygon.coordinates[0] as Position[] | undefined;
  if (!ring?.length) {
    return { path: "", viewBox: `0 0 ${width} ${height}`, bounds: null };
  }

  const bounds = getPolygonBounds(ring);
  const points = ring.map(([lng, lat]) => {
    const { x, y } = projectPolygonPoint(lng, lat, bounds, width, height, padding);
    return `${x.toFixed(1)},${y.toFixed(1)}`;
  });

  return {
    path: `M ${points.join(" L ")} Z`,
    viewBox: `0 0 ${width} ${height}`,
    bounds,
  };
}

export function formatCoordinates(lat: number, lng: number): string {
  const latDir = lat >= 0 ? "N" : "S";
  const lngDir = lng >= 0 ? "E" : "W";
  return `${Math.abs(lat).toFixed(4)}° ${latDir}, ${Math.abs(lng).toFixed(4)}° ${lngDir}`;
}
