/* ===== maps.jsx — real OpenStreetMap site plan (Leaflet) =====
   Shared by the field app and the admin console. Pins = boreholes,
   coloured by workflow stage by default, or via `colorOf(b)`.
   Optional `onPinClick(b)` (selection mode) + `selected` Set of ids. */

function BhMap({ projectId, height = 260, showRoute = true, colorOf, onPinClick, selected }) {
  const elRef = useRef(null);
  const mapRef = useRef(null);
  const layerRef = useRef(null);
  const fittedRef = useRef(null);
  const clickRef = useRef(onPinClick);
  clickRef.current = onPinClick;

  const pid = projectId && projectId !== "all" ? projectId : null;
  const items = (window.BOREHOLE_ITEMS || []).filter(
    (b) => (!pid || b.project === pid) && b.lat != null && b.lon != null
  );
  const colorFn = colorOf || ((b) => STAGES[Math.min(b.stage || 0, STAGES.length - 1)].hex);
  const selKey = selected ? [...selected].sort().join(",") : "";
  // re-render markers only when the relevant set changes
  const sig = items.map((b) => b.key + ":" + colorFn(b)).join("|") + "·" + (pid || "all") + "·" + selKey;

  useEffect(() => {
    if (!window.L || !elRef.current) return;
    if (!mapRef.current) {
      // NB: zoom/fade animations rely on CSS transitions which do not run in
      // the preview iframe — animated fitBounds never commits. Disable them.
      mapRef.current = L.map(elRef.current, {
        scrollWheelZoom: false, zoomControl: true,
        zoomAnimation: false, fadeAnimation: false, markerZoomAnimation: false,
      });
      L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
        maxZoom: 19, attribution: "&copy; OpenStreetMap",
      }).addTo(mapRef.current);
      layerRef.current = L.layerGroup().addTo(mapRef.current);
      mapRef.current.setView([58.8, 25.2], 7);
    }
    const lg = layerRef.current;
    lg.clearLayers();

    if (showRoute) {
      (window.PROJECTS || []).forEach((p) => {
        if (pid && p.id !== pid) return;
        if (p.routeLine && p.routeLine.length > 1) {
          L.polyline(p.routeLine, { color: "#22285c", weight: 3, opacity: 0.35, dashArray: "6 7" }).addTo(lg);
        }
      });
    }

    const pts = [];
    items.forEach((b) => {
      const st = STAGES[Math.min(b.stage || 0, STAGES.length - 1)];
      const hex = colorFn(b);
      const isSel = selected && selected.has(b.id);
      pts.push([b.lat, b.lon]);
      const mk = L.circleMarker([b.lat, b.lon], {
        radius: isSel ? 9 : 6.5,
        color: isSel ? "#111827" : "#ffffff",
        weight: isSel ? 2.5 : 1.6,
        fillColor: hex, fillOpacity: 1,
      });
      if (clickRef.current) {
        mk.bindTooltip(b.id, { direction: "top", offset: [0, -6] });
        mk.on("click", () => clickRef.current && clickRef.current(b));
      } else {
        mk.bindPopup(
          "<div class='bhmap-pop'><b>" + b.id + "</b> · " + b.type +
          "<br>" + (b.projectCode || "") +
          "<br><span style='color:" + st.hex + "'>●</span> " + st.name +
          (b.depth ? "<br>" + (+b.depth).toFixed(2) + " m" : "") + "</div>"
        );
      }
      mk.addTo(lg);
    });

    // fit only when the project scope changes (not on every selection toggle)
    const scope = pid || "all";
    const needFit = fittedRef.current !== scope && pts.length > 0;
    if (needFit) {
      mapRef.current.invalidateSize();   // refresh cached container size first
      mapRef.current.fitBounds(pts, { padding: [30, 30], maxZoom: 13, animate: false });
    }
    const t = setTimeout(() => {
      if (!mapRef.current) return;
      mapRef.current.invalidateSize();
      if (needFit && pts.length) {
        mapRef.current.fitBounds(pts, { padding: [30, 30], maxZoom: 13, animate: false });
        fittedRef.current = scope;       // mark done only after the post-layout fit ran
      }
    }, 180);
    return () => clearTimeout(t);
  }, [sig, height]);

  useEffect(() => () => {           // unmount: tear the map down
    if (mapRef.current) { mapRef.current.remove(); mapRef.current = null; }
  }, []);

  if (!window.L) {
    return (
      <div className="bhmap bhmap-off" style={{ height }}>
        <span className="mono">Kaart vajab võrguühendust (OpenStreetMap)</span>
      </div>
    );
  }
  return <div className="bhmap" ref={elRef} style={{ height }}></div>;
}

Object.assign(window, { BhMap });
