"use client";

import { useEffect, useRef, type ReactNode } from "react";

const MAX_PULL = 6;

/**
 * Subtle magnetism for primary CTAs: pulls the button up to 6px toward the pointer
 * and sets the fill origin to the pointer position. Fine pointers only; off under reduced motion.
 */
export function MagneticButton({ children, className }: { children: ReactNode; className?: string }) {
  const wrapperRef = useRef<HTMLSpanElement>(null);

  useEffect(() => {
    const wrapper = wrapperRef.current;
    if (!wrapper) return;
    const finePointer = window.matchMedia("(pointer: fine)").matches;
    const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
    if (!finePointer || reducedMotion) return;

    const button = wrapper.querySelector<HTMLElement>(".btn");
    let frame = 0;

    const onMove = (event: PointerEvent) => {
      const rect = wrapper.getBoundingClientRect();
      const x = event.clientX - rect.left;
      const y = event.clientY - rect.top;
      const dx = Math.max(-1, Math.min(1, (x - rect.width / 2) / (rect.width / 2)));
      const dy = Math.max(-1, Math.min(1, (y - rect.height / 2) / (rect.height / 2)));
      cancelAnimationFrame(frame);
      frame = requestAnimationFrame(() => {
        wrapper.style.transform = `translate3d(${(dx * MAX_PULL).toFixed(2)}px, ${(dy * MAX_PULL * 0.6).toFixed(2)}px, 0)`;
        button?.style.setProperty("--fill-x", `${x}px`);
        button?.style.setProperty("--fill-y", `${y}px`);
      });
    };

    const onLeave = () => {
      cancelAnimationFrame(frame);
      wrapper.style.transform = "";
    };

    wrapper.addEventListener("pointermove", onMove);
    wrapper.addEventListener("pointerleave", onLeave);
    return () => {
      cancelAnimationFrame(frame);
      wrapper.removeEventListener("pointermove", onMove);
      wrapper.removeEventListener("pointerleave", onLeave);
    };
  }, []);

  return (
    <span
      ref={wrapperRef}
      className={className ?? "inline-flex"}
      style={{ transition: "transform 500ms var(--ease-out-expo)" }}
    >
      {children}
    </span>
  );
}
