/**
 * RangeInput Component
 *
 * Displays a range input for filtering numeric values (e.g., price range)
 * Integrates with SearchStateManager for automatic state sync
 */
import React, { useState, useCallback, useEffect } from 'react';
import { useSearchContext } from './SearchProvider';
import { useSearchState } from '../hooks/useSearchState';
import { clsx } from 'clsx';
/**
 * Helper to parse range values from refinements
 */
const parseRangeFromRefinements = (refinements, field) => {
    let min;
    let max;
    refinements.forEach(r => {
        if (r.field === field) {
            // Parse >=X format
            const minMatch = r.value.match(/^>=(\d+(?:\.\d+)?)$/);
            if (minMatch) {
                min = parseFloat(minMatch[1]);
            }
            // Parse <=X format
            const maxMatch = r.value.match(/^<=(\d+(?:\.\d+)?)$/);
            if (maxMatch) {
                max = parseFloat(maxMatch[1]);
            }
        }
    });
    return { min, max };
};
export const RangeInput = ({ field, label, min, max, currentMin: currentMinProp, currentMax: currentMaxProp, step = 1, onRangeChange, renderRangeInput, className, style, theme: customTheme, showApplyButton = true, placeholder = { min: 'Min', max: 'Max' }, syncWithState = true, }) => {
    const { theme } = useSearchContext();
    const { refinements, addRefinement, removeRefinement } = useSearchState();
    const rangeInputTheme = customTheme || {};
    // 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.
    const stateRange = !syncWithState
        ? { min: undefined, max: undefined }
        : parseRangeFromRefinements(refinements, field);
    const [internalMin, setInternalMin] = useState(currentMinProp ?? stateRange.min);
    const [internalMax, setInternalMax] = useState(currentMaxProp ?? stateRange.max);
    const [appliedMin, setAppliedMin] = useState(currentMinProp ?? stateRange.min);
    const [appliedMax, setAppliedMax] = useState(currentMaxProp ?? stateRange.max);
    // Sync internal state when StateManager refinements change
    useEffect(() => {
        if (syncWithState) {
            if (stateRange.min !== appliedMin || stateRange.max !== appliedMax) {
                setInternalMin(stateRange.min);
                setInternalMax(stateRange.max);
                setAppliedMin(stateRange.min);
                setAppliedMax(stateRange.max);
            }
        }
    }, [syncWithState, stateRange.min, stateRange.max]);
    const currentMin = currentMinProp !== undefined ? currentMinProp : internalMin;
    const currentMax = currentMaxProp !== undefined ? currentMaxProp : internalMax;
    // Helper to 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); // Don't trigger search yet
            }
        });
        // Add new range refinements
        if (minVal !== undefined) {
            addRefinement(field, `>=${minVal}`, false); // Don't trigger search yet
        }
        if (maxVal !== undefined) {
            addRefinement(field, `<=${maxVal}`, true); // Trigger search on the last update
        }
        else if (minVal !== undefined) {
            // If only min is set, trigger search now
            addRefinement(field, `>=${minVal}`, true);
        }
    }, [syncWithState, field, refinements, addRefinement, removeRefinement]);
    const handleMinChange = useCallback((e) => {
        const value = e.target.value === '' ? undefined : parseFloat(e.target.value);
        setInternalMin(value);
        if (!showApplyButton) {
            updateStateManager(value, currentMax);
            if (onRangeChange) {
                onRangeChange(value, currentMax);
            }
        }
    }, [currentMax, showApplyButton, onRangeChange, updateStateManager]);
    const handleMaxChange = useCallback((e) => {
        const value = e.target.value === '' ? undefined : parseFloat(e.target.value);
        setInternalMax(value);
        if (!showApplyButton) {
            updateStateManager(currentMin, value);
            if (onRangeChange) {
                onRangeChange(currentMin, value);
            }
        }
    }, [currentMin, showApplyButton, onRangeChange, updateStateManager]);
    const handleApply = useCallback(() => {
        setAppliedMin(internalMin);
        setAppliedMax(internalMax);
        updateStateManager(internalMin, internalMax);
        if (onRangeChange) {
            onRangeChange(internalMin, internalMax);
        }
    }, [internalMin, internalMax, onRangeChange, updateStateManager]);
    const handleReset = useCallback(() => {
        setInternalMin(undefined);
        setInternalMax(undefined);
        setAppliedMin(undefined);
        setAppliedMax(undefined);
        // Clear refinements for this field from StateManager
        if (syncWithState) {
            refinements.forEach(r => {
                if (r.field === field) {
                    removeRefinement(field, r.value, true);
                }
            });
        }
        if (onRangeChange) {
            onRangeChange(undefined, undefined);
        }
    }, [syncWithState, field, refinements, removeRefinement, onRangeChange]);
    const defaultRenderRangeInput = () => (React.createElement("div", { className: clsx(rangeInputTheme.container, className), style: style },
        label && (React.createElement("label", { className: rangeInputTheme.label, style: {
                display: 'block',
                fontSize: theme.typography.fontSize.medium,
                fontWeight: 'bold',
                marginBottom: theme.spacing.small,
                color: theme.colors.text,
            } }, label)),
        React.createElement("div", { className: rangeInputTheme.inputGroup, style: {
                display: 'flex',
                alignItems: 'center',
                gap: theme.spacing.small,
            } },
            React.createElement("input", { type: "number", min: min, max: max, step: step, value: currentMin !== undefined ? currentMin : '', onChange: handleMinChange, placeholder: placeholder.min, className: clsx(rangeInputTheme.input), style: {
                    flex: 1,
                    padding: theme.spacing.small,
                    fontSize: theme.typography.fontSize.medium,
                    backgroundColor: theme.colors.background,
                    color: theme.colors.text,
                    border: `1px solid ${theme.colors.border}`,
                    borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
                    outline: 'none',
                } }),
            React.createElement("span", { className: rangeInputTheme.separator, style: {
                    color: theme.colors.text,
                    opacity: 0.7,
                } }, "to"),
            React.createElement("input", { type: "number", min: min, max: max, step: step, value: currentMax !== undefined ? currentMax : '', onChange: handleMaxChange, placeholder: placeholder.max, className: clsx(rangeInputTheme.input), style: {
                    flex: 1,
                    padding: theme.spacing.small,
                    fontSize: theme.typography.fontSize.medium,
                    backgroundColor: theme.colors.background,
                    color: theme.colors.text,
                    border: `1px solid ${theme.colors.border}`,
                    borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
                    outline: 'none',
                } }),
            showApplyButton && (React.createElement("button", { type: "button", onClick: handleApply, className: rangeInputTheme.button, style: {
                    padding: `${theme.spacing.small} ${theme.spacing.medium}`,
                    backgroundColor: theme.colors.primary,
                    color: '#fff',
                    border: 'none',
                    borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
                    cursor: 'pointer',
                    fontSize: theme.typography.fontSize.small,
                    fontWeight: '500',
                } }, "Apply")),
            (appliedMin !== undefined || appliedMax !== undefined || currentMin !== undefined || currentMax !== undefined) && (React.createElement("button", { type: "button", onClick: handleReset, style: {
                    padding: `${theme.spacing.small} ${theme.spacing.medium}`,
                    backgroundColor: 'transparent',
                    color: theme.colors.text,
                    border: `1px solid ${theme.colors.border}`,
                    borderRadius: typeof theme.borderRadius === 'string' ? theme.borderRadius : theme.borderRadius.medium,
                    cursor: 'pointer',
                    fontSize: theme.typography.fontSize.small,
                } }, "Reset")))));
    if (renderRangeInput) {
        return (React.createElement("div", { className: clsx(rangeInputTheme.container, className), style: style }, renderRangeInput({
            min: currentMin,
            max: currentMax,
            onMinChange: (value) => {
                setInternalMin(value);
                if (!showApplyButton && onRangeChange) {
                    onRangeChange(value, currentMax);
                }
            },
            onMaxChange: (value) => {
                setInternalMax(value);
                if (!showApplyButton && onRangeChange) {
                    onRangeChange(currentMin, value);
                }
            },
            onApply: handleApply,
        })));
    }
    return defaultRenderRangeInput();
};
