/* ============================================================
   <CustomCursor /> — global cursor with multiple modes.

   Modes:
   - default   → small arrow + "You" pill
   - active    → accent-tinted arrow + contextual label (Read/Click/Type/…)
   - preview   → pill expands into a small card with gradient cover + title
                 (driven by [data-cursor-preview] attributes)
   - reading   → arrow becomes vertical caret, label shows scroll progress
                 (active inside [data-reading-zone])

   Extras:
   - Magnetic pull: elements matching .btn--primary / [data-magnetic] tug
     both the cursor and the element itself toward each other when within
     range. Pure visual sugar; click target is unchanged.
   - Click ripples: short-lived accent rings spawn at the click point.
   - RTL aware: pill mirrors to below-left when html[dir="rtl"].
   ============================================================ */

function CustomCursor({ enabled = true, defaultLabel = "You" }) {
  const dotRef        = React.useRef(null);
  const followRef     = React.useRef(null);
  const rippleLayerRef= React.useRef(null);

  const [label,    setLabel]    = React.useState(defaultLabel);
  const [mode,     setMode]     = React.useState("default");
  const [preview,  setPreview]  = React.useState(null);
  const [pressed,  setPressed]  = React.useState(false);
  const [visible,  setVisible]  = React.useState(false);
  const [progress, setProgress] = React.useState(0);

  // RTL detection (live)
  const [rtl, setRtl] = React.useState(false);
  React.useEffect(() => {
    const sync = () => setRtl(document.documentElement.dir === "rtl");
    sync();
    const obs = new MutationObserver(sync);
    obs.observe(document.documentElement, { attributes: true, attributeFilter: ["dir"] });
    return () => obs.disconnect();
  }, []);

  const supported = React.useMemo(() => {
    if (typeof window === "undefined") return false;
    return window.matchMedia("(pointer: fine)").matches;
  }, []);

  React.useEffect(() => {
    if (!supported || !enabled) return;
    document.documentElement.classList.add("has-custom-cursor");
    return () => document.documentElement.classList.remove("has-custom-cursor");
  }, [supported, enabled]);

  // ---- Main loop: pointer tracking, magnetic pull, spring follower ----
  React.useEffect(() => {
    if (!supported || !enabled) return;

    let mx = -200, my = -200;     // raw mouse
    let tx = -200, ty = -200;     // dot target (after magnetic pull)
    let fx = -200, fy = -200;     // follower spring pos
    let vfx = 0,   vfy = 0;       // follower velocity
    let lastMagnet = null;        // currently displaced element
    let raf;

    // Magnetic pull DISABLED — kept commented for future tweakability.
    let magnets = [];
    const refreshMagnets = () => { magnets = []; };
    const mo = { disconnect() {} };

    const findMagnet = () => null;

    const onMove = (e) => {
      mx = e.clientX;
      my = e.clientY;
      if (!visible) setVisible(true);

      const target = e.target;

      let newMode    = "default";
      let newLabel   = defaultLabel;
      let newPreview = null;

      const previewEl = target.closest("[data-cursor-preview]");
      const readingEl = target.closest("[data-reading-zone]");
      const explicit  = target.closest("[data-cursor]");
      const link      = target.closest("a");
      const btn       = target.closest('button, [role="button"]');
      const field     = target.closest(
        'input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]), textarea'
      );

      if (previewEl) {
        newMode = "preview";
        newPreview = {
          title:    previewEl.getAttribute("data-cursor-preview"),
          meta:     previewEl.getAttribute("data-cursor-meta") || "",
          gradient: previewEl.getAttribute("data-cursor-gradient") || "",
        };
      } else if (readingEl) {
        newMode  = "reading";
      } else if (explicit) {
        newMode  = "active";
        newLabel = explicit.getAttribute("data-cursor") || defaultLabel;
      } else if (link) {
        newMode  = "active";
        // Smart label per link kind
        const href = (link.getAttribute("href") || "").trim();
        const ROUTE_LABELS = {
          "apps.html": "Browse apps", "app.html": "Open app",
          "about.html": "About us", "pricing.html": "See pricing",
          "careers.html": "Careers", "blog.html": "Read blog",
          "post.html": "Read article", "faq.html": "Open FAQ",
          "process.html": "Our process", "contact.html": "Contact us",
          "index.html": "Home",
        };
        if (!href || href === "#") newLabel = "Open";
        else if (href.startsWith("mailto:")) newLabel = "Email";
        else if (href.startsWith("tel:"))    newLabel = "Call";
        else if (href.startsWith("#"))       newLabel = "Jump";
        else if (/^https?:\/\//i.test(href) && !href.startsWith(window.location.origin)) {
          try { newLabel = new URL(href).hostname.replace(/^www\./, ""); }
          catch { newLabel = "Visit"; }
        } else {
          const file = href.split("?")[0].split("#")[0].split("/").pop();
          newLabel = ROUTE_LABELS[file] || "Open";
        }
      } else if (btn) {
        newMode  = "active";
        newLabel = "Click";
      } else if (field) {
        newMode  = "active";
        newLabel = "Type";
      }

      setMode((p)    => (p === newMode ? p : newMode));
      setLabel((p)   => (p === newLabel ? p : newLabel));
      setPreview((p) => {
        if (!newPreview) return p === null ? p : null;
        if (p && p.title === newPreview.title) return p;
        return newPreview;
      });
    };

    const onDown = (e) => {
      setPressed(true);
      // Click ripple disabled.
    };
    const onUp     = () => setPressed(false);
    const onLeave  = () => setVisible(false);
    const onEnter  = () => setVisible(true);

    const tick = () => {
      // Magnetic pull on cursor target + element itself
      const magnet = findMagnet(mx, my);
      if (magnet) {
        const dxC = magnet.cx - mx;
        const dyC = magnet.cy - my;
        const strength = 1 - Math.min(1, magnet.edgeDist / 80);
        tx = mx + dxC * strength * 0.30;
        ty = my + dyC * strength * 0.30;

        if (lastMagnet && lastMagnet !== magnet.el) {
          lastMagnet.style.transform = "";
        }
        lastMagnet = magnet.el;
        const ex = (mx - magnet.cx) * 0.20 * strength;
        const ey = (my - magnet.cy) * 0.20 * strength;
        magnet.el.style.transform = `translate(${ex}px, ${ey}px)`;
        magnet.el.style.willChange = "transform";
      } else {
        if (lastMagnet) {
          lastMagnet.style.transform = "";
          lastMagnet = null;
        }
        tx = mx; ty = my;
      }

      // Critically-damped spring on follower
      const stiffness = 0.18;
      const damping   = 0.72;
      vfx = (vfx + (tx - fx) * stiffness) * damping;
      vfy = (vfy + (ty - fy) * stiffness) * damping;
      fx += vfx;
      fy += vfy;

      if (dotRef.current)    dotRef.current.style.transform    = `translate3d(${tx}px, ${ty}px, 0)`;
      if (followRef.current) followRef.current.style.transform = `translate3d(${fx}px, ${fy}px, 0)`;

      raf = requestAnimationFrame(tick);
    };

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

    return () => {
      cancelAnimationFrame(raf);
      mo.disconnect();
      if (lastMagnet) lastMagnet.style.transform = "";
      window.removeEventListener("mousemove", onMove);
      window.removeEventListener("mousedown", onDown);
      window.removeEventListener("mouseup", onUp);
      document.documentElement.removeEventListener("mouseleave", onLeave);
      document.documentElement.removeEventListener("mouseenter", onEnter);
    };
  }, [supported, enabled, defaultLabel, visible]);

  // ---- Reading-mode scroll progress ----
  React.useEffect(() => {
    if (mode !== "reading") return;
    const zone = document.querySelector("[data-reading-zone]");
    if (!zone) return;
    const calc = () => {
      const r   = zone.getBoundingClientRect();
      const vh  = window.innerHeight;
      const total    = Math.max(1, r.height - vh);
      const scrolled = Math.max(0, -r.top);
      setProgress(Math.max(0, Math.min(1, scrolled / total)));
    };
    calc();
    window.addEventListener("scroll", calc, { passive: true });
    window.addEventListener("resize", calc);
    return () => {
      window.removeEventListener("scroll", calc);
      window.removeEventListener("resize", calc);
    };
  }, [mode]);

  if (!supported || !enabled) return null;

  const cls = [
    "cursor-layer",
    visible ? "" : "is-hidden",
    `cursor-mode-${mode}`,
    pressed ? "is-pressed" : "",
    rtl ? "is-rtl" : "",
  ].filter(Boolean).join(" ");

  const readingLabel = `${Math.max(1, Math.round((1 - progress) * 100))}% left`;

  return (
    <div className={cls} aria-hidden="true">
      <div className="cursor-ripples" ref={rippleLayerRef}></div>

      <div ref={dotRef} className="cursor-dot">
        <svg className="cursor-dot__arrow" viewBox="0 0 20 20" width="26" height="26">
          <path
            d="M3.5 2.5 L16.5 9.5 L10 10.5 L7.5 16.5 Z"
            fill="currentColor"
            stroke="#fff"
            strokeWidth="1.4"
            strokeLinejoin="round"
          />
        </svg>
        <span className="cursor-dot__caret" aria-hidden="true"></span>
      </div>

      <div ref={followRef} className="cursor-follow">
        <div className="cursor-follow__pill">
          <span className="cursor-follow__label">
            {mode === "reading" ? (
              <>
                <span className="cursor-follow__icon">
                  <svg width="9" height="9" viewBox="0 0 9 9" fill="none">
                    <path d="M1.5 1 L7 4.5 L1.5 8 Z" fill="currentColor"/>
                  </svg>
                </span>
                Reading · {readingLabel}
              </>
            ) : label}
          </span>
        </div>

        {preview && (
          <div className="cursor-follow__preview">
            <div
              className="cursor-follow__preview-cover"
              style={{ background: preview.gradient || "var(--accent)" }}
            ></div>
            <div className="cursor-follow__preview-body">
              {preview.meta ? (
                <div className="cursor-follow__preview-meta">{preview.meta}</div>
              ) : null}
              <div className="cursor-follow__preview-title">{preview.title}</div>
            </div>
          </div>
        )}
      </div>
    </div>
  );
}

window.CustomCursor = CustomCursor;
