/* ============================================================
   FOOTER EXTRAS — OSM distance card + live CO2 footprint
   ============================================================ */
const { useState: fUS, useEffect: fUE, useRef: fUR } = React;

const GRAVELOTTE = { lat: 49.14639, lon: 6.01417 }; // Gravelotte, Moselle (FR)

/* ---------- tiny stylized icons ---------- */
function FIcon({ kind }) {
  let body = null;
  if (kind === "cloud") {
    body = <path d="M9 22c-3 0-5-2-5-4.6 0-2.4 1.8-4.3 4.2-4.5C9 9.3 11.6 7.4 14.6 7.4c3.4 0 6.2 2.5 6.7 5.7 2.6.2 4.7 2.3 4.7 5 0 2.8-2.3 3.9-5 3.9H9z" />;
  } else if (kind === "car") {
    body = <g><path d="M5 20v3a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1v-4l2.2-6.4A3 3 0 0 1 9 10h14a3 3 0 0 1 2.8 1.9L28 18v5a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-3H5z" /><path d="M6.5 12l-1.3 4h21.6l-1.3-4a1.2 1.2 0 0 0-1.1-.8H7.6a1.2 1.2 0 0 0-1.1.8z" fill="#0b0b0a" /><circle cx="8.5" cy="20" r="2.2" fill="#0b0b0a" /><circle cx="23.5" cy="20" r="2.2" fill="#0b0b0a" /></g>;
  } else if (kind === "jet") {
    body = <path d="M2 17l5-1 4.5-5.2L9 4l2.4-.2 6 5.6 6.8-1.4c1.4-.3 2.6.2 2.8 1.2.2 1-.7 1.9-2.1 2.3l-6.6 2 .2 7.2-1.9.7-2.4-6.2-5 1.6L9 22l-1.7.4-.3-3.2L4 18.6 2 17z" />;
  } else if (kind === "beer") {
    body = <g><path d="M7 5h13v4h2.5A3.5 3.5 0 0 1 26 12.5v3A3.5 3.5 0 0 1 22.5 19H20v3a3 3 0 0 1-3 3h-7a3 3 0 0 1-3-3V5z" /><path d="M20 11.5v5.5h2.3a1.5 1.5 0 0 0 1.5-1.5v-2.5a1.5 1.5 0 0 0-1.5-1.5H20z" fill="#0b0b0a" /><rect x="10" y="9" width="2" height="11" rx="1" fill="#0b0b0a" /><rect x="14.5" y="9" width="2" height="11" rx="1" fill="#0b0b0a" /></g>;
  }
  return <svg className="ficon" viewBox="0 0 32 32" fill="currentColor" aria-hidden="true">{body}</svg>;
}

/* ---------- formatting ---------- */
function fmtMass(g, U) {
  if (g >= 1000) return (g / 1000).toFixed(2) + " " + U.kg;
  if (g >= 1) return g.toFixed(2) + " " + U.g;
  return (g * 1000).toFixed(0) + " " + U.mg;
}
function fmtDist(km, U) {
  if (km >= 1) return km.toFixed(2) + " " + U.km;
  if (km >= 0.001) return (km * 1000).toFixed(0) + " " + U.m;
  return (km * 1e6).toFixed(0) + " " + U.mm;
}
function fmtVol(l, U) {
  if (l >= 1) return l.toFixed(2) + " " + U.l;
  return (l * 1000).toFixed(0) + " " + U.ml;
}
function fmtDur(s) {
  const h = Math.floor(s / 3600);
  const m = Math.round((s % 3600) / 60);
  return h ? `${h} h ${String(m).padStart(2, "0")}` : `${m} min`;
}

/* ============================================================
   DISTANCE — OSM dark map, Gravelotte -> entered address
   ============================================================ */
function Distance({ lang }) {
  const L = window.I18N[lang];
  const D = L.dist;
  const langRef = fUR(lang); langRef.current = lang;

  const mapEl = fUR(null);
  const map = fUR(null);
  const routeLayer = fUR(null);
  const endMarker = fUR(null);
  const [q, setQ] = fUS("");
  const [state, setState] = fUS("idle"); // idle | loading | done | error | notfound
  const [result, setResult] = fUS(null); // {durText, distText, place}

  fUE(() => {
    if (!window.L || map.current) return;
    const m = window.L.map(mapEl.current, {
      center: [GRAVELOTTE.lat, GRAVELOTTE.lon],
      zoom: 9, zoomControl: true, scrollWheelZoom: false, attributionControl: true,
    });
    window.L.tileLayer("https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png", {
      attribution: '© OpenStreetMap · © CARTO', subdomains: "abcd", maxZoom: 19,
    }).addTo(m);
    const start = window.L.divIcon({ className: "pin pin-start", html: '<span></span>', iconSize: [16, 16] });
    window.L.marker([GRAVELOTTE.lat, GRAVELOTTE.lon], { icon: start })
      .addTo(m).bindTooltip(window.I18N[langRef.current].dist.from, { permanent: false, direction: "top" });
    map.current = m;
    setTimeout(() => m.invalidateSize(), 200);
    return () => { m.remove(); map.current = null; };
  }, []);

  async function search(e) {
    if (e) e.preventDefault();
    const term = q.trim();
    if (!term || state === "loading") return;
    setState("loading"); setResult(null);
    try {
      const geo = await fetch(
        "https://nominatim.openstreetmap.org/search?format=json&limit=1&accept-language=" +
        langRef.current + "&q=" + encodeURIComponent(term),
        { headers: { "Accept": "application/json" } }
      ).then((r) => r.json());
      if (!geo || !geo.length) { setState("notfound"); return; }
      const dest = { lat: parseFloat(geo[0].lat), lon: parseFloat(geo[0].lon), name: geo[0].display_name };
      const osrm = await fetch(
        `https://router.project-osrm.org/route/v1/driving/${GRAVELOTTE.lon},${GRAVELOTTE.lat};${dest.lon},${dest.lat}?overview=full&geometries=geojson`
      ).then((r) => r.json());
      if (!osrm || osrm.code !== "Ok" || !osrm.routes || !osrm.routes.length) { setState("error"); return; }
      const route = osrm.routes[0];
      const coords = route.geometry.coordinates.map((c) => [c[1], c[0]]);
      const m = map.current;
      if (routeLayer.current) m.removeLayer(routeLayer.current);
      if (endMarker.current) m.removeLayer(endMarker.current);
      routeLayer.current = window.L.polyline(coords, { color: "#f4f3ef", weight: 3, opacity: 0.95, dashArray: "1 7", lineCap: "round" }).addTo(m);
      const endIcon = window.L.divIcon({ className: "pin pin-end", html: "<span></span>", iconSize: [16, 16] });
      endMarker.current = window.L.marker([dest.lat, dest.lon], { icon: endIcon }).addTo(m);
      m.fitBounds(routeLayer.current.getBounds(), { padding: [40, 40] });
      const short = dest.name.split(",").slice(0, 3).join(",");
      setResult({
        durText: fmtDur(route.duration),
        distText: (route.distance / 1000).toFixed(0) + " " + L.units.km,
        place: short,
      });
      setState("done");
    } catch (err) {
      setState("error");
    }
  }

  return (
    <section className="section wrap" id="distance">
      <div className="sec-head">
        <h2>{D.title[0]}<br />{D.title[1]}</h2>
        <span className="count">{D.kicker}</span>
      </div>
      <div className="dist-grid">
        <div className="dist-panel reveal">
          <p className="dist-lead">{D.lead}</p>
          <form className="dist-form" onSubmit={search}>
            <input
              type="text" value={q} onChange={(e) => setQ(e.target.value)}
              placeholder={D.placeholder} aria-label={D.placeholder} data-cursor="↵" />
            <button type="submit" data-cursor="→" data-cursor-solid disabled={state === "loading"}>
              {state === "loading" ? D.loading : D.button}
            </button>
          </form>
          {state === "notfound" && <p className="dist-msg err">{D.notFound}</p>}
          {state === "error" && <p className="dist-msg err">{D.error}</p>}
          {state === "idle" && <p className="dist-msg">{D.hint}</p>}
          {state === "done" && result && (
            <div className="dist-result">
              <div className="dist-readout">
                <span className="dist-num">{result.durText}</span>
                <span className="dist-unit">{D.byCar} · {result.distText}</span>
              </div>
              <div className="dist-route">
                <span className="dr-a">{D.from}</span>
                <span className="dr-line"></span>
                <span className="dr-b">{result.place}</span>
              </div>
            </div>
          )}
        </div>
        <div className="dist-map-wrap reveal">
          <div ref={mapEl} className="dist-map"></div>
        </div>
      </div>
    </section>
  );
}

/* ============================================================
   FOOTPRINT — live CO2 estimate of the visit
   ============================================================ */
function bytesLoaded() {
  let transfer = 0, body = 0;
  try {
    const nav = performance.getEntriesByType("navigation")[0];
    if (nav) { transfer += nav.transferSize || 0; body += nav.encodedBodySize || 0; }
    for (const r of performance.getEntriesByType("resource")) {
      transfer += r.transferSize || 0; body += r.encodedBodySize || 0;
    }
  } catch (e) {}
  return Math.max(transfer, body, 1_600_000);
}

function Footprint({ lang }) {
  const L = window.I18N[lang];
  const C = L.co2;
  const [grams, setGrams] = fUS(0);
  const t0 = fUR(Date.now());

  fUE(() => {
    const tick = () => {
      const mb = bytesLoaded() / 1e6;
      const secs = (Date.now() - t0.current) / 1000;
      // sustainable-web-design-ish: ~0.5 g CO2 per MB transferred + a sliver of device/idle energy over time
      const g = mb * 0.5 + secs * 0.0009;
      setGrams(g);
    };
    tick();
    const id = setInterval(tick, 1000);
    return () => clearInterval(id);
  }, []);

  const U = L.units;
  const carKm = grams / 120;        // ~120 g CO2 / km, small car
  const jetKm = grams / 2000;       // ~2 kg CO2 / km, private jet (per pax)
  const beerL = grams / 500;        // ~0.5 kg CO2 / L brewed

  const items = [
    { icon: "car", val: fmtDist(carKm, U), label: C.car },
    { icon: "jet", val: fmtDist(jetKm, U), label: C.jet },
    { icon: "beer", val: fmtVol(beerL, U), label: C.beer },
  ];

  return (
    <section className="section wrap" id="footprint">
      <div className="co2-card reveal">
        <div className="co2-head">
          <span className="co2-kicker">{C.kicker}</span>
          <FIcon kind="cloud" />
        </div>
        <p className="co2-lead">{C.lead}</p>
        <div className="co2-big">
          <span className="co2-num">{fmtMass(grams, U)}</span>
          <span className="co2-of">{C.of}</span>
        </div>
        <p className="co2-equiv">{C.equiv}</p>
        <div className="co2-grid">
          {items.map((it) => (
            <div className="co2-item" key={it.icon}>
              <FIcon kind={it.icon} />
              <span className="co2-item-val">{it.val}</span>
              <span className="co2-item-label">{it.label}</span>
            </div>
          ))}
        </div>
        <p className="co2-note">{C.note}</p>
      </div>
    </section>
  );
}

Object.assign(window, { Distance, Footprint, FIcon });
