// ============================================================
// SHARED COMPONENTS — Nicolas Nechitch
// ============================================================
const { useState, useEffect, useRef, useCallback } = React;

// ===== Custom Cursor =====
function CustomCursor() {
  const dotRef = useRef(null);
  const ringRef = useRef(null);

  useEffect(() => {
    const dot = dotRef.current;
    const ring = ringRef.current;
    if (!dot || !ring) return;

    let dotX = 0, dotY = 0;
    let ringX = 0, ringY = 0;
    let mouseX = 0, mouseY = 0;
    let raf;

    const onMove = (e) => {
      mouseX = e.clientX;
      mouseY = e.clientY;
    };

    const tick = () => {
      dotX += (mouseX - dotX) * 0.6;
      dotY += (mouseY - dotY) * 0.6;
      ringX += (mouseX - ringX) * 0.18;
      ringY += (mouseY - ringY) * 0.18;
      dot.style.transform = `translate3d(${dotX}px, ${dotY}px, 0)`;
      ring.style.transform = `translate3d(${ringX}px, ${ringY}px, 0)`;
      raf = requestAnimationFrame(tick);
    };

    const onEnter = () => ring.classList.add("is-hover");
    const onLeave = () => ring.classList.remove("is-hover");

    window.addEventListener("mousemove", onMove);
    document.querySelectorAll("a, button, [data-hover]").forEach((el) => {
      el.addEventListener("mouseenter", onEnter);
      el.addEventListener("mouseleave", onLeave);
    });

    tick();
    return () => {
      window.removeEventListener("mousemove", onMove);
      cancelAnimationFrame(raf);
    };
  }, []);

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

// ===== Scroll Reveal Hook =====
function useReveal() {
  const ref = useRef(null);
  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    const targets = el.querySelectorAll(".reveal-word, .reveal-up, .reveal-fade");
    // Immediately reveal any element already in viewport at mount
    targets.forEach((node) => {
      const r = node.getBoundingClientRect();
      if (r.top < window.innerHeight && r.bottom > 0) {
        node.classList.add("is-in");
      }
    });
    const io = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            entry.target.classList.add("is-in");
          }
        });
      },
      { threshold: 0, rootMargin: "0px 0px -5% 0px" }
    );
    targets.forEach((node) => {
      if (!node.classList.contains("is-in")) io.observe(node);
    });
    return () => io.disconnect();
  }, []);
  return ref;
}

// ===== Split Text into Reveal Words =====
function SplitReveal({ text, delay = 0, className = "" }) {
  const words = text.split(" ");
  return (
    <span className={className}>
      {words.map((w, i) => (
        <React.Fragment key={i}>
          <span
            className="reveal-word"
            style={{ "--d": `${delay + i * 60}ms` }}
          >
            <span style={{ transitionDelay: `${delay + i * 60}ms` }}>{w}</span>
          </span>
          {i < words.length - 1 && " "}
        </React.Fragment>
      ))}
    </span>
  );
}

// ===== Magnetic Button =====
function Magnetic({ children, strength = 0.35, className = "", ...props }) {
  const ref = useRef(null);

  const onMove = (e) => {
    const el = ref.current;
    if (!el) return;
    const rect = el.getBoundingClientRect();
    const x = e.clientX - rect.left - rect.width / 2;
    const y = e.clientY - rect.top - rect.height / 2;
    el.style.transform = `translate(${x * strength}px, ${y * strength}px)`;
  };
  const onLeave = () => {
    const el = ref.current;
    if (el) el.style.transform = "translate(0, 0)";
  };

  return (
    <span
      ref={ref}
      onMouseMove={onMove}
      onMouseLeave={onLeave}
      className={className}
      style={{ display: "inline-block", transition: "transform 0.4s cubic-bezier(0.16, 1, 0.3, 1)" }}
      {...props}
    >
      {children}
    </span>
  );
}

// ===== Marquee =====
function Marquee({ items, separator = "✦" }) {
  return (
    <div className="marquee">
      <div className="marquee-track">
        {[...items, ...items].map((item, i) => (
          <span key={i} style={{ display: "inline-flex", alignItems: "center", gap: 64 }}>
            <span>{item}</span>
            <span style={{ color: "var(--blue)" }}>{separator}</span>
          </span>
        ))}
      </div>
    </div>
  );
}

// ===== Tilt Card =====
function Tilt({ children, max = 8, className = "", style = {}, ...props }) {
  const ref = useRef(null);

  const onMove = (e) => {
    const el = ref.current;
    if (!el) return;
    const rect = el.getBoundingClientRect();
    const x = (e.clientX - rect.left) / rect.width - 0.5;
    const y = (e.clientY - rect.top) / rect.height - 0.5;
    el.style.transform = `perspective(1000px) rotateX(${-y * max}deg) rotateY(${x * max}deg) translateZ(0)`;
  };
  const onLeave = () => {
    if (ref.current) ref.current.style.transform = "perspective(1000px) rotateX(0) rotateY(0)";
  };

  return (
    <div
      ref={ref}
      className={className}
      onMouseMove={onMove}
      onMouseLeave={onLeave}
      style={{ transition: "transform 0.5s cubic-bezier(0.16, 1, 0.3, 1)", transformStyle: "preserve-3d", ...style }}
      {...props}
    >
      {children}
    </div>
  );
}

// ===== Arrow Icon =====
function ArrowUpRight({ size = 14 }) {
  return (
    <svg className="arrow" width={size} height={size} viewBox="0 0 14 14" fill="none">
      <path d="M3 11L11 3M11 3H4.5M11 3V9.5" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  );
}

Object.assign(window, {
  CustomCursor,
  useReveal,
  SplitReveal,
  Magnetic,
  Marquee,
  Tilt,
  ArrowUpRight,
});
