import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import React__default, { useMemo } from 'react';
import { useReducedMotion, motion } from 'motion/react';
import { progressTheme } from './Progress.theme.js';
import { cn } from '../../../utils/cn.js';

const PROGRESS_SPRING_TRANSITION = {
    type: "spring",
    stiffness: 100,
    damping: 20,
    mass: 0.5,
};
/**
 * Progress component - Linear progress bar for tracking completion
 *
 * Features:
 * - Determinate mode: Shows specific progress value (0-100)
 * - Indeterminate mode: Animated loading state when value is undefined
 * - Multiple sizes with default primary color
 * - className controls the fill bar color (the primary styling target)
 * - wrapperClassName controls the outer container
 * - Flexible label positioning (right, top, bottom, inside)
 * - Respects reduced motion preferences
 *
 * @example
 * // Default (primary color)
 * <Progress value={60} />
 *
 * // Custom fill color via className
 * <Progress value={70} className="bg-[var(--color-success)]" />
 *
 * // With label
 * <Progress value={75} showLabel labelPosition="right" />
 *
 * // Indeterminate (loading)
 * <Progress />
 */
const Progress = React__default.forwardRef(({ value, size = "md", showLabel = false, labelPosition = "right", formatLabel, animated = true, wrapperClassName, className, theme: customTheme, ...props }, ref) => {
    const shouldReduceMotion = useReducedMotion();
    // Merge custom theme with default theme
    const theme = useMemo(() => {
        if (!customTheme)
            return progressTheme;
        return {
            ...progressTheme,
            ...customTheme,
            sizes: { ...progressTheme.sizes, ...customTheme.sizes },
        };
    }, [customTheme]);
    // Calculate percentage (clamped to 0-100)
    const percentage = useMemo(() => {
        if (value === undefined || value === null)
            return 0;
        return Math.min(Math.max(Math.round(value), 0), 100);
    }, [value]);
    // Determine if this is indeterminate mode
    const isIndeterminate = value === undefined || value === null;
    // Format the label
    const label = useMemo(() => {
        if (formatLabel)
            return formatLabel(percentage);
        return `${percentage}%`;
    }, [percentage, formatLabel]);
    // Determine if animation should be applied
    const shouldAnimate = animated && !shouldReduceMotion;
    // Get container layout based on label position
    const containerLayoutClass = useMemo(() => {
        if (!showLabel || isIndeterminate)
            return "";
        switch (labelPosition) {
            case "top":
                return "flex flex-col gap-1.5";
            case "bottom":
                return "flex flex-col gap-1.5";
            case "right":
                return "flex items-center gap-3";
            case "inside":
                return "";
            default:
                return "";
        }
    }, [showLabel, labelPosition, isIndeterminate]);
    // Render label element
    const renderLabel = () => {
        if (!showLabel || isIndeterminate)
            return null;
        if (labelPosition === "inside") {
            // Only show inside label for lg size (enough height)
            if (size !== "lg")
                return null;
            return jsx("span", { className: theme.insideLabelStyle, children: label });
        }
        return (jsx("span", { className: cn(theme.labelStyle, labelPosition === "top" || labelPosition === "bottom"
                ? "text-left"
                : ""), children: label }));
    };
    // Track element with optional fill
    const renderTrack = () => (jsxs("div", { className: cn(theme.trackStyle, theme.sizes[size], "relative", wrapperClassName), children: [isIndeterminate ? (
            // Indeterminate animation
            jsx("div", { className: cn(theme.fillStyle, "absolute", theme.indeterminateStyle, className) })) : shouldAnimate ? (
            // Animated determinate progress with spring animation
            jsx(motion.div, { className: cn(theme.fillStyle, className), initial: { width: 0 }, animate: { width: `${percentage}%` }, transition: PROGRESS_SPRING_TRANSITION })) : (
            // Static determinate progress
            jsx("div", { className: cn(theme.fillStyle, className), style: { width: `${percentage}%` } })), showLabel && labelPosition === "inside" && size === "lg" && !isIndeterminate && (jsx("span", { className: theme.insideLabelStyle, children: label }))] }));
    return (jsxs("div", { ref: ref, className: cn(theme.containerStyle, containerLayoutClass), role: "progressbar", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": isIndeterminate ? undefined : percentage, "aria-label": isIndeterminate ? "Loading" : `${percentage}% complete`, ...props, children: [labelPosition === "top" && renderLabel(), labelPosition === "right" ? (jsxs(Fragment, { children: [jsx("div", { className: "flex-1", children: renderTrack() }), renderLabel()] })) : (renderTrack()), labelPosition === "bottom" && renderLabel()] }));
});
Progress.displayName = "Progress";

export { Progress };
