/**
 * Qibla direction calculation utilities.
 *
 * Computes the bearing (direction) from a user's location to the Kaaba in Mecca.
 * Also provides distance to Mecca using the haversine formula.
 *
 * Kaaba coordinates: 21.4225° N, 39.8262° E
 */

const KAABA_LAT = 21.4225;
const KAABA_LNG = 39.8262;

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

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

/**
 * Calculate the bearing (direction) from a location to the Kaaba in Mecca.
 *
 * Uses the standard great-circle bearing formula:
 *   θ = atan2(sin(Δλ)·cos(φ₂), cos(φ₁)·sin(φ₂) − sin(φ₁)·cos(φ₂)·cos(Δλ))
 *
 * @param lat  User's latitude (degrees)
 * @param lng  User's longitude (degrees)
 * @returns    Bearing in degrees clockwise from North (0–360)
 */
export function qiblaBearing(lat: number, lng: number): number {
  const φ1 = toRadians(lat);
  const φ2 = toRadians(KAABA_LAT);
  const Δλ = toRadians(KAABA_LNG - lng);

  const y = Math.sin(Δλ) * Math.cos(φ2);
  const x =
    Math.cos(φ1) * Math.sin(φ2) -
    Math.sin(φ1) * Math.cos(φ2) * Math.cos(Δλ);

  let bearing = toDegrees(Math.atan2(y, x));
  // Normalize to 0–360
  return (bearing + 360) % 360;
}

/**
 * Calculate the distance from a location to the Kaaba in Mecca.
 *
 * @param lat  User's latitude (degrees)
 * @param lng  User's longitude (degrees)
 * @returns    Distance in kilometres, rounded to 1 decimal place
 */
export function distanceToMecca(lat: number, lng: number): number {
  const EARTH_RADIUS_KM = 6371;
  const dLat = toRadians(KAABA_LAT - lat);
  const dLng = toRadians(KAABA_LNG - lng);

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

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

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

/**
 * Get a human-readable cardinal direction from a bearing.
 *
 * @param bearing  Bearing in degrees (0–360)
 * @returns        Cardinal direction string (e.g., "NE")
 */
export function bearingToDirection(bearing: number): string {
  const dirs = ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];
  const index = Math.round(bearing / 45) % 8;
  return dirs[index];
}

/**
 * Format distance in a human-readable way.
 */
export function formatDistance(km: number): string {
  if (km < 1) return `${Math.round(km * 1000)} m`;
  if (km < 100) return `${km.toFixed(1)} km`;
  return `${Math.round(km).toLocaleString()} km`;
}

export { KAABA_LAT, KAABA_LNG };
