"use client";

import { motion, useMotionValue, useSpring, useTransform } from "framer-motion";
import type { MouseEvent, PointerEvent, ReactNode } from "react";
import { cn } from "@/lib/utils";

type PhysicsButtonProps = {
  href: string;
  children: ReactNode;
  className?: string;
  external?: boolean;
  onClick?: (event: MouseEvent<HTMLAnchorElement>) => void;
};

export default function PhysicsButton({ href, children, className, external = false, onClick }: PhysicsButtonProps) {
  const pullX = useMotionValue(0);
  const pullY = useMotionValue(0);
  const press = useMotionValue(0);
  const x = useSpring(pullX, { stiffness: 190, damping: 13, mass: 0.42 });
  const y = useSpring(pullY, { stiffness: 190, damping: 13, mass: 0.42 });
  const pressed = useSpring(press, { stiffness: 520, damping: 18, mass: 0.35 });
  const pointerScaleX = useTransform(x, [-30, 0, 30], [1.18, 1, 1.18]);
  const pointerScaleY = useTransform(y, [-18, 0, 18], [0.9, 1, 0.9]);
  const tapScaleX = useTransform(pressed, [0, 1], [1, 1.24]);
  const tapScaleY = useTransform(pressed, [0, 1], [1, 0.82]);
  const scaleX = useTransform([pointerScaleX, tapScaleX], ([pointerValue, tapValue]) => (pointerValue as number) * (tapValue as number));
  const scaleY = useTransform([pointerScaleY, tapScaleY], ([pointerValue, tapValue]) => (pointerValue as number) * (tapValue as number));
  const rotate = useTransform(x, [-30, 0, 30], [-2.2, 0, 2.2]);
  const glowX = useTransform(x, (value) => value * 0.65);
  const glowY = useTransform(y, (value) => value * 0.65);

  function handleMove(event: PointerEvent<HTMLAnchorElement>) {
    if (event.pointerType === "touch") return;

    const bounds = event.currentTarget.getBoundingClientRect();
    const localX = event.clientX - bounds.left - bounds.width / 2;
    const localY = event.clientY - bounds.top - bounds.height / 2;

    const xLimit = 30;
    const yLimit = 18;
    const strength = 0.42;

    pullX.set(Math.max(-xLimit, Math.min(xLimit, localX * strength)));
    pullY.set(Math.max(-yLimit, Math.min(yLimit, localY * strength)));
  }

  function release() {
    pullX.set(0);
    pullY.set(0);
    press.set(0);
  }

  return (
    <motion.a
      href={href}
      target={external ? "_blank" : undefined}
      rel={external ? "noreferrer" : undefined}
      onClick={onClick}
      onPointerMove={handleMove}
      onPointerLeave={release}
      onPointerCancel={release}
      onPointerDown={(event) => {
        event.currentTarget.setPointerCapture?.(event.pointerId);
        handleMove(event);
        press.set(1);
        pullY.set(event.pointerType === "touch" ? 10 : 12);
      }}
      onPointerUp={release}
      onLostPointerCapture={release}
      whileHover={{ scale: 1.035 }}
      style={{ x, y, scaleX, scaleY, rotate }}
      transition={{ type: "spring", stiffness: 520, damping: 18, mass: 0.45 }}
      className={cn("premium-glass group relative inline-flex touch-manipulation select-none items-center justify-center overflow-hidden will-change-transform", className)}
    >
      <motion.span
        className="pointer-events-none absolute inset-0 rounded-full bg-white/15 opacity-0 blur-xl transition-opacity duration-300 group-hover:opacity-100"
        style={{ x: glowX, y: glowY }}
      />
      <span className="relative z-10 inline-flex items-center justify-center gap-2">{children}</span>
    </motion.a>
  );
}
