'use client';

import Link from 'next/link';
import {
  type ComponentProps,
  type MouseEvent as ReactMouseEvent,
  useRef,
  useState,
} from 'react';

interface Pulse {
  id: number;
  x: number; // percentage 0-100
  y: number;
}

/**
 * Shared indigo glow-pulse-on-click effect used by hero CTAs and other
 * primary actions across the site. Same visual language as the hero
 * load-in glow — a small bright dot detonates from the click point and
 * scales out fast, fading to transparent.
 *
 * Two variants exposed:
 *   - <PulseLink>   wraps next/link
 *   - <PulseButton> wraps a native <button>
 *
 * Both compose with whatever className the caller passes. They add
 * `relative overflow-hidden` so the expanding pulse stays inside the
 * button's rounded shape — without overflow-hidden, the pulse would
 * bleed onto neighbouring content.
 *
 * The CSS keyframe `glow-pulse` lives in app/globals.css. It scales the
 * pulse dot from 1x to 80x over 650ms, which on a 2px base size gives a
 * ~160px max radius — comfortably bigger than every button on the site,
 * so the bloom always fills the chrome.
 *
 * Reduced-motion: the keyframe is suppressed to instant-opacity-0 in
 * globals.css, so the click flow is preserved but the bloom is silent.
 */
function usePulseState() {
  const [pulses, setPulses] = useState<Pulse[]>([]);
  const idRef = useRef(0);

  const trigger = (e: ReactMouseEvent<HTMLElement>) => {
    const rect = e.currentTarget.getBoundingClientRect();
    const x = ((e.clientX - rect.left) / rect.width) * 100;
    const y = ((e.clientY - rect.top) / rect.height) * 100;
    const id = ++idRef.current;
    setPulses((p) => [...p, { id, x, y }]);
    // Self-cleanup after the animation finishes (650ms keyframe + 50ms slack).
    // We don't rely on `onAnimationEnd` because if the user clicks twice
    // rapidly the second pulse's mount can race the first's animation event.
    setTimeout(() => setPulses((p) => p.filter((q) => q.id !== id)), 700);
  };

  return { pulses, trigger };
}

function PulseLayer({ pulses }: { pulses: Pulse[] }) {
  return (
    <>
      {pulses.map((p) => (
        <span
          key={p.id}
          aria-hidden
          className="pointer-events-none absolute size-2 -translate-x-1/2 -translate-y-1/2 rounded-full"
          style={{
            left: `${p.x}%`,
            top: `${p.y}%`,
            background: 'radial-gradient(circle, rgba(99,102,241,0.85), transparent 65%)',
            animation: 'glow-pulse 0.65s cubic-bezier(0.16, 1, 0.3, 1) forwards',
          }}
        />
      ))}
    </>
  );
}

export function PulseLink({
  className,
  children,
  onClick,
  ...rest
}: ComponentProps<typeof Link>) {
  const { pulses, trigger } = usePulseState();
  return (
    <Link
      {...rest}
      onClick={(e) => {
        trigger(e);
        onClick?.(e);
      }}
      className={`relative overflow-hidden ${className ?? ''}`}
    >
      {children}
      <PulseLayer pulses={pulses} />
    </Link>
  );
}

export function PulseButton({
  className,
  children,
  onClick,
  ...rest
}: ComponentProps<'button'>) {
  const { pulses, trigger } = usePulseState();
  return (
    <button
      {...rest}
      onClick={(e) => {
        trigger(e);
        onClick?.(e);
      }}
      className={`relative overflow-hidden ${className ?? ''}`}
    >
      {children}
      <PulseLayer pulses={pulses} />
    </button>
  );
}
