import { jsxs, jsx } from 'react/jsx-runtime';
import React__default, { useCallback, useRef } from 'react';
import { useReducedMotion, motion } from 'motion/react';
import { buttonTheme } from './Button.theme.js';
import { cn } from '../../../utils/cn.js';
import { Spinner } from '../Spinner/Spinner.js';
import { useRipple, getRippleAnimation, getRippleColorClass } from './Button.ripple.js';

// Button animation variants (module-level constant)
const BUTTON_TAP_ANIMATION = {
    tap: {
        scale: 0.95,
        transition: {
            duration: 0.1,
            type: "spring",
            stiffness: 400,
            damping: 10,
        },
    },
};
const Button = React__default.forwardRef(({ children, className = "", iconOnly = false, state = "default", size = "md", color, variant, block = false, onClick, enableRipple = true, rippleEffect = "default", rippleClassName, rippleScale = 10, showReflection = true, darkMode = false, disabled: disabledProp, "aria-label": ariaLabelProp, onAnimationStart: _onAnimationStart, onAnimationEnd: _onAnimationEnd, onDrag: _onDrag, onDragStart: _onDragStart, onDragEnd: _onDragEnd, ...restProps }, ref) => {
    var _a, _b, _c, _d, _e, _f, _g;
    const shouldReduceMotion = useReducedMotion();
    const shouldDisableAnimations = !!shouldReduceMotion;
    // Initialize ripple hook
    const { ripples, createRipple, buttonRef, effect } = useRipple({
        scale: rippleScale,
        duration: 600,
        effect: rippleEffect,
    });
    // Resolve color and variant with defaults
    const resolvedColor = color || "primary";
    const resolvedVariant = variant || "filled";
    // Derived state flags (direct computation - faster than useMemo)
    const isLoading = state === "loading";
    const isDisabled = state === "disabled" || state === "loading" || !!disabledProp;
    const isError = state === "error";
    // Dev-time a11y warning for iconOnly buttons without aria-label
    if (process.env.NODE_ENV !== "production") {
        if (iconOnly && !ariaLabelProp) {
            // eslint-disable-next-line no-console
            console.warn("Button(iconOnly) requires 'aria-label' for accessibility.");
        }
    }
    // Safe onClick handler - respect both state="disabled" and disabled={true}
    const handleClick = useCallback((event) => {
        if (isDisabled)
            return;
        // Create ripple effect if enabled
        if (enableRipple && !shouldReduceMotion) {
            createRipple(event);
        }
        try {
            onClick === null || onClick === void 0 ? void 0 : onClick(event);
        }
        catch (error) {
            if (process.env.NODE_ENV !== "production") {
                // eslint-disable-next-line no-console
                console.error("Error in button click handler:", error);
            }
        }
    }, [onClick, isDisabled, enableRipple, shouldReduceMotion, createRipple]);
    // Compute theme classes (direct computation - faster than useMemo)
    const sizeClasses = ((_b = (_a = buttonTheme.sizes) === null || _a === void 0 ? void 0 : _a[size]) === null || _b === void 0 ? void 0 : _b[iconOnly ? "iconOnly" : resolvedVariant === "link" ? "link" : "default"]) || "";
    const colorClasses = ((_c = buttonTheme.variantColors[resolvedVariant]) === null || _c === void 0 ? void 0 : _c[resolvedColor]) || "";
    const variantClasses = ((_d = buttonTheme.variantStyles) === null || _d === void 0 ? void 0 : _d[resolvedVariant]) || "";
    const stateClasses = isDisabled
        ? ((_e = buttonTheme.states) === null || _e === void 0 ? void 0 : _e.disabled) || ""
        : isError
            ? ((_f = buttonTheme.states) === null || _f === void 0 ? void 0 : _f.error) || ""
            : isLoading
                ? ((_g = buttonTheme.states) === null || _g === void 0 ? void 0 : _g.loading) || ""
                : "";
    const blockStyle = block ? buttonTheme.blockStyle : "";
    // Generate default aria-label for icon-only buttons if not provided (fallback only)
    const ariaLabel = iconOnly && !ariaLabelProp ? "Button" : ariaLabelProp;
    // Determine animation props (user props will override due to spread order)
    const animationProps = shouldDisableAnimations
        ? {}
        : {
            whileTap: !isDisabled ? "tap" : undefined,
            variants: BUTTON_TAP_ANIMATION,
        };
    // Spinner color - ensure contrast on filled buttons
    const spinnerClassName = resolvedVariant === "filled" && color !== "neutral"
        ? "border-t-white border-l-white"
        : "";
    // Track the latest forwarded ref to avoid mergedRef recreation on inline callback refs
    const forwardedRef = useRef(ref);
    forwardedRef.current = ref;
    // Merge refs - stable callback that won't cause DOM detach/attach cycles
    const mergedRef = useCallback((node) => {
        // Set ripple's buttonRef
        if (buttonRef) {
            buttonRef.current = node;
        }
        // Set forwarded ref
        const fRef = forwardedRef.current;
        if (typeof fRef === "function") {
            fRef(node);
        }
        else if (fRef) {
            fRef.current =
                node;
        }
    }, [buttonRef]);
    return (jsxs(motion.button, { type: "button", ...restProps, ...animationProps, ref: mergedRef, className: cn(buttonTheme.baseStyle, colorClasses, variantClasses, sizeClasses, blockStyle, stateClasses, darkMode && "dark", className), disabled: isDisabled, "data-state": state, "data-color": resolvedColor, "data-variant": resolvedVariant, "data-size": size, "data-icon-only": iconOnly ? "true" : "false", "data-block": block ? "true" : "false", "aria-disabled": isDisabled || undefined, "aria-invalid": isError || undefined, "aria-label": ariaLabel, onClick: handleClick, children: [showReflection &&
                resolvedVariant !== "link" &&
                resolvedVariant !== "outline" && (jsx("div", { className: "absolute top-0.25 right-0.25 left-0.25 h-3 border-t-[0.5px] border-white/40 rounded-t-[calc(var(--button-radius)-1.25px)] opacity-60" })), isLoading && (jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsx(Spinner, { size: "sm", color: color, className: spinnerClassName }) })), jsx("span", { className: cn("inline-flex items-center gap-2 whitespace-nowrap", isLoading && "opacity-0"), children: children }), enableRipple &&
                ripples.map((ripple) => {
                    const animation = getRippleAnimation(effect, ripple, rippleScale);
                    return (jsx(motion.span, { initial: animation.initial, animate: animation.animate, transition: animation.transition, className: cn("absolute rounded-full size-5 pointer-events-none ", animation.className, rippleClassName ||
                            getRippleColorClass(resolvedVariant, resolvedColor)), style: {
                            top: ripple.y - 10,
                            left: ripple.x - 10,
                        } }, ripple.id));
                })] }));
});
// Set display name for dev tools and Storybook
Button.displayName = "Button";

export { Button };
