/** Wireframe globe on a canvas — drag to spin, it marks where you are. */
function Globe({ lat = -23.55, lon = -46.63, size = 176, color = "#fff", onSpin, turns = 0 }) {
  const ref = React.useRef(null);
  const rot = React.useRef({ x: -0.35, y: 0.8 });
  const drag = React.useRef(null);

  const draw = React.useCallback(() => {
    const c = ref.current; if (!c) return;
    const dpr = window.devicePixelRatio || 1;
    c.width = size * dpr; c.height = size * dpr;
    const g = c.getContext("2d");
    g.setTransform(dpr, 0, 0, dpr, 0, 0);
    g.clearRect(0, 0, size, size);
    const R = size / 2 - 6, cx = size / 2, cy = size / 2;
    const { x: rx, y: ry } = rot.current;

    const project = (la, lo) => {
      const a = la * Math.PI / 180, b = (lo * Math.PI / 180) + ry;
      let X = Math.cos(a) * Math.sin(b), Y = Math.sin(a), Z = Math.cos(a) * Math.cos(b);
      const Y2 = Y * Math.cos(rx) - Z * Math.sin(rx), Z2 = Y * Math.sin(rx) + Z * Math.cos(rx);
      return { x: cx + X * R, y: cy - Y2 * R, z: Z2 };
    };

    const rgb = color === "#000" ? "0,0,0" : "255,255,255";
    g.strokeStyle = "rgba(" + rgb + ",0.9)"; g.lineWidth = 1;
    g.beginPath(); g.arc(cx, cy, R, 0, Math.PI * 2); g.stroke();

    const line = (pts) => {
      g.beginPath(); let open = false;
      pts.forEach(p => {
        if (p.z > 0) { if (!open) { g.moveTo(p.x, p.y); open = true; } else g.lineTo(p.x, p.y); }
        else open = false;
      });
      g.stroke();
    };

    g.strokeStyle = "rgba(" + rgb + ",0.34)";
    for (let lo = -180; lo < 180; lo += 30) {
      const pts = []; for (let la = -90; la <= 90; la += 4) pts.push(project(la, lo));
      line(pts);
    }
    for (let la = -60; la <= 60; la += 30) {
      const pts = []; for (let lo = -180; lo <= 180; lo += 4) pts.push(project(la, lo));
      line(pts);
    }
    g.strokeStyle = "rgba(" + rgb + ",0.6)";
    const eq = []; for (let lo = -180; lo <= 180; lo += 4) eq.push(project(0, lo)); line(eq);

    const m = project(lat, lon);
    if (m.z > 0) {
      g.fillStyle = color;
      g.beginPath(); g.arc(m.x, m.y, 4, 0, Math.PI * 2); g.fill();
      g.strokeStyle = "rgba(" + rgb + ",0.85)";
      g.beginPath(); g.arc(m.x, m.y, 9, 0, Math.PI * 2); g.stroke();
    }
  }, [lat, lon, size, color]);

  React.useEffect(() => { draw(); }, [draw]);

  /** Picking a place re-aims the globe: it eases from wherever it was spun to face the marker.
   *  `turns` adds whole revolutions around the polar axis first — the globe really spins,
   *  it is not the flat image being rotated. */
  React.useEffect(() => {
    const target = { x: lat * Math.PI / 180, y: -lon * Math.PI / 180 };
    const from = { ...rot.current };
    const twoPi = Math.PI * 2;
    let dy = (target.y - from.y) % twoPi;
    if (dy > Math.PI) dy -= twoPi;
    if (dy < -Math.PI) dy += twoPi;
    dy -= turns * twoPi;
    const dx = target.x - from.x;
    const dur = turns ? 980 : 620, t0 = performance.now();
    let raf;
    const step = (now) => {
      const p = Math.min(1, (now - t0) / dur);
      const e = 1 - Math.pow(1 - p, 3);
      rot.current = { x: from.x + dx * e, y: from.y + dy * e };
      draw();
      if (p < 1) raf = requestAnimationFrame(step);
    };
    raf = requestAnimationFrame(step);
    return () => cancelAnimationFrame(raf);
  }, [lat, lon, draw, turns]);

  return (
    <canvas ref={ref}
      onPointerDown={e => { drag.current = { x: e.clientX, y: e.clientY, xr: rot.current.x, yr: rot.current.y }; }}
      onPointerMove={e => {
        if (!drag.current) return;
        rot.current = {
          y: drag.current.yr + (e.clientX - drag.current.x) * 0.01,
          x: Math.max(-1.2, Math.min(1.2, drag.current.xr + (e.clientY - drag.current.y) * -0.008))
        };
        draw(); if (onSpin) onSpin();
      }}
      onPointerUp={() => { drag.current = null; }}
      onPointerLeave={() => { drag.current = null; }}
      style={{ width: size, height: size, touchAction: "none", cursor: "grab", display: "block" }} />
  );
}
Object.assign(window, { Globe });
