"use client";

import dynamic from "next/dynamic";
import { Vehicle } from "@/lib/api";
import { useMapsConfig } from "@/lib/useMapsConfig";
import { useLocale } from "@/i18n/LocaleProvider";
import { EmptyState } from "@/components/ui";

// mapbox-gl is ~250 kB; only pull it in when a map actually renders (client-only).
const MapboxFleetMap = dynamic(
  () => import("@/components/MapboxFleetMap").then((m) => m.MapboxFleetMap),
  { ssr: false, loading: () => <div className="h-full w-full animate-pulse rounded-card bg-surface-raised" /> },
);

/** What a dot's colour means. Operational status, not battery: see MapboxFleetMap. */
export type FleetTone = "available" | "inUse" | "lowBattery" | "maintenance" | "offline";

export const FLEET_COLORS: Record<FleetTone, string> = {
  available: "#22C55E",
  inUse: "#3B82F6",
  lowBattery: "#F59E0B",
  maintenance: "#A855F7",
  offline: "#6B7280",
};

/**
 * The dot colour for one vehicle.
 *
 * <p>Order matters. A vehicle that is OFFLINE and also low on battery is drawn as offline,
 * because the thing an operator must act on first is that it stopped reporting; a battery figure
 * from an hour ago is not a reason to send a van.
 */
export function fleetTone(v: Vehicle): FleetTone {
  switch (v.status) {
    case "OFFLINE":
      return "offline";
    case "MAINTENANCE":
      return "maintenance";
    case "IN_USE":
      return "inUse";
    case "LOW_BATTERY":
      return "lowBattery";
    default:
      return v.batteryPercent < 20 ? "lowBattery" : "available";
  }
}

/**
 * The fleet map, provider-agnostic at this boundary.
 *
 * <p>An absent map key is a supported state, not an error: the fleet list is still the complete
 * picture, so this renders an honest explanation rather than a dead grey tile.
 */
export function FleetMap({
  vehicles,
  selectedId,
  onSelect,
  onPickFrom,
  className = "h-full w-full overflow-hidden rounded-card border border-line",
}: {
  vehicles: Vehicle[];
  selectedId: string | null;
  onSelect: (id: string) => void;
  /** Members of a cluster that zooming can never separate, e.g. a depot at one coordinate. */
  onPickFrom: (ids: string[]) => void;
  className?: string;
}) {
  const { t } = useLocale();
  const { config, loading } = useMapsConfig();

  if (loading) {
    return <div className={`${className} animate-pulse bg-surface-raised`} />;
  }

  if (!config?.apiKey) {
    return (
      <div className={`${className} flex items-center justify-center p-6`}>
        <EmptyState
          icon={<span className="text-xl">🗺️</span>}
          title={t("fleetMap.noKeyTitle")}
          description={t("fleetMap.noKeyBody")}
        />
      </div>
    );
  }

  return (
    <MapboxFleetMap
      token={config.apiKey}
      vehicles={vehicles}
      selectedId={selectedId}
      onSelect={onSelect}
      onPickFrom={onPickFrom}
      // The cluster tooltip is raw HTML inside a mapbox popup, so its words cannot come from a
      // React component and are handed down already translated.
      labels={{
        vehicles: t("fleetMap.clusterVehicles"),
        needAttention: t("fleetMap.clusterAttention"),
      }}
      className={className}
    />
  );
}
