/**
 * Haversine distance utility.
 * Computes the great-circle distance between two points on Earth
 * using the haversine formula.
 */

const EARTH_RADIUS_KM = 6371;

/**
 * Convert degrees to radians.
 */
function toRadians(deg: number): number {
  return (deg * Math.PI) / 180;
}

/**
 * Calculate the distance (in km) between two geographic coordinates
 * using the haversine formula.
 *
 * @param lat1  Latitude of point 1 (degrees)
 * @param lng1  Longitude of point 1 (degrees)
 * @param lat2  Latitude of point 2 (degrees)
 * @param lng2  Longitude of point 2 (degrees)
 * @returns     Distance in kilometres, rounded to 2 decimal places
 */
export function haversineDistance(
  lat1: number,
  lng1: number,
  lat2: number,
  lng2: number,
): number {
  const dLat = toRadians(lat2 - lat1);
  const dLng = toRadians(lng2 - lng1);

  const a =
    Math.sin(dLat / 2) ** 2 +
    Math.cos(toRadians(lat1)) *
      Math.cos(toRadians(lat2)) *
      Math.sin(dLng / 2) ** 2;

  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

  return Math.round(EARTH_RADIUS_KM * c * 100) / 100;
}
