// Weigh-stations map — every state weigh / inspection station we've
// pulled from OpenStreetMap, color-coded by state, clustered for
// readability. Locations are static; live status (open/bypass/closed)
// is the Phase-2 add when state 511 ingest lands.

const { useState: useStateWS, useEffect: useEffectWS, useRef: useRefWS, useMemo: useMemoWS } = React;

function WeighStationsPage({ onNav }) {
  const [stations, setStations] = useStateWS([]);
  const [loading, setLoading] = useStateWS(true);
  const [filter, setFilter] = useStateWS({ state: null, q: "" });
  const mapRef = useRefWS(null);
  const elRef = useRefWS(null);
  const layerRef = useRefWS(null);
  const clusterRef = useRefWS(null);

  useEffectWS(() => {
    let alive = true;
    if (!window.SI_DB || !window.SI_DB.raw) { setLoading(false); return; }
    (async () => {
      try {
        // Pull in chunks of 1000 (PostgREST default cap) until the page
        // returns less than a full page. Total US set runs ~700–1500.
        const all = [];
        let offset = 0;
        const PAGE = 1000;
        while (alive) {
          const rows = await window.SI_DB.raw.select(
            "weigh_stations",
            `select=id,name,state,lat,lng,operator,direction&order=state.asc,name.asc&limit=${PAGE}&offset=${offset}`
          );
          if (!Array.isArray(rows) || rows.length === 0) break;
          all.push(...rows);
          if (rows.length < PAGE) break;
          offset += PAGE;
        }
        if (!alive) return;
        setStations(all);
      } catch {} finally {
        if (alive) setLoading(false);
      }
    })();
    return () => { alive = false; };
  }, []);

  // Mount the map once.
  useEffectWS(() => {
    if (!elRef.current || !window.L || mapRef.current) return;
    const map = window.L.map(elRef.current, {
      zoomControl: true, scrollWheelZoom: false,
      attributionControl: true, worldCopyJump: false,
      minZoom: 3, maxZoom: 13, fadeAnimation: false,
    }).setView([39.5, -98.5], 4);
    window.L.tileLayer(
      "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
      { attribution: "OSM weigh-station data · © OpenStreetMap · © CARTO",
        subdomains: "abcd", maxZoom: 13, noWrap: true }
    ).addTo(map);
    mapRef.current = map;
    setTimeout(() => map.invalidateSize(), 80);
    return () => { map.remove(); mapRef.current = null; };
  }, []);

  // (Re)build the marker layer when the rows or filter change. Use
  // markercluster for legibility — 1000+ pins on a continental map is
  // unreadable without it.
  useEffectWS(() => {
    const map = mapRef.current;
    if (!map || !window.L) return;
    if (clusterRef.current && map.hasLayer(clusterRef.current)) {
      map.removeLayer(clusterRef.current);
    }
    if (layerRef.current && map.hasLayer(layerRef.current)) {
      map.removeLayer(layerRef.current);
    }
    const filtered = stations.filter(s => {
      if (filter.state && s.state !== filter.state) return false;
      if (filter.q.trim()) {
        const q = filter.q.toLowerCase();
        if (!(s.name || "").toLowerCase().includes(q) &&
            !(s.operator || "").toLowerCase().includes(q)) return false;
      }
      return s.lat != null && s.lng != null;
    });
    const cluster = window.L.markerClusterGroup
      ? window.L.markerClusterGroup({ chunkedLoading: true, maxClusterRadius: 60 })
      : window.L.layerGroup();
    filtered.forEach(s => {
      const html = `<span style="display:block;width:11px;height:11px;border-radius:2px;background:#0F4DA8;border:1.5px solid #fff;box-shadow:0 0 0 1px rgba(0,0,0,0.25);transform:rotate(45deg)"></span>`;
      const icon = window.L.divIcon({
        className: "ws-pin", html,
        iconSize: [15, 15], iconAnchor: [7.5, 7.5],
      });
      const m = window.L.marker([s.lat, s.lng], { icon, riseOnHover: true });
      const dirLine = s.direction ? `<div style="font-size:11px;color:#666;margin-top:2px">${s.direction}</div>` : "";
      const opLine = s.operator ? `<div style="font-size:12px;margin-top:4px">${s.operator}</div>` : "";
      const dirUrl = `https://www.google.com/maps/dir/?api=1&destination=${s.lat},${s.lng}&travelmode=driving`;
      m.bindPopup(`
        <div style="font-family:system-ui;font-size:12px;line-height:1.4;min-width:180px">
          <div style="font-family:Helvetica;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;font-size:10px;color:#0F4DA8;margin-bottom:4px">
            ⚖ ${s.state || "Weigh Station"}
          </div>
          <div style="font-weight:600;font-size:14px">${(s.name || "Weigh station").replace(/'/g,"&#39;")}</div>
          ${opLine}${dirLine}
          <div style="margin-top:8px"><a href="${dirUrl}" target="_blank" rel="noopener noreferrer"
            style="display:inline-block;padding:4px 10px;border:1px solid #0F4DA8;border-radius:3px;color:#0F4DA8;text-decoration:none;font-family:Helvetica;font-size:11px;font-weight:600;letter-spacing:0.04em;text-transform:uppercase">Directions →</a></div>
        </div>
      `);
      cluster.addLayer(m);
    });
    cluster.addTo(map);
    clusterRef.current = cluster;
    if (filtered.length >= 2) {
      try {
        map.fitBounds(window.L.latLngBounds(filtered.map(f => [f.lat, f.lng])).pad(0.08));
      } catch {}
    } else if (filtered.length === 1) {
      map.setView([filtered[0].lat, filtered[0].lng], 9);
    }
  }, [stations, filter.state, filter.q]);

  const stateOptions = useMemoWS(() => {
    const s = new Set();
    stations.forEach(r => r.state && s.add(r.state));
    return Array.from(s).sort();
  }, [stations]);
  const filteredCount = useMemoWS(() => {
    return stations.filter(s => {
      if (filter.state && s.state !== filter.state) return false;
      if (filter.q.trim()) {
        const q = filter.q.toLowerCase();
        if (!(s.name || "").toLowerCase().includes(q) &&
            !(s.operator || "").toLowerCase().includes(q)) return false;
      }
      return true;
    }).length;
  }, [stations, filter.state, filter.q]);

  return (
    <div className="ws-page">
      <style>{`
        .ws-page { background: var(--paper); padding-bottom: 96px; min-height: 100vh; }
        .ws-hero {
          max-width: 1200px; margin: 0 auto; padding: 56px 24px 24px;
        }
        .ws-back {
          display: inline-flex; align-items: center; gap: 6px;
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em;
          text-transform: uppercase; color: var(--ink-soft);
          background: transparent; border: 0; cursor: pointer;
          padding: 0 0 16px;
        }
        .ws-back:hover { color: var(--ink); }
        .ws-mark {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.32em;
          text-transform: uppercase; color: var(--ink-soft); margin-bottom: 14px;
          display: inline-flex; align-items: center; gap: 10px;
        }
        .ws-mark .dot {
          display: inline-block; width: 8px; height: 8px; border-radius: 50%;
          background: oklch(0.55 0.18 145);
        }
        .ws-title {
          font-family: var(--font-serif); font-size: 56px; line-height: 1.04;
          letter-spacing: -0.028em; margin: 0 0 16px;
        }
        .ws-title em { font-style: italic; color: var(--red, oklch(0.50 0.16 250)); }
        .ws-dek {
          font-size: 16px; line-height: 1.55; color: var(--ink-soft); margin: 0;
          max-width: 760px;
        }
        @media (max-width: 700px) { .ws-title { font-size: 38px; } }

        .ws-controls {
          max-width: 1200px; margin: 24px auto 16px; padding: 0 24px;
          display: flex; gap: 12px; flex-wrap: wrap; align-items: center;
        }
        .ws-search {
          flex: 1; min-width: 240px;
          padding: 10px 14px; border: 1px solid var(--rule); border-radius: 6px;
          background: #fff; font-family: inherit; font-size: 14px; color: var(--ink);
          outline: none;
        }
        .ws-search:focus { border-color: var(--ink); }
        .ws-state-row {
          display: flex; gap: 6px; flex-wrap: wrap; max-width: 100%; overflow-x: auto;
        }
        .ws-state-btn {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
          padding: 6px 10px; border: 1px solid var(--rule); border-radius: 4px;
          background: #fff; cursor: pointer; color: var(--ink-soft);
          text-transform: uppercase;
        }
        .ws-state-btn:hover { color: var(--ink); border-color: var(--ink-soft); }
        .ws-state-btn.is-active {
          background: var(--ink); color: #fff; border-color: var(--ink);
        }

        .ws-counts {
          max-width: 1200px; margin: 0 auto 12px; padding: 0 24px;
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em;
          color: var(--ink-soft);
          display: flex; justify-content: space-between; align-items: baseline;
        }

        .ws-map-wrap {
          max-width: 1200px; margin: 0 auto; padding: 0 24px;
        }
        .ws-map {
          width: 100%; height: 600px; border-radius: 8px;
          border: 1px solid var(--rule); overflow: hidden;
          background: var(--paper-2);
        }
        @media (max-width: 700px) { .ws-map { height: 480px; } }

        .ws-foot {
          max-width: 1200px; margin: 28px auto 0; padding: 0 24px;
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.04em;
          color: var(--ink-soft); line-height: 1.7; max-width: 800px; font-style: italic;
        }
      `}</style>

      <section className="ws-hero">
        <button className="ws-back" onClick={() => onNav("drivers")}>← Back to The Yard</button>
        <div className="ws-mark"><span className="dot" /> Weigh stations</div>
        <h1 className="ws-title">Every <em>scale house</em> on your route.</h1>
        <p className="ws-dek">
          State weigh and inspection stations across the lower 48 + DC, with
          one-tap directions. Search by name or filter by state. Live
          open / bypass / closed status is on the way — for now,
          assume operating hours per state DOT.
        </p>
      </section>

      <div className="ws-controls">
        <input
          className="ws-search"
          type="search"
          placeholder="Search by name or operator…"
          value={filter.q}
          onChange={e => setFilter(f => ({ ...f, q: e.target.value }))}
        />
        <button
          className={`ws-state-btn ${filter.state == null ? "is-active" : ""}`}
          onClick={() => setFilter(f => ({ ...f, state: null }))}
        >All</button>
        <div className="ws-state-row">
          {stateOptions.map(s => (
            <button key={s}
              className={`ws-state-btn ${filter.state === s ? "is-active" : ""}`}
              onClick={() => setFilter(f => ({ ...f, state: f.state === s ? null : s }))}
            >{s}</button>
          ))}
        </div>
      </div>

      <div className="ws-counts">
        <span>
          {loading
            ? "Loading…"
            : <>{filteredCount.toLocaleString()} {filter.state ? `${filter.state} ` : ""}stations
                {filter.state || filter.q ? <> · of {stations.length.toLocaleString()} total</> : null}</>
          }
        </span>
        <span>{stations.length.toLocaleString()} pinned</span>
      </div>

      <div className="ws-map-wrap">
        <div className="ws-map" ref={elRef} />
      </div>

      <p className="ws-foot">
        Coverage is refreshed periodically. Live status (open / bypass /
        closed) varies by state and isn't included here yet — when you see a
        sign that says CLOSED but the pin says open, the sign wins. Don't
        rely on this map for legal compliance — your ELD log and the
        scale-house signal at the entrance are the controlling sources.
      </p>
    </div>
  );
}

window.WeighStationsPage = WeighStationsPage;
