/* CustomCursor — magnetic two-part cursor for the map.
 *
 * Two DOM elements:
 *   - .cmgc-cursor-ring : the OUTER circle. Eases toward the cursor
 *     with a lag, so it trails fast movement. When the user nears a
 *     château pin (within MAGNET_PX), the ring SNAPS to the pin's
 *     centre — that's the "aimante" behaviour the brief asked for.
 *   - .cmgc-cursor-dot  : the INNER dot. Always sits at the exact
 *     cursor position, even when the ring is magnetised — so the dot
 *     visibly moves WITHIN the ring as the user hovers around a pin.
 *
 * The native cursor is hidden via a body class (`.cmgc-cursor-on`) the
 * effect adds on the first mousemove. We also strip ourselves on
 * coarse pointers (touch) — a fake cursor on a phone is hostile.
 *
 * No deps. Runs at ~60fps off a single rAF loop; reads
 * .mb-pin-inner rects every frame (cheap — usually 5–20 pins on screen).
 */
function CustomCursor() {
  const ringRef = React.useRef(null);
  const dotRef  = React.useRef(null);

  React.useEffect(() => {
    // Skip entirely on touch — no cursor to hide, would just litter
    // overlay nodes.
    if (window.matchMedia && window.matchMedia("(pointer: coarse)").matches) {
      return;
    }

    const MAGNET_PX        = 44;     // distance at which we snap to a pin
    const RING_EASE        = 0.22;   // lerp factor for the trailing ring
    const RING_MAGNET_EASE = 0.32;   // a touch tighter when locked on

    let mx = -100, my = -100;       // raw mouse position
    let rx = -100, ry = -100;       // eased ring position
    let magnetEl = null;             // currently-magnetised pin element

    let started = false;
    const start = () => {
      if (started) return;
      started = true;
      rx = mx; ry = my;
      document.body.classList.add("cmgc-cursor-on");
    };

    const onMove = (e) => {
      mx = e.clientX;
      my = e.clientY;
      start();
    };
    const onLeave = () => {
      document.body.classList.remove("cmgc-cursor-on");
      document.body.classList.remove("cmgc-cursor-magnet");
      started = false;
      magnetEl = null;
    };
    const onEnter = () => { /* next mousemove restarts */ };
    const onDown = () => document.body.classList.add("cmgc-cursor-press");
    const onUp   = () => document.body.classList.remove("cmgc-cursor-press");

    window.addEventListener("mousemove", onMove, { passive: true });
    document.documentElement.addEventListener("mouseleave", onLeave);
    document.documentElement.addEventListener("mouseenter", onEnter);
    window.addEventListener("mousedown", onDown);
    window.addEventListener("mouseup",   onUp);

    let raf = 0;
    const tick = () => {
      // ---- find nearest magnetisable pin ----
      let best = null;
      let bestD = MAGNET_PX;
      // Both individual château pins AND appellation cluster dots AND
      // slide-menu château rows are magnetisable.
      const pins = document.querySelectorAll(".mb-pin-inner, .mb-cluster-dot, .slide-chateau");
      for (let i = 0; i < pins.length; i++) {
        const r = pins[i].getBoundingClientRect();
        // Skip offscreen pins quickly
        if (r.right < 0 || r.bottom < 0 || r.left > innerWidth || r.top > innerHeight) continue;
        const cx = r.left + r.width  / 2;
        const cy = r.top  + r.height / 2;
        const d = Math.hypot(cx - mx, cy - my);
        if (d < bestD) {
          bestD = d;
          best = { x: cx, y: cy, el: pins[i] };
        }
      }

      // ---- pick the ring target ----
      let tx, ty, ease;
      if (best) {
        tx = best.x; ty = best.y;
        ease = RING_MAGNET_EASE;
        if (magnetEl !== best.el) {
          magnetEl = best.el;
          document.body.classList.add("cmgc-cursor-magnet");
        }
      } else {
        tx = mx; ty = my;
        ease = RING_EASE;
        if (magnetEl) {
          magnetEl = null;
          document.body.classList.remove("cmgc-cursor-magnet");
        }
      }

      // ---- ease ring toward target, dot to raw cursor ----
      rx += (tx - rx) * ease;
      ry += (ty - ry) * ease;

      if (ringRef.current) {
        ringRef.current.style.transform =
          `translate3d(${rx}px, ${ry}px, 0) translate(-50%, -50%)`;
      }
      if (dotRef.current) {
        dotRef.current.style.transform =
          `translate3d(${mx}px, ${my}px, 0) translate(-50%, -50%)`;
      }

      raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);

    return () => {
      window.removeEventListener("mousemove", onMove);
      document.documentElement.removeEventListener("mouseleave", onLeave);
      document.documentElement.removeEventListener("mouseenter", onEnter);
      window.removeEventListener("mousedown", onDown);
      window.removeEventListener("mouseup",   onUp);
      cancelAnimationFrame(raf);
      document.body.classList.remove("cmgc-cursor-on");
      document.body.classList.remove("cmgc-cursor-magnet");
      document.body.classList.remove("cmgc-cursor-press");
    };
  }, []);

  return (
    <>
      <div ref={ringRef} className="cmgc-cursor-ring" aria-hidden="true"/>
      <div ref={dotRef}  className="cmgc-cursor-dot"  aria-hidden="true"/>
    </>
  );
}

window.CustomCursor = CustomCursor;
