import type { Site, VehicleMaster, Zone, ZoneId } from "@/lib/fleet/types";

/** Ray-casting point-in-polygon. polygon is [lat, lng][]. */
export function pointInPolygon(
  lat: number,
  lng: number,
  polygon: [number, number][],
): boolean {
  let inside = false;
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
    const [yi, xi] = polygon[i];
    const [yj, xj] = polygon[j];
    const intersect =
      yi > lat !== yj > lat &&
      lng < ((xj - xi) * (lat - yi)) / (yj - yi + Number.EPSILON) + xi;
    if (intersect) inside = !inside;
  }
  return inside;
}

export function getVehicleLatLng(vehicle: VehicleMaster): {
  lat: number;
  lng: number;
} {
  const [lng, lat] = vehicle.location.geometry.coordinates;
  return { lat: lat!, lng: lng! };
}

export function findZoneForVehicle(
  vehicle: VehicleMaster,
  sites: Site[],
): Zone | null {
  const { lat, lng } = getVehicleLatLng(vehicle);
  for (const site of sites) {
    for (const zone of site.zones) {
      if (pointInPolygon(lat, lng, zone.polygon)) return zone;
    }
  }
  return null;
}

export function isInExpectedZone(
  vehicle: VehicleMaster,
  sites: Site[],
): boolean {
  const zone = findZoneForVehicle(vehicle, sites);
  if (!zone) return false;
  return (
    zone.siteId === vehicle.expectedSiteId &&
    zone.id === vehicle.expectedZoneId
  );
}

export function dataAgeMinutes(timestamp: string, now = Date.now()): number {
  return (now - new Date(timestamp).getTime()) / 60_000;
}

export function isStale(
  timestamp: string,
  thresholdMinutes: number,
  now = Date.now(),
): boolean {
  return dataAgeMinutes(timestamp, now) > thresholdMinutes;
}

export function newestTelematicsTimestamp(vehicle: VehicleMaster): string {
  const stamps = [
    vehicle.odometer.timestamp,
    vehicle.health.timestamp,
    vehicle.exterior.timestamp,
    vehicle.availability.timestamp,
    vehicle.location.properties.timestamp,
    vehicle.battery?.timestamp,
    vehicle.fuel?.timestamp,
  ].filter(Boolean) as string[];
  return stamps.sort((a, b) => +new Date(b) - +new Date(a))[0]!;
}

export const ZONE_LABELS: Record<ZoneId, string> = {
  verkauf: "Verkauf",
  werkstatt: "Werkstatt",
  hof: "Hof",
  auslieferung: "Auslieferung",
};
