// worldmap.jsx — Interactive world map (real geographic outline)
const { useMemo: useMemoWM, useState: useStateWM, useEffect: useEffectWM } = React;

// Equirectangular projection onto a 900×500 viewBox.
// Lat range clipped to ±60° so the visible world fills the canvas
// (kills empty Antarctic strip and tightens density of pins).
const MAP_W = 900, MAP_H = 500;
const LAT_TOP = 78, LAT_BOTTOM = -56;
function proj(lon, lat) {
  const x = (lon + 180) / 360 * MAP_W;
  const y = (LAT_TOP - lat) / (LAT_TOP - LAT_BOTTOM) * MAP_H;
  return [x, y];
}
function projXY(coords) { return proj(coords.lon, coords.lat); }

// Convert a GeoJSON-style ring [[lon,lat], ...] to an SVG path "d" string.
// Splits the ring wherever it crosses the antimeridian (Δlon > 180°) so
// countries like Russia and Fiji don't draw a seam straight across the map.
function ringToPath(ring) {
  let d = "";
  let prevLon = null;
  for (let i = 0; i < ring.length; i++) {
    const lon = ring[i][0];
    const [x, y] = proj(lon, ring[i][1]);
    const jump = prevLon !== null && Math.abs(lon - prevLon) > 180;
    d += (i === 0 || jump ? "M" : "L") + x.toFixed(1) + "," + y.toFixed(1);
    prevLon = lon;
  }
  return d;
}
function featureToPath(geom) {
  if (!geom) return "";
  if (geom.type === "Polygon") {
    return geom.coordinates.map(ringToPath).join(" ");
  }
  if (geom.type === "MultiPolygon") {
    return geom.coordinates.map(polys => polys.map(ringToPath).join(" ")).join(" ");
  }
  return "";
}

function WorldMap() {
  const mapThemes = useMemoWM(() => ["All Themes", ...new Set(MAP_PROJECTS.map(p => p.theme))], []);
  const [theme, setTheme] = useStateWM("All Themes");
  const visible = useMemoWM(() => theme === "All Themes" ? MAP_PROJECTS : MAP_PROJECTS.filter(p => p.theme === theme), [theme]);
  const [activeId, setActiveId] = useStateWM(MAP_PROJECTS[0].id);
  const active = MAP_PROJECTS.find(p => p.id === activeId) || MAP_PROJECTS[0];

  // Fetch world geometry once (TopoJSON → GeoJSON features → SVG paths).
  const [countryPaths, setCountryPaths] = useStateWM([]);
  useEffectWM(() => {
    let cancelled = false;
    (async () => {
      try {
        if (!window.topojson) {
          console.warn("topojson-client not loaded");
          return;
        }
        const url = (window.__resources && window.__resources.worldAtlas)
          || "https://cdn.jsdelivr.net/npm/world-atlas@2.0.2/countries-110m.json";
        const topo = await fetch(url).then(r => r.json());
        const fc = window.topojson.feature(topo, topo.objects.countries);
        const paths = fc.features
          .filter(f => f.properties && f.properties.name !== "Antarctica")
          .map(f => ({ name: f.properties.name, d: featureToPath(f.geometry) }));
        if (!cancelled) setCountryPaths(paths);
      } catch (e) {
        console.warn("World atlas load failed", e && e.message ? e.message : e);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  useEffectWM(() => {
    if (theme !== "All Themes" && active.theme !== theme) {
      setActiveId(visible[0]?.id ?? MAP_PROJECTS[0].id);
    }
  }, [theme]);

  const themeCounts = useMemoWM(() => {
    const m = {};
    mapThemes.forEach(t => { m[t] = t === "All Themes" ? MAP_PROJECTS.length : MAP_PROJECTS.filter(p => p.theme === t).length; });
    return m;
  }, [mapThemes]);

  const idx = MAP_PROJECTS.indexOf(active);
  const dc = proj(-77.04, 38.91); // Washington, D.C.
  const activeXY = projXY(active.coords);

  return (
    <section className="section on-buff" id="map">
      <div className="container">
        <div className="section-head reveal">
          <div>
            <span className="eyebrow">Where We Work · Recent Cohorts</span>
            <h2 className="headline" style={{marginTop: 20}}>
              Twelve cities. <em>One discipline.</em>
            </h2>
          </div>
          <div className="head-meta">
            Selected projects · 2024–2025<br />
            ▸ click a pin to read the brief
          </div>
        </div>

        <div className="region-tabs reveal">
          {mapThemes.map(r => (
            <button key={r}
              className={`region-tab ${theme === r ? "active" : ""}`}
              onClick={() => setTheme(r)}
            >
              {r}<span className="num">{String(themeCounts[r]).padStart(2,"0")}</span>
            </button>
          ))}
        </div>

        <div className="map-stage reveal">
          <div className="world-map">
            <div className="map-tag map-tag-tl">▸ Capstone Network · 2024–25</div>
            <div className="map-tag map-tag-tr">{visible.length} projects</div>
            <svg viewBox={`0 0 ${MAP_W} ${MAP_H}`} preserveAspectRatio="xMidYMid meet">
              {/* land */}
              <g>
                {countryPaths.map((c, i) => (
                  <path key={c.name + i} d={c.d}
                    fill="rgba(214,191,145,0.18)"
                    stroke="rgba(214,191,145,0.55)"
                    strokeWidth="0.5"
                    strokeLinejoin="round" />
                ))}
              </g>

              {/* connection: D.C. → active */}
              {(() => {
                // curved arc: midpoint perpendicular offset
                const [x1, y1] = dc, [x2, y2] = activeXY;
                const mx = (x1 + x2) / 2, my = (y1 + y2) / 2;
                const dx = x2 - x1, dy = y2 - y1;
                const dist = Math.hypot(dx, dy);
                const nx = -dy / dist, ny = dx / dist;
                const off = Math.min(dist * 0.18, 80);
                const cx = mx + nx * off, cy = my + ny * off;
                return (
                  <g>
                    <path d={`M${x1},${y1} Q${cx},${cy} ${x2},${y2}`}
                      stroke="#D6BF91" strokeWidth="1" fill="none"
                      strokeDasharray="3 3" opacity="0.75" />
                    <circle cx={x1} cy={y1} r="3.4" fill="#0075C8" stroke="#F6F1E8" strokeWidth="0.8" />
                    <text x={x1 + 6} y={y1 - 6} fill="#D6BF91" fontFamily="DM Sans" fontSize="9" fontWeight="600" letterSpacing="2">D.C.</text>
                  </g>
                );
              })()}

              {/* pins */}
              {MAP_PROJECTS.map(p => {
                const dim = theme !== "All Themes" && p.theme !== theme;
                const [px, py] = projXY(p.coords);
                return (
                  <g key={p.id}
                    className={`world-pin ${active.id === p.id ? "active" : ""}`}
                    style={{ opacity: dim ? 0.25 : 1 }}
                    onClick={() => setActiveId(p.id)}
                  >
                    <circle className="ring" cx={px} cy={py} />
                    <circle className="dot" cx={px} cy={py} r="4.5" />
                    {active.id === p.id && (
                      <text x={px + 9} y={py - 8} fill="#F6F1E8"
                        fontFamily="DM Sans" fontSize="10" fontWeight="600" letterSpacing="1.6">
                        {p.city.toUpperCase()}
                      </text>
                    )}
                  </g>
                );
              })}
            </svg>
          </div>

          <div className="map-info">
            <div className="country">
              <span>{active.country} · {active.city}</span>
              <span>{String(idx + 1).padStart(2,"0")}/{String(MAP_PROJECTS.length).padStart(2,"0")}</span>
            </div>
            <div className="project">{active.title}</div>
            <div className="client-line">
              Client: <b>{active.partner}</b>
            </div>
            <div className="blurb">{active.blurb}</div>
            <div className="info-meta">
              <div>
                <span>Country</span>
                <span>{active.country}</span>
              </div>
              <div>
                <span>Theme</span>
                <span>{active.theme}</span>
              </div>
              <div>
                <span>Cohort year</span>
                <span>{active.year}</span>
              </div>
              <div>
                <span>Team size</span>
                <span>{4 + (active.id % 3)} students</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>
  );
}

window.WorldMap = WorldMap;
