import { useEffect } from "react";
import {
  MapContainer,
  TileLayer,
  Marker,
  Polyline,
  Tooltip,
  useMap,
} from "react-leaflet";
import L from "leaflet";
import "leaflet/dist/leaflet.css";

// This component is loaded via React.lazy from the route planner page so that
// Leaflet + react-leaflet land in a separate code-split chunk and never weigh
// down the main admin bundle.

export interface RouteMapStop {
  id: string;
  stopOrder: number;
  latitude: number;
  longitude: number;
  clientName: string;
}

interface RouteMapProps {
  stops: RouteMapStop[];
  primaryColor: string;
}

/** A numbered teardrop pin rendered as an inline-SVG divIcon (no image assets). */
function numberedIcon(order: number, color: string): L.DivIcon {
  return L.divIcon({
    className: "route-stop-pin",
    html: `<div style="position:relative;width:28px;height:40px">
      <svg width="28" height="40" viewBox="0 0 28 40" xmlns="http://www.w3.org/2000/svg">
        <path d="M14 0C6.27 0 0 6.27 0 14c0 9.5 14 26 14 26s14-16.5 14-26C28 6.27 21.73 0 14 0z" fill="${color}" stroke="#ffffff" stroke-width="1.5"/>
      </svg>
      <span style="position:absolute;top:5px;left:0;width:28px;text-align:center;color:#fff;font-size:13px;font-weight:700;font-family:system-ui,sans-serif">${order}</span>
    </div>`,
    iconSize: [28, 40],
    iconAnchor: [14, 40],
    tooltipAnchor: [0, -34],
  });
}

/** Keeps the viewport framed around all stops whenever the route changes. */
function FitBounds({ stops }: { stops: RouteMapStop[] }) {
  const map = useMap();
  useEffect(() => {
    if (stops.length === 0) return;
    const latlngs = stops.map((s) => [s.latitude, s.longitude] as [number, number]);
    if (latlngs.length === 1) {
      map.setView(latlngs[0]!, 14);
    } else {
      map.fitBounds(L.latLngBounds(latlngs), { padding: [40, 40] });
    }
  }, [map, stops]);
  return null;
}

export default function RouteMap({ stops, primaryColor }: RouteMapProps) {
  // Fallback centre (London) only used briefly before FitBounds runs or when the
  // route has no geocoded stops.
  const center: [number, number] = stops[0]
    ? [stops[0].latitude, stops[0].longitude]
    : [51.505, -0.09];
  const line = stops.map((s) => [s.latitude, s.longitude] as [number, number]);

  return (
    <MapContainer
      center={center}
      zoom={12}
      scrollWheelZoom
      style={{ height: "100%", width: "100%", borderRadius: 8 }}
    >
      <TileLayer
        attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
      />
      {line.length >= 2 && (
        <Polyline positions={line} color={primaryColor} weight={4} opacity={0.7} />
      )}
      {stops.map((s) => (
        <Marker
          key={s.id}
          position={[s.latitude, s.longitude]}
          icon={numberedIcon(s.stopOrder, primaryColor)}
        >
          <Tooltip>
            {s.stopOrder}. {s.clientName}
          </Tooltip>
        </Marker>
      ))}
      <FitBounds stops={stops} />
    </MapContainer>
  );
}
