import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export type Coordinates = {
  lat: number;
  lng: number;
};

export function cn(...inputs: ClassValue[]): string {
  return twMerge(clsx(inputs));
}

export function formatCoordinate(value: number, locale = "en-US"): string {
  const formatter = new Intl.NumberFormat(locale, {
    minimumFractionDigits: 3,
    maximumFractionDigits: 3,
  });
  return formatter.format(value);
}

export function formatRelativeTime(dateIso: string, locale = "en-US"): string {
  const date = new Date(dateIso);
  const now = new Date();
  const diff = Math.max(0, now.getTime() - date.getTime());

  const seconds = Math.floor(diff / 1000);
  const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });

  if (seconds < 60) {
    return rtf.format(-seconds, "second");
  }

  const minutes = Math.floor(seconds / 60);
  if (minutes < 60) {
    return rtf.format(-minutes, "minute");
  }

  const hours = Math.floor(minutes / 60);
  if (hours < 24) {
    return rtf.format(-hours, "hour");
  }

  const days = Math.floor(hours / 24);
  if (days < 7) {
    return rtf.format(-days, "day");
  }

  const weeks = Math.floor(days / 7);
  return rtf.format(-weeks, "week");
}

export function formatTimestamp(dateIso: string, locale = "en-US"): string {
  const date = new Date(dateIso);
  return new Intl.DateTimeFormat(locale, {
    month: "short",
    day: "numeric",
    hour: "numeric",
    minute: "2-digit",
  }).format(date);
}

const EARTH_RADIUS_KM = 6371;

export function distanceInKm(a: Coordinates, b: Coordinates): number {
  const lat1 = toRadians(a.lat);
  const lat2 = toRadians(b.lat);
  const deltaLat = toRadians(b.lat - a.lat);
  const deltaLng = toRadians(b.lng - a.lng);

  const haversine =
    Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
    Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLng / 2) * Math.sin(deltaLng / 2);

  const c = 2 * Math.atan2(Math.sqrt(haversine), Math.sqrt(1 - haversine));
  return EARTH_RADIUS_KM * c;
}

function toRadians(value: number): number {
  return (value * Math.PI) / 180;
}
