"use client";

import * as React from "react";
import { motion, useMotionValue, useTransform, useSpring } from "framer-motion";
import { cn } from "../../lib/utils";
import { cva, type VariantProps } from "class-variance-authority";

const magneticButtonVariants = cva(
  "relative inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
        outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
        secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "text-primary underline-offset-4 hover:underline",
      },
      size: {
        default: "h-10 px-4 py-2",
        sm: "h-9 rounded-md px-3",
        lg: "h-11 rounded-md px-8",
        icon: "h-10 w-10",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
);

export interface MagneticButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof magneticButtonVariants> {
  magnetStrength?: number;
  magnetDistance?: number;
}

const MagneticButton = React.forwardRef<HTMLButtonElement, MagneticButtonProps>(
  (
    {
      className,
      variant,
      size,
      magnetStrength = 0.25,
      magnetDistance = 100,
      children,
      onMouseMove,
      onMouseLeave,
      ...props
    },
    ref
  ) => {
    const buttonRef = React.useRef<HTMLDivElement>(null);
    const mouseX = useMotionValue(0);
    const mouseY = useMotionValue(0);

    const springConfig = { damping: 15, stiffness: 150 };
    const x = useSpring(useTransform(mouseX, (value) => value * magnetStrength), springConfig);
    const y = useSpring(useTransform(mouseY, (value) => value * magnetStrength), springConfig);

    const handleMouseMove = React.useCallback(
      (e: React.MouseEvent<HTMLButtonElement>) => {
        if (!buttonRef.current) return;

        const rect = buttonRef.current.getBoundingClientRect();
        const centerX = rect.left + rect.width / 2;
        const centerY = rect.top + rect.height / 2;
        
        const distanceX = e.clientX - centerX;
        const distanceY = e.clientY - centerY;
        
        const distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
        
        if (distance < magnetDistance) {
          mouseX.set(distanceX);
          mouseY.set(distanceY);
        } else {
          mouseX.set(0);
          mouseY.set(0);
        }

        onMouseMove?.(e);
      },
      [magnetDistance, mouseX, mouseY, onMouseMove]
    );

    const handleMouseLeave = React.useCallback(
      (e: React.MouseEvent<HTMLButtonElement>) => {
        mouseX.set(0);
        mouseY.set(0);
        onMouseLeave?.(e);
      },
      [mouseX, mouseY, onMouseLeave]
    );

    return (
      <motion.div
        ref={buttonRef}
        style={{ x, y }}
        className="inline-block"
      >
        <motion.button
          ref={ref}
          className={cn(magneticButtonVariants({ variant, size, className }))}
          onMouseMove={handleMouseMove}
          onMouseLeave={handleMouseLeave}
          whileHover={{ scale: 1.05 }}
          whileTap={{ scale: 0.95 }}
          transition={{ type: "spring", stiffness: 400, damping: 17 }}
          {...props}
        >
          <motion.span
            style={{ x: useTransform(x, (value) => value * 0.2), y: useTransform(y, (value) => value * 0.2) }}
            className="relative z-10"
          >
            {children}
          </motion.span>
        </motion.button>
      </motion.div>
    );
  }
);

MagneticButton.displayName = "MagneticButton";

export { MagneticButton, magneticButtonVariants };