/** Map transform state */
export interface MapTransform {
  x: number;
  y: number;
  scale: number;
}

/**
 * Projection constants derived from the world-map-data.ts SVG (viewBox 0 0 1010 666).
 * Fitted via linear regression against geographic centroids of ~14 countries.
 *
 * Usage:
 *   const [x, y] = latlngToSvg(51.5, -0.12); // London → [473.6, 288.7]
 */
const LNG_SCALE = 2.8189; // SVG units per degree longitude
const LNG_OFFSET = 473.96; // SVG x at lng=0 (prime meridian)
const LAT_SCALE = -3.6337; // SVG units per degree latitude (negative = N is up)
const LAT_OFFSET = 475.84; // SVG y at lat=0 (equator)

/**
 * Convert geographic coordinates to SVG viewBox coordinates for the built-in world map.
 *
 * @param lat  Latitude  (-90 to 90,  positive = North)
 * @param lng  Longitude (-180 to 180, positive = East)
 * @returns    [x, y] in SVG viewBox space (0–1010 × 0–666)
 */
export function latlngToSvg(lat: number, lng: number): [number, number] {
  return [LNG_SCALE * lng + LNG_OFFSET, LAT_SCALE * lat + LAT_OFFSET];
}

/**
 * Convert SVG viewBox coordinates back to geographic lat/lng.
 * Inverse of `latlngToSvg`.
 */
export function svgToLatlng(svgX: number, svgY: number): [number, number] {
  return [(svgY - LAT_OFFSET) / LAT_SCALE, (svgX - LNG_OFFSET) / LNG_SCALE];
}

/** Build a quadratic bezier arc path string between two SVG points. */
export function arcPath(
  x1: number,
  y1: number,
  x2: number,
  y2: number,
  curvature = 0.25
): string {
  const mx = (x1 + x2) / 2;
  const my = (y1 + y2) / 2;
  const dx = x2 - x1;
  const dy = y2 - y1;
  // Control point perpendicular to the midpoint
  const cpx = mx - dy * curvature;
  const cpy = my + dx * curvature;
  return `M ${x1} ${y1} Q ${cpx} ${cpy} ${x2} ${y2}`;
}

/**
 * Convert waypoint SVG coords to viewport-relative pixel position.
 * Returns `fixed`-positioning values (relative to the viewport).
 */
export function svgCoordsToViewportPx(
  svgX: number,
  svgY: number,
  transform: MapTransform,
  containerEl: HTMLDivElement,
  viewBox: string
): { left: number; top: number } {
  const parts = viewBox.split(' ').map(Number);
  const vbW = parts[2] ?? 1010;
  const vbH = parts[3] ?? 666;
  const rect = containerEl.getBoundingClientRect();
  const scaleX = rect.width / vbW;
  const scaleY = rect.height / vbH;
  const originX = rect.width / 2;
  const originY = rect.height / 2;
  // Coords relative to container top-left
  const px =
    (svgX * scaleX - originX) * transform.scale + originX + transform.x;
  const py =
    (svgY * scaleY - originY) * transform.scale + originY + transform.y;
  // Add container's viewport offset to get fixed coords
  return { left: rect.left + px, top: rect.top + py };
}
