/**
 * RangeSlider Component
 *
 * Visual slider for numeric range filtering
 * Alternative to RangeInput for a more interactive UX
 */
import React, { useState, useCallback, useEffect, useRef } from 'react';
import { useSearchContext } from './SearchProvider';
import { useSearchState } from '../hooks/useSearchState';
import { clsx } from 'clsx';
const SHADOWS = {
    sm: '0 1px 2px rgba(0,0,0,0.05)',
    md: '0 2px 4px rgba(0,0,0,0.1)',
    lg: '0 4px 6px rgba(0,0,0,0.1)',
    xl: '0 10px 15px rgba(0,0,0,0.1)',
};
export const RangeSlider = ({ field, label, min, max, step = 1, currentMin: currentMinProp, currentMax: currentMaxProp, onRangeChange, formatValue = (v) => v.toString(), className, style, theme: customTheme, showValues = true, syncWithState = true, debounceMs = 300, }) => {
    const { theme } = useSearchContext();
    const { refinements, addRefinement, removeRefinement } = useSearchState();
    const rangeSliderTheme = customTheme || {};
    const thumbClass = rangeSliderTheme.thumb || 'seekora-range-slider__thumb';
    // Parse current range from StateManager
    // NOTE: computed every render (no useMemo) because the state manager mutates
    // the refinements array in place — the reference never changes.
    let stateRange;
    if (!syncWithState) {
        stateRange = { min: undefined, max: undefined };
    }
    else {
        let minVal;
        let maxVal;
        refinements.forEach(r => {
            if (r.field === field) {
                const minMatch = r.value.match(/^>=(\d+(?:\.\d+)?)$/);
                if (minMatch)
                    minVal = parseFloat(minMatch[1]);
                const maxMatch = r.value.match(/^<=(\d+(?:\.\d+)?)$/);
                if (maxMatch)
                    maxVal = parseFloat(maxMatch[1]);
            }
        });
        stateRange = { min: minVal, max: maxVal };
    }
    const [internalMin, setInternalMin] = useState(currentMinProp ?? stateRange.min ?? min);
    const [internalMax, setInternalMax] = useState(currentMaxProp ?? stateRange.max ?? max);
    const isDraggingRef = useRef(false);
    const debounceRef = useRef(null);
    const pendingMinRef = useRef(internalMin);
    const pendingMaxRef = useRef(internalMax);
    // Sync with StateManager changes (only when stateRange actually changes, not on drag)
    useEffect(() => {
        if (syncWithState && !isDraggingRef.current) {
            if (stateRange.min !== undefined)
                setInternalMin(stateRange.min);
            else
                setInternalMin(min);
            if (stateRange.max !== undefined)
                setInternalMax(stateRange.max);
            else
                setInternalMax(max);
        }
    }, [syncWithState, stateRange.min, stateRange.max, min, max]);
    // Update StateManager with range refinements
    const updateStateManager = useCallback((minVal, maxVal) => {
        if (!syncWithState)
            return;
        // Remove existing range refinements for this field
        refinements.forEach(r => {
            if (r.field === field) {
                removeRefinement(field, r.value, false);
            }
        });
        // Add new range refinements — trigger search on the last one added
        const setMin = minVal > min;
        const setMax = maxVal < max;
        if (setMin && setMax) {
            addRefinement(field, `>=${minVal}`, false);
            addRefinement(field, `<=${maxVal}`, true);
        }
        else if (setMin) {
            addRefinement(field, `>=${minVal}`, true);
        }
        else if (setMax) {
            addRefinement(field, `<=${maxVal}`, true);
        }
    }, [syncWithState, field, refinements, addRefinement, removeRefinement, min, max]);
    // Debounced update (during drag only)
    const debouncedUpdate = useCallback((minVal, maxVal) => {
        pendingMinRef.current = minVal;
        pendingMaxRef.current = maxVal;
        if (debounceRef.current) {
            clearTimeout(debounceRef.current);
        }
        debounceRef.current = setTimeout(() => {
            updateStateManager(minVal, maxVal);
            if (onRangeChange) {
                onRangeChange(minVal, maxVal);
            }
        }, debounceMs);
    }, [updateStateManager, onRangeChange, debounceMs]);
    // Handle min slider change
    const handleMinChange = (e) => {
        const value = Math.min(Number(e.target.value), internalMax - step);
        setInternalMin(value);
        isDraggingRef.current = true;
        debouncedUpdate(value, internalMax);
    };
    // Handle max slider change
    const handleMaxChange = (e) => {
        const value = Math.max(Number(e.target.value), internalMin + step);
        setInternalMax(value);
        isDraggingRef.current = true;
        debouncedUpdate(internalMin, value);
    };
    // Handle drag end — flush pending update immediately
    const handleDragEnd = () => {
        isDraggingRef.current = false;
        // Cancel the debounce and commit immediately
        if (debounceRef.current) {
            clearTimeout(debounceRef.current);
            debounceRef.current = null;
        }
        updateStateManager(pendingMinRef.current, pendingMaxRef.current);
        if (onRangeChange) {
            onRangeChange(pendingMinRef.current, pendingMaxRef.current);
        }
    };
    // Handle keyboard navigation for enhanced control (Shift+Arrow for 10x step, Home/End)
    const handleMinKeyDown = (e) => {
        let newValue = null;
        if (e.key === 'Home') {
            e.preventDefault();
            newValue = min;
        }
        else if (e.key === 'End') {
            e.preventDefault();
            newValue = internalMax - step;
        }
        else if (e.shiftKey && (e.key === 'ArrowLeft' || e.key === 'ArrowDown')) {
            e.preventDefault();
            newValue = Math.max(min, internalMin - step * 10);
        }
        else if (e.shiftKey && (e.key === 'ArrowRight' || e.key === 'ArrowUp')) {
            e.preventDefault();
            newValue = Math.min(internalMax - step, internalMin + step * 10);
        }
        if (newValue !== null) {
            setInternalMin(newValue);
            debouncedUpdate(newValue, internalMax);
        }
    };
    const handleMaxKeyDown = (e) => {
        let newValue = null;
        if (e.key === 'Home') {
            e.preventDefault();
            newValue = internalMin + step;
        }
        else if (e.key === 'End') {
            e.preventDefault();
            newValue = max;
        }
        else if (e.shiftKey && (e.key === 'ArrowLeft' || e.key === 'ArrowDown')) {
            e.preventDefault();
            newValue = Math.max(internalMin + step, internalMax - step * 10);
        }
        else if (e.shiftKey && (e.key === 'ArrowRight' || e.key === 'ArrowUp')) {
            e.preventDefault();
            newValue = Math.min(max, internalMax + step * 10);
        }
        if (newValue !== null) {
            setInternalMax(newValue);
            debouncedUpdate(internalMin, newValue);
        }
    };
    // Calculate filled track position
    const minPercent = ((internalMin - min) / (max - min)) * 100;
    const maxPercent = ((internalMax - min) / (max - min)) * 100;
    return (React.createElement("div", { className: clsx(rangeSliderTheme.root, className), style: {
            fontFamily: 'inherit',
            ...style,
        } },
        label && (React.createElement("label", { className: rangeSliderTheme.label, style: {
                display: 'block',
                marginBottom: theme.spacing.small,
                fontSize: theme.typography.fontSize.medium,
                fontWeight: theme.typography.fontWeight?.medium || 500,
                color: theme.colors.text,
            } }, label)),
        React.createElement("div", { className: rangeSliderTheme.slider, style: {
                position: 'relative',
                minHeight: '40px',
                display: 'flex',
                alignItems: 'center',
            } },
            React.createElement("div", { className: rangeSliderTheme.track, style: {
                    position: 'absolute',
                    width: '100%',
                    height: '4px',
                    backgroundColor: theme.colors.border,
                    borderRadius: '2px',
                } }),
            React.createElement("div", { className: rangeSliderTheme.trackFilled, style: {
                    position: 'absolute',
                    left: `${minPercent}%`,
                    width: `${maxPercent - minPercent}%`,
                    height: '4px',
                    backgroundColor: theme.colors.primary,
                    borderRadius: '2px',
                } }),
            React.createElement("input", { type: "range", min: min, max: max, step: step, value: internalMin, onChange: handleMinChange, onMouseUp: handleDragEnd, onTouchEnd: handleDragEnd, onKeyDown: handleMinKeyDown, tabIndex: 0, "aria-valuenow": internalMin, "aria-valuemin": min, "aria-valuemax": max, className: thumbClass, style: {
                    position: 'absolute',
                    width: '100%',
                    height: '4px',
                    background: 'transparent',
                    WebkitAppearance: 'none',
                    appearance: 'none',
                    cursor: 'pointer',
                    pointerEvents: 'none',
                }, "aria-label": `Minimum ${label || field}` }),
            React.createElement("input", { type: "range", min: min, max: max, step: step, value: internalMax, onChange: handleMaxChange, onMouseUp: handleDragEnd, onTouchEnd: handleDragEnd, onKeyDown: handleMaxKeyDown, tabIndex: 0, "aria-valuenow": internalMax, "aria-valuemin": min, "aria-valuemax": max, className: thumbClass, style: {
                    position: 'absolute',
                    width: '100%',
                    height: '4px',
                    background: 'transparent',
                    WebkitAppearance: 'none',
                    appearance: 'none',
                    cursor: 'pointer',
                    pointerEvents: 'none',
                }, "aria-label": `Maximum ${label || field}` })),
        showValues && (React.createElement("div", { className: rangeSliderTheme.values, style: {
                display: 'flex',
                justifyContent: 'space-between',
                marginTop: theme.spacing.small,
                fontSize: theme.typography.fontSize.small,
                color: theme.colors.textSecondary,
            } },
            React.createElement("span", { className: rangeSliderTheme.value }, formatValue(internalMin)),
            React.createElement("span", { className: rangeSliderTheme.value }, formatValue(internalMax)))),
        React.createElement("style", null, `
        .${thumbClass}::-webkit-slider-thumb {
          -webkit-appearance: none;
          appearance: none;
          width: 20px;
          height: 20px;
          background: ${theme.colors.primary};
          border-radius: 50%;
          cursor: pointer;
          pointer-events: all;
          box-shadow: ${SHADOWS.md};
        }
        .${thumbClass}::-moz-range-thumb {
          width: 20px;
          height: 20px;
          background: ${theme.colors.primary};
          border-radius: 50%;
          cursor: pointer;
          pointer-events: all;
          border: none;
          box-shadow: ${SHADOWS.md};
        }
      `)));
};
