/* global React, L */

const { useEffect: useEffectMap, useRef: useRefMap, useState: useStateMap } = React;

function TrajectoryMap({ trajectory, fromAirport, toAirport, t }) {
  const tx = t || ((k) => k);
  const mapEl = useRefMap(null);
  const mapRef = useRefMap(null);
  const layerRef = useRefMap(null);
  const natLayerRef = useRefMap(null);
  const [showNat, setShowNat] = useStateMap(false);
  const [natTracks, setNatTracks] = useStateMap([]);

  // init map once
  useEffectMap(() => {
    if (mapRef.current || !mapEl.current || typeof L === "undefined") return;

    const map = L.map(mapEl.current, {
      center: [30, 10],
      zoom: 2,
      zoomControl: true,
      worldCopyJump: true,
      attributionControl: true,
      scrollWheelZoom: true,
      minZoom: 2,
    });

    L.tileLayer("https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png", {
      attribution: "© OpenStreetMap · CARTO",
      subdomains: "abcd",
      maxZoom: 18,
    }).addTo(map);

    mapRef.current = map;
    setTimeout(() => map.invalidateSize(), 50);
    const ro = new ResizeObserver(() => map.invalidateSize());
    ro.observe(mapEl.current);
    return () => ro.disconnect();
  }, []);

  // fetch NAT tracks once on mount
  useEffectMap(() => {
    fetch("/nat-tracks?ocean=atlantic")
      .then((r) => r.ok ? r.json() : { tracks: [] })
      .then((data) => {
        const tracks = Array.isArray(data) ? data : (data.tracks || []);
        if (tracks.length) setNatTracks(tracks);
      })
      .catch(() => {});
  }, []);

  // draw / hide NAT layer when showNat or natTracks changes
  useEffectMap(() => {
    const map = mapRef.current;
    if (!map) return;
    if (natLayerRef.current) {
      map.removeLayer(natLayerRef.current);
      natLayerRef.current = null;
    }
    if (!showNat || !natTracks.length) return;

    const group = L.layerGroup();
    natTracks.forEach((track) => {
      if (!track.coords || track.coords.length < 2) return;
      L.polyline(track.coords, {
        color: "#1a6fbd",
        weight: 1.5,
        opacity: 0.55,
        dashArray: "6 8",
      }).bindTooltip(track.name || "NAT", { className: "penumbra-tip", sticky: true })
        .addTo(group);

      // direction arrow at midpoint
      const mid = track.coords[Math.floor(track.coords.length / 2)];
      if (mid) {
        const icon = L.divIcon({
          className: "",
          html: `<div class="nat-label">${track.name || ""}</div>`,
          iconAnchor: [20, 10],
        });
        L.marker(mid, { icon, interactive: false }).addTo(group);
      }
    });
    group.addTo(map);
    natLayerRef.current = group;
  }, [showNat, natTracks]);

  // redraw trajectory whenever it changes
  useEffectMap(() => {
    const map = mapRef.current;
    if (!map) return;

    if (layerRef.current) {
      map.removeLayer(layerRef.current);
      layerRef.current = null;
    }
    if (!trajectory) return;

    const group = L.layerGroup();

    // dashed path connecting samples
    const latlngs = trajectory.samples.map(s => [s.lat, s.lon]);
    L.polyline(latlngs, {
      color: "#0a0a0a",
      weight: 1.2,
      opacity: 0.45,
      dashArray: "3 5",
    }).addTo(group);

    // colored dots
    trajectory.samples.forEach((s) => {
      const icon = L.divIcon({
        className: "",
        html: `<div class="trajectory-dot ${s.risk}"></div>`,
        iconSize: [12, 12],
        iconAnchor: [6, 6],
      });
      const m = L.marker([s.lat, s.lon], { icon, interactive: true }).addTo(group);
      const tip = `
        <div class="tip-head">${formatLatLon(s.lat, s.lon)}</div>
        <div class="tip-row"><span class="k">${tx("tip_alt")}</span><span class="v">${Math.round(s.altFt).toLocaleString("fr-FR")} ft</span></div>
        <div class="tip-row"><span class="k">${tx("tip_dose")}</span><span class="v">${s.doseRate.toFixed(2)} µSv/h</span></div>
      `;
      m.bindTooltip(tip, {
        className: "penumbra-tip",
        direction: "top",
        offset: [0, -6],
        sticky: false,
      });
    });

    // airport pins
    if (fromAirport) {
      const fromIcon = L.divIcon({
        className: "",
        html: `<div class="airport-pin">${fromAirport.iata}</div>`,
        iconSize: [24, 24],
        iconAnchor: [12, 12],
      });
      L.marker([fromAirport.lat, fromAirport.lon], { icon: fromIcon, zIndexOffset: 1000 })
        .addTo(group)
        .bindTooltip(`${fromAirport.city} · ${fromAirport.name}`, { className: "penumbra-tip", direction: "top" });
    }
    if (toAirport) {
      const toIcon = L.divIcon({
        className: "",
        html: `<div class="airport-pin">${toAirport.iata}</div>`,
        iconSize: [24, 24],
        iconAnchor: [12, 12],
      });
      L.marker([toAirport.lat, toAirport.lon], { icon: toIcon, zIndexOffset: 1000 })
        .addTo(group)
        .bindTooltip(`${toAirport.city} · ${toAirport.name}`, { className: "penumbra-tip", direction: "top" });
    }

    group.addTo(map);
    layerRef.current = group;

    // fit bounds
    const bounds = L.latLngBounds(latlngs);
    map.fitBounds(bounds, { padding: [60, 60] });
  }, [trajectory, fromAirport, toAirport]);

  return (
    <>
      <div ref={mapEl} id="map"></div>
      {!trajectory && (
        <div className="map-empty">
          <div className="icon" aria-hidden="true">
            <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
              <path d="M21 16v-2l-8-5V3.5a1.5 1.5 0 0 0-3 0V9l-8 5v2l8-2.5V19l-2 1.5V22l3.5-1L15 22v-1.5L13 19v-5.5l8 2.5z"/>
            </svg>
          </div>
          <div className="text">{tx("map_empty")}</div>
        </div>
      )}
      <div className="map-controls">
        {natTracks.length > 0 && (
          <button
            className={"nat-toggle" + (showNat ? " active" : "")}
            onClick={() => setShowNat((v) => !v)}
            title={showNat ? tx("nat_toggle_hide") : tx("nat_toggle_show")}
          >
            <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M3 12h18M3 6l9-3 9 3M3 18l9 3 9-3"/>
            </svg>
            {tx("nat_label")}
          </button>
        )}
        {trajectory && (
          <div className="map-legend">
            <span className="item"><span className="swatch low"></span>{tx("legend_low")}</span>
            <span className="item"><span className="swatch mod"></span>{tx("legend_mod")}</span>
            <span className="item"><span className="swatch high"></span>{tx("legend_high")}</span>
          </div>
        )}
      </div>
    </>
  );
}

function formatLatLon(lat, lon) {
  const ns = lat >= 0 ? "N" : "S";
  const ew = lon >= 0 ? "E" : "O";
  return `${Math.abs(lat).toFixed(2)}°${ns} · ${Math.abs(lon).toFixed(2)}°${ew}`;
}

window.TrajectoryMap = TrajectoryMap;
