// Cross-dock terminal directory — every facility_xdock entity in the
// graph, grouped by city and carrier. Used as a standalone page at
// /#/xdocks AND as an embed component (CrossDocksByCity) inside the
// LA report card and the dashboard Carriers tab.
//
// Cross-dock = LTL/TL freight handoff points. The site has them as
// entity rows with type='facility_xdock', parent_id pointing to the
// carrier, and primary_city_id pointing to the city. Each clickable
// pin routes to /#/terminal/<slug> — that's the per-facility page
// where the tip line and per-dock intel live.

const { useState: useStateXD, useEffect: useEffectXD, useRef: useRefXD, useMemo: useMemoXD } = React;

// =============================================================
// Reusable embed — given a cityId, render the xdocks for that city.
// Used inside LA report card + dashboard.
// =============================================================
function CrossDocksByCity({ cityId, onNav }) {
  const [docks, setDocks] = useStateXD([]);
  const [carrierLookup, setCarrierLookup] = useStateXD({});
  const [loading, setLoading] = useStateXD(true);

  useEffectXD(() => {
    if (!cityId || !window.SI_DB || !window.SI_DB.raw) { setLoading(false); return; }
    let alive = true;
    (async () => {
      try {
        const [terms, carriers] = await Promise.all([
          window.SI_DB.raw.select(
            "entities",
            `select=id,slug,name,parent_id,lat,lng,address,primary_city_id&type=eq.facility_xdock&primary_city_id=eq.${encodeURIComponent(cityId)}&order=name.asc`
          ),
          window.SI_DB.raw.select("entities", "select=id,name,slug&type=eq.carrier"),
        ]);
        if (!alive) return;
        const lookup = {};
        (carriers || []).forEach(c => { lookup[c.id] = { name: c.name, slug: c.slug }; });
        setCarrierLookup(lookup);
        setDocks(Array.isArray(terms) ? terms : []);
      } catch {} finally { if (alive) setLoading(false); }
    })();
    return () => { alive = false; };
  }, [cityId]);

  if (loading) {
    return <div style={{ color: "var(--ink-soft)", fontSize: 14, padding: "12px 0" }}>Loading cross-docks…</div>;
  }
  if (docks.length === 0) {
    return (
      <div style={{
        color: "var(--ink-soft)", fontSize: 14, padding: "16px 0",
        fontStyle: "italic",
      }}>
        No carrier hubs tracked in this metro yet — the atlas is still filling in.
      </div>
    );
  }

  // Group by carrier for readability
  const byCarrier = {};
  docks.forEach(d => {
    const k = d.parent_id || "independent";
    if (!byCarrier[k]) byCarrier[k] = [];
    byCarrier[k].push(d);
  });
  const order = Object.entries(byCarrier).sort((a, b) => b[1].length - a[1].length);

  return (
    <div className="xdc-embed">
      <style>{`
        .xdc-embed { display: flex; flex-direction: column; gap: 16px; }
        .xdc-grp-h {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.16em;
          text-transform: uppercase; color: var(--ink-soft);
          padding-bottom: 6px; border-bottom: 1px solid var(--rule); margin-bottom: 8px;
          display: flex; justify-content: space-between; align-items: baseline;
        }
        .xdc-grp-count { font-size: 10px; letter-spacing: 0.06em; }
        .xdc-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 8px; }
        .xdc-tile {
          background: var(--paper); border: 1px solid var(--rule); border-radius: 6px;
          padding: 12px 14px; cursor: pointer; text-align: left;
          font-family: inherit; transition: border-color 0.15s, transform 0.15s;
          display: flex; flex-direction: column; gap: 4px;
        }
        .xdc-tile:hover { border-color: var(--ink); transform: translateY(-1px); }
        .xdc-name {
          font-family: var(--font-serif); font-size: 15px; letter-spacing: -0.005em;
          color: var(--ink); line-height: 1.3;
        }
        .xdc-addr {
          font-size: 12px; color: var(--ink-soft); line-height: 1.4;
        }
      `}</style>
      {order.map(([cid, list]) => {
        const carrier = carrierLookup[cid];
        const label = carrier ? carrier.name : "Independent";
        return (
          <div key={cid} className="xdc-grp">
            <div className="xdc-grp-h">
              <span>{label}</span>
              <span className="xdc-grp-count">{list.length} terminal{list.length === 1 ? "" : "s"}</span>
            </div>
            <div className="xdc-list">
              {list.map(d => (
                <button key={d.id} className="xdc-tile"
                        onClick={() => { window.location.hash = `#/terminal/${d.slug}`; }}>
                  <span className="xdc-name">{d.name}</span>
                  {d.address && <span className="xdc-addr">{d.address}</span>}
                </button>
              ))}
            </div>
          </div>
        );
      })}
    </div>
  );
}

window.CrossDocksByCity = CrossDocksByCity;

// =============================================================
// Standalone page — every cross-dock terminal in the graph, with
// search, city filter, and a Leaflet map.
// =============================================================
function CrossDocksPage({ onNav }) {
  const [docks, setDocks] = useStateXD([]);
  const [carrierLookup, setCarrierLookup] = useStateXD({});
  const [cityLookup, setCityLookup] = useStateXD({});
  const [loading, setLoading] = useStateXD(true);
  const [filter, setFilter] = useStateXD({ city: null, carrier: null, q: "" });

  const mapRef = useRefXD(null);
  const elRef = useRefXD(null);
  const layerRef = useRefXD(null);

  useEffectXD(() => {
    if (!window.SI_DB || !window.SI_DB.raw) { setLoading(false); return; }
    let alive = true;
    (async () => {
      try {
        const [terms, carriers, cities] = await Promise.all([
          window.SI_DB.raw.select(
            "entities",
            "select=id,slug,name,parent_id,lat,lng,address,primary_city_id&type=eq.facility_xdock&order=name.asc&limit=10000"
          ),
          window.SI_DB.raw.select("entities", "select=id,name,slug&type=eq.carrier"),
          window.SI_DB.raw.select("cities", "select=id,name,state&order=name.asc"),
        ]);
        if (!alive) return;
        const cl = {};
        (carriers || []).forEach(c => { cl[c.id] = { name: c.name, slug: c.slug }; });
        const cm = {};
        (cities || []).forEach(c => { cm[c.id] = c; });
        setCarrierLookup(cl);
        setCityLookup(cm);
        setDocks(Array.isArray(terms) ? terms : []);
      } catch {} finally { if (alive) setLoading(false); }
    })();
    return () => { alive = false; };
  }, []);

  // Mount map once
  useEffectXD(() => {
    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: "© OpenStreetMap · © CARTO",
        subdomains: "abcd", maxZoom: 13, noWrap: true }
    ).addTo(map);
    mapRef.current = map;
    setTimeout(() => map.invalidateSize(), 80);
    return () => { map.remove(); mapRef.current = null; };
  }, []);

  const filtered = useMemoXD(() => {
    return docks.filter(d => {
      if (filter.city && d.primary_city_id !== filter.city) return false;
      if (filter.carrier && d.parent_id !== filter.carrier) return false;
      if (filter.q.trim()) {
        const q = filter.q.toLowerCase();
        const carrier = carrierLookup[d.parent_id];
        if (!(d.name || "").toLowerCase().includes(q) &&
            !(d.address || "").toLowerCase().includes(q) &&
            !(carrier?.name || "").toLowerCase().includes(q)) return false;
      }
      return true;
    });
  }, [docks, filter, carrierLookup]);

  // Rebuild markers when filter changes
  useEffectXD(() => {
    const map = mapRef.current;
    if (!map || !window.L) return;
    if (layerRef.current && map.hasLayer(layerRef.current)) map.removeLayer(layerRef.current);
    const valid = filtered.filter(d => d.lat != null && d.lng != null);
    const cluster = window.L.markerClusterGroup
      ? window.L.markerClusterGroup({ chunkedLoading: true, maxClusterRadius: 50 })
      : window.L.layerGroup();
    valid.forEach(d => {
      const carrier = carrierLookup[d.parent_id];
      const html = `<span style="display:block;width:11px;height:11px;border-radius:50%;background:#7c3aed;border:1.5px solid #fff;box-shadow:0 0 0 1px rgba(0,0,0,0.25)"></span>`;
      const icon = window.L.divIcon({
        className: "xdc-pin", html,
        iconSize: [14, 14], iconAnchor: [7, 7],
      });
      const m = window.L.marker([d.lat, d.lng], { icon, riseOnHover: true });
      const carLine = carrier ? `<div style="font-family:Helvetica;font-weight:700;text-transform:uppercase;letter-spacing:0.05em;font-size:10px;color:#7c3aed;margin-bottom:4px">${carrier.name}</div>` : "";
      const addrLine = d.address ? `<div style="font-size:12px;color:#666;margin-top:2px">${d.address}</div>` : "";
      m.bindPopup(`
        <div style="font-family:system-ui;font-size:12px;line-height:1.4;min-width:180px">
          ${carLine}
          <div style="font-weight:600;font-size:14px">${(d.name || "Cross-dock").replace(/'/g,"&#39;")}</div>
          ${addrLine}
          <div style="margin-top:8px"><a href="#/terminal/${d.slug}"
            style="display:inline-block;padding:4px 10px;border:1px solid #7c3aed;border-radius:3px;color:#7c3aed;text-decoration:none;font-family:Helvetica;font-size:11px;font-weight:600;letter-spacing:0.04em;text-transform:uppercase">Open terminal page →</a></div>
        </div>
      `);
      cluster.addLayer(m);
    });
    cluster.addTo(map);
    layerRef.current = cluster;
    if (valid.length >= 2) {
      try {
        map.fitBounds(window.L.latLngBounds(valid.map(v => [v.lat, v.lng])).pad(0.08));
      } catch {}
    }
  }, [filtered, carrierLookup]);

  // Group filtered docks by city for the list view
  const byCityList = useMemoXD(() => {
    const grouped = {};
    filtered.forEach(d => {
      const k = d.primary_city_id || "_unmapped";
      if (!grouped[k]) grouped[k] = [];
      grouped[k].push(d);
    });
    return Object.entries(grouped).sort((a, b) => b[1].length - a[1].length);
  }, [filtered]);

  const cityOptions = useMemoXD(() => {
    const s = new Set();
    docks.forEach(d => d.primary_city_id && s.add(d.primary_city_id));
    return Array.from(s).map(id => cityLookup[id]).filter(Boolean).sort((a, b) => a.name.localeCompare(b.name));
  }, [docks, cityLookup]);
  const carrierOptions = useMemoXD(() => {
    const counts = {};
    docks.forEach(d => { if (d.parent_id) counts[d.parent_id] = (counts[d.parent_id] || 0) + 1; });
    return Object.entries(counts)
      .map(([id, n]) => ({ id, n, name: carrierLookup[id]?.name || "Unknown" }))
      .sort((a, b) => b.n - a.n);
  }, [docks, carrierLookup]);

  return (
    <div className="xdp-page">
      <style>{`
        .xdp-page { background: var(--paper); padding-bottom: 96px; min-height: 100vh; }
        .xdp-hero { max-width: 1200px; margin: 0 auto; padding: 56px 24px 24px; }
        .xdp-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;
        }
        .xdp-back:hover { color: var(--ink); }
        .xdp-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;
        }
        .xdp-mark .dot {
          display: inline-block; width: 8px; height: 8px; border-radius: 50%;
          background: oklch(0.55 0.18 295);
        }
        .xdp-title {
          font-family: var(--font-serif); font-size: 56px; line-height: 1.04;
          letter-spacing: -0.028em; margin: 0 0 16px;
        }
        .xdp-title em { font-style: italic; color: oklch(0.50 0.18 295); }
        .xdp-dek { font-size: 16px; line-height: 1.55; color: var(--ink-soft); margin: 0; max-width: 760px; }
        @media (max-width: 700px) { .xdp-title { font-size: 38px; } }

        .xdp-controls {
          max-width: 1200px; margin: 24px auto 0; padding: 0 24px;
          display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 12px;
        }
        @media (max-width: 800px) { .xdp-controls { grid-template-columns: 1fr; } }
        .xdp-search, .xdp-select {
          padding: 10px 14px; border: 1px solid var(--rule); border-radius: 6px;
          background: #fff; font-family: inherit; font-size: 14px; color: var(--ink);
          outline: none; width: 100%;
        }
        .xdp-search:focus, .xdp-select:focus { border-color: var(--ink); }

        .xdp-counts {
          max-width: 1200px; margin: 12px auto 12px; padding: 0 24px;
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.06em;
          color: var(--ink-soft);
        }

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

        .xdp-list { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
        .xdp-city-h {
          font-family: var(--font-serif); font-size: 22px; letter-spacing: -0.015em;
          margin: 32px 0 12px; padding-bottom: 8px; border-bottom: 1px solid var(--rule);
          display: flex; justify-content: space-between; align-items: baseline;
        }
        .xdp-city-meta {
          font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.08em;
          color: var(--ink-soft); text-transform: uppercase;
        }
        .xdp-city-grid {
          display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
          gap: 10px;
        }
        .xdp-tile {
          background: #fff; border: 1px solid var(--rule); border-radius: 6px;
          padding: 14px 16px; cursor: pointer; text-align: left;
          font-family: inherit; transition: border-color 0.15s, transform 0.15s;
          display: flex; flex-direction: column; gap: 4px;
        }
        .xdp-tile:hover { border-color: var(--ink); transform: translateY(-1px); }
        .xdp-tile-cl {
          font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em;
          text-transform: uppercase; color: oklch(0.50 0.18 295); font-weight: 700;
        }
        .xdp-tile-name {
          font-family: var(--font-serif); font-size: 15px; letter-spacing: -0.005em;
          color: var(--ink); line-height: 1.3;
        }
        .xdp-tile-addr {
          font-size: 12px; color: var(--ink-soft); line-height: 1.4;
        }
      `}</style>

      <section className="xdp-hero">
        <button className="xdp-back" onClick={() => onNav("drivers")}>← Back to The Yard</button>
        <div className="xdp-mark"><span className="dot" /> Carrier hub atlas</div>
        <h1 className="xdp-title">Where the major <em>carriers</em> run their networks.</h1>
        <p className="xdp-dek">
          A directory of carrier-owned terminal hubs and sortation centers —
          UPS, FedEx, Amazon, Old Dominion, Saia, Estes, and the rest. These
          are <strong>private network nodes</strong>, not third-party drop-and-hook
          or transload yards. Use it to see how a carrier's footprint actually
          looks in the city you ship from. Search by name, address, or carrier;
          filter by metro.
        </p>
        <p className="xdp-dek" style={{ marginTop: 10, fontSize: 13, color: "var(--ink-soft)" }}>
          Looking for an <strong>independent cross-dock</strong> that handles drop, hook,
          transload, lumper, repack, or driver assist? That's a separate
          directory we're building — <a href="mailto:hello@shippingclarity.com?subject=Independent%20cross-dock%20directory" style={{ color: "var(--ink)", borderBottom: "1px solid var(--rule)" }}>tell us where you'd want one listed</a>.
        </p>
      </section>

      <div className="xdp-controls">
        <input
          className="xdp-search"
          type="search"
          placeholder="Search by name, address, or carrier…"
          value={filter.q}
          onChange={e => setFilter(f => ({ ...f, q: e.target.value }))}
        />
        <select className="xdp-select"
          value={filter.city || ""}
          onChange={e => setFilter(f => ({ ...f, city: e.target.value || null }))}
        >
          <option value="">All cities</option>
          {cityOptions.map(c => (
            <option key={c.id} value={c.id}>{c.name}, {c.state}</option>
          ))}
        </select>
        <select className="xdp-select"
          value={filter.carrier || ""}
          onChange={e => setFilter(f => ({ ...f, carrier: e.target.value || null }))}
        >
          <option value="">All carriers</option>
          {carrierOptions.map(c => (
            <option key={c.id} value={c.id}>{c.name} ({c.n})</option>
          ))}
        </select>
      </div>

      <div className="xdp-counts">
        {loading
          ? "Loading…"
          : <>{filtered.length.toLocaleString()} terminal{filtered.length === 1 ? "" : "s"}
              {filter.city || filter.carrier || filter.q ? <> · of {docks.length.toLocaleString()} total</> : null}</>
        }
      </div>

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

      <div className="xdp-list">
        {byCityList.map(([cid, list]) => {
          const city = cityLookup[cid];
          const cityLabel = city ? `${city.name}, ${city.state}` : "Other";
          return (
            <div key={cid} className="xdp-city-grp">
              <div className="xdp-city-h">
                <span>{cityLabel}</span>
                <span className="xdp-city-meta">{list.length} terminal{list.length === 1 ? "" : "s"}</span>
              </div>
              <div className="xdp-city-grid">
                {list.map(d => {
                  const carrier = carrierLookup[d.parent_id];
                  return (
                    <button key={d.id} className="xdp-tile"
                            onClick={() => { window.location.hash = `#/terminal/${d.slug}`; }}>
                      {carrier && <span className="xdp-tile-cl">{carrier.name}</span>}
                      <span className="xdp-tile-name">{d.name}</span>
                      {d.address && <span className="xdp-tile-addr">{d.address}</span>}
                    </button>
                  );
                })}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

window.CrossDocksPage = CrossDocksPage;
