import { jsxs, jsx } from 'react/jsx-runtime';
import React__default, { useRef, useState, useCallback, useMemo } from 'react';
import { FormLabel } from '../FormLabel/FormLabel.js';
import { sliderTheme } from './Slider.theme.js';
import { cn } from '../../../utils/cn.js';

const Slider = React__default.forwardRef(({ state = "default", className = "", label, labelClassName = "", helperText, helperTextClassName = "", wrapperClassName = "", min = 0, max = 100, step = 1, value, defaultValue, onChange, onChangeCommitted, showValue = false, unit = "", showMinMax = false, showTicks = false, tickStep, range = false, iconStart, iconEnd, theme = {}, required = false, name, id, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby, ...props }, ref) => {
    var _a;
    const trackRef = useRef(null);
    const generatedId = React__default.useId();
    const sliderId = id || generatedId;
    const helperTextId = helperText ? `${sliderId}-helper` : undefined;
    // Handle controlled/uncontrolled value
    const [internalValue, setInternalValue] = useState((_a = value !== null && value !== void 0 ? value : defaultValue) !== null && _a !== void 0 ? _a : (range ? [min, min] : min));
    const currentValue = value !== null && value !== void 0 ? value : internalValue;
    const isDisabled = state === "disabled";
    const isInvalid = state === "invalid";
    // Get values as array for consistent handling
    const values = Array.isArray(currentValue) ? currentValue : [currentValue];
    const [dragIndex, setDragIndex] = useState(null);
    // Calculate percentage for positioning
    const getPercentage = useCallback((val) => {
        return ((val - min) / (max - min)) * 100;
    }, [min, max]);
    // Get value from mouse/touch position
    const getValueFromPosition = useCallback((clientX) => {
        if (!trackRef.current)
            return min;
        const rect = trackRef.current.getBoundingClientRect();
        const percentage = ((clientX - rect.left) / rect.width) * 100;
        const clampedPercentage = Math.max(0, Math.min(100, percentage));
        const rawValue = min + (clampedPercentage / 100) * (max - min);
        // Round to nearest step
        const steppedValue = Math.round(rawValue / step) * step;
        return Math.max(min, Math.min(max, steppedValue));
    }, [min, max, step]);
    // Handle value change
    const handleValueChange = useCallback((newValue) => {
        if (isDisabled)
            return;
        if (value === undefined) {
            setInternalValue(newValue);
        }
        onChange === null || onChange === void 0 ? void 0 : onChange(newValue);
    }, [value, onChange, isDisabled]);
    // Handle pointer down on thumb
    const handlePointerDown = useCallback((e, thumbIndex) => {
        if (isDisabled)
            return;
        e.preventDefault();
        setDragIndex(thumbIndex);
        const handleMove = (moveEvent) => {
            const newValue = getValueFromPosition(moveEvent.clientX);
            if (range) {
                const newValues = [...values];
                newValues[thumbIndex] = newValue;
                // Ensure values don't cross over
                if (thumbIndex === 0 && newValue > newValues[1]) {
                    newValues[0] = newValues[1];
                }
                else if (thumbIndex === 1 && newValue < newValues[0]) {
                    newValues[1] = newValues[0];
                }
                handleValueChange(newValues);
            }
            else {
                handleValueChange(newValue);
            }
        };
        const handleEnd = () => {
            setDragIndex(null);
            onChangeCommitted === null || onChangeCommitted === void 0 ? void 0 : onChangeCommitted(currentValue);
            document.removeEventListener("pointermove", handleMove);
            document.removeEventListener("pointerup", handleEnd);
        };
        document.addEventListener("pointermove", handleMove);
        document.addEventListener("pointerup", handleEnd);
    }, [
        isDisabled,
        range,
        values,
        getValueFromPosition,
        handleValueChange,
        onChangeCommitted,
        currentValue,
    ]);
    // Handle track click
    const handleTrackClick = useCallback((e) => {
        if (isDisabled || dragIndex !== null)
            return;
        const newValue = getValueFromPosition(e.clientX);
        if (range) {
            // Find closest thumb
            const distances = values.map((val) => Math.abs(val - newValue));
            const closestIndex = distances[0] <= distances[1] ? 0 : 1;
            const newValues = [...values];
            newValues[closestIndex] = newValue;
            // Ensure values don't cross over
            if (closestIndex === 0 && newValue > newValues[1]) {
                newValues[0] = newValues[1];
            }
            else if (closestIndex === 1 && newValue < newValues[0]) {
                newValues[1] = newValues[0];
            }
            handleValueChange(newValues);
            onChangeCommitted === null || onChangeCommitted === void 0 ? void 0 : onChangeCommitted(newValues);
        }
        else {
            handleValueChange(newValue);
            onChangeCommitted === null || onChangeCommitted === void 0 ? void 0 : onChangeCommitted(newValue);
        }
    }, [
        isDisabled,
        dragIndex,
        range,
        values,
        getValueFromPosition,
        handleValueChange,
        onChangeCommitted,
    ]);
    // Handle keyboard navigation
    const handleKeyDown = useCallback((e, thumbIndex) => {
        if (isDisabled)
            return;
        let delta = 0;
        switch (e.key) {
            case "ArrowRight":
            case "ArrowUp":
                delta = step;
                break;
            case "ArrowLeft":
            case "ArrowDown":
                delta = -step;
                break;
            case "PageUp":
                delta = step * 10;
                break;
            case "PageDown":
                delta = -step * 10;
                break;
            case "Home":
                delta = min - values[thumbIndex];
                break;
            case "End":
                delta = max - values[thumbIndex];
                break;
            default:
                return;
        }
        e.preventDefault();
        if (range) {
            const newValues = [...values];
            newValues[thumbIndex] = Math.max(min, Math.min(max, newValues[thumbIndex] + delta));
            // Ensure values don't cross over
            if (thumbIndex === 0 && newValues[0] > newValues[1]) {
                newValues[0] = newValues[1];
            }
            else if (thumbIndex === 1 && newValues[1] < newValues[0]) {
                newValues[1] = newValues[0];
            }
            handleValueChange(newValues);
        }
        else {
            const newValue = Math.max(min, Math.min(max, values[0] + delta));
            handleValueChange(newValue);
        }
    }, [isDisabled, step, min, max, range, values, handleValueChange]);
    // Generate tick marks
    const generateTicks = useCallback(() => {
        if (!showTicks)
            return [];
        const actualTickStep = tickStep !== null && tickStep !== void 0 ? tickStep : step;
        const ticks = [];
        for (let i = min; i <= max; i += actualTickStep) {
            ticks.push(i);
        }
        return ticks;
    }, [showTicks, tickStep, step, min, max]);
    const ticks = generateTicks();
    // Merged theme
    const mergedTheme = useMemo(() => {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
        return ({
            wrapperStyle: (_a = theme.wrapperStyle) !== null && _a !== void 0 ? _a : sliderTheme.wrapperStyle,
            labelStyle: (_b = theme.labelStyle) !== null && _b !== void 0 ? _b : sliderTheme.labelStyle,
            helperTextStyle: (_c = theme.helperTextStyle) !== null && _c !== void 0 ? _c : sliderTheme.helperTextStyle,
            rootStyle: (_d = theme.rootStyle) !== null && _d !== void 0 ? _d : sliderTheme.rootStyle,
            trackStyle: (_e = theme.trackStyle) !== null && _e !== void 0 ? _e : sliderTheme.trackStyle,
            rangeStyle: (_f = theme.rangeStyle) !== null && _f !== void 0 ? _f : sliderTheme.rangeStyle,
            thumbStyle: (_g = theme.thumbStyle) !== null && _g !== void 0 ? _g : sliderTheme.thumbStyle,
            valueDisplayStyle: (_h = theme.valueDisplayStyle) !== null && _h !== void 0 ? _h : sliderTheme.valueDisplayStyle,
            minMaxLabelStyle: (_j = theme.minMaxLabelStyle) !== null && _j !== void 0 ? _j : sliderTheme.minMaxLabelStyle,
            tickStyle: (_k = theme.tickStyle) !== null && _k !== void 0 ? _k : sliderTheme.tickStyle,
        });
    }, [theme]);
    // Calculate filled track dimensions
    const getFilledTrackStyle = () => {
        if (range) {
            const start = getPercentage(Math.min(...values));
            const end = getPercentage(Math.max(...values));
            return {
                left: `${start}%`,
                width: `${end - start}%`,
            };
        }
        const percentage = getPercentage(values[0]);
        return {
            left: 0,
            width: `${percentage}%`,
        };
    };
    // Format value display
    const formatValueDisplay = () => {
        if (Array.isArray(currentValue)) {
            return `${currentValue[0]}${unit} - ${currentValue[1]}${unit}`;
        }
        return `${currentValue}${unit}`;
    };
    const filterId = `slider-liquid-lens-${sliderId}`;
    return (jsxs("div", { className: cn(mergedTheme.wrapperStyle, wrapperClassName), ref: ref, ...props, children: [jsx("svg", { width: "0", height: "0", className: "absolute", "aria-hidden": "true", children: jsx("defs", { children: jsxs("filter", { id: filterId, children: [jsx("feGaussianBlur", { in: "SourceGraphic", stdDeviation: "1", result: "blur" }), jsx("feColorMatrix", { in: "blur", type: "matrix", values: "1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 18 -7", result: "goo" }), jsx("feComposite", { in: "SourceGraphic", in2: "goo", operator: "atop" })] }) }) }), label && (jsx(FormLabel, { htmlFor: sliderId, required: required, className: cn(mergedTheme.labelStyle, labelClassName), children: label })), jsxs("div", { className: "flex items-center gap-4", children: [iconStart && (jsx("div", { className: "flex-shrink-0 text-[var(--color-text-muted)]", children: iconStart })), showMinMax && (jsx("span", { className: cn(mergedTheme.minMaxLabelStyle), children: min })), jsxs("div", { className: cn(mergedTheme.rootStyle, className), "data-disabled": isDisabled || undefined, "data-invalid": isInvalid || undefined, "data-orientation": "horizontal", children: [jsxs("div", { ref: trackRef, className: mergedTheme.trackStyle, onPointerDown: handleTrackClick, role: "presentation", children: [jsx("div", { className: mergedTheme.rangeStyle, style: getFilledTrackStyle() }), showTicks &&
                                        ticks.map((tick) => {
                                            const percentage = getPercentage(tick);
                                            return (jsx("div", { className: mergedTheme.tickStyle, style: { left: `${percentage}%` } }, tick));
                                        })] }), values.map((val, index) => {
                                const percentage = getPercentage(val);
                                return (jsxs("div", { className: cn(mergedTheme.thumbStyle, "outline-[2px] outline-[var(--color-border)]/80 ring-0 shadow-lg p-0"), style: {
                                        left: `${percentage}%`,
                                        transform: "translate(-50%, -50%)",
                                        position: "absolute",
                                        top: "50%",
                                    }, onPointerDown: (e) => handlePointerDown(e, index), onKeyDown: (e) => handleKeyDown(e, index), role: "slider", "aria-valuemin": min, "aria-valuemax": max, "aria-valuenow": val, "aria-orientation": "horizontal", "aria-label": ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : (range ? `Slider thumb ${index + 1}` : "Slider"), "aria-labelledby": ariaLabelledby, "aria-describedby": ariaDescribedby !== null && ariaDescribedby !== void 0 ? ariaDescribedby : helperTextId, tabIndex: isDisabled ? -1 : 0, "data-disabled": isDisabled || undefined, "data-invalid": isInvalid || undefined, children: [jsx("div", { className: "absolute inset-0 z-0 rounded-full", style: {
                                                backdropFilter: "blur(0.6px)",
                                                WebkitBackdropFilter: "blur(0.6px)",
                                                filter: `url(#${filterId})`,
                                            }, "aria-hidden": "true" }), jsx("div", { className: "absolute inset-0 z-[1] rounded-full bg-[var(--color-surface)]/90", "aria-hidden": "true" }), jsx("div", { className: "absolute inset-0 z-[2] rounded-full", style: {
                                                boxShadow: "inset 1px 1px 0 rgba(255,255,255,0.35), inset 1px 3px 0 rgba(0,0,0,0.03), inset 0 0 14px rgba(255,255,255,0.25), inset -1px -1px 0 rgba(0,0,0,0.06)",
                                            }, "aria-hidden": "true" })] }, index));
                            }), name && (jsx("input", { type: "hidden", name: name, value: Array.isArray(currentValue)
                                    ? currentValue.join(",")
                                    : currentValue }))] }), showMinMax && (jsx("span", { className: cn(mergedTheme.minMaxLabelStyle), children: max })), showValue && (jsx("div", { className: cn(mergedTheme.valueDisplayStyle), children: formatValueDisplay() })), iconEnd && (jsx("div", { className: "flex-shrink-0 text-[var(--color-text-muted)]", children: iconEnd }))] }), helperText && (jsx("div", { id: helperTextId, className: cn(mergedTheme.helperTextStyle, helperTextClassName), children: helperText }))] }));
});
Slider.displayName = "Slider";

export { Slider };
