import React, { useEffect, useState } from "react";
import cls from "classnames";
import { classes } from "../../Slider.tokens";
import { useRangeHandlers } from "../../hooks/useRangeHandlers";
import { getTickStyle } from "../../utils/getTickStyle";
import { getSingleSliderLayout } from "../../utils/getSingleSliderLayout";
import { Label, LabelContent, LabelWrapper, ScaleTick, ScaleTickDot, ScaleTicksWrapper, SingleWrapper, SliderBaseWrapper, SliderContainer, StyledCurrentValue, StyledProgress, StyledRange, StyledRangeValue, StyledTrack } from "./Single.styles";
const clamp = (value, min, max)=>Math.max(min, Math.min(value, max));
export const SingleSlider = ({ // value
min, max, value: outerValue, defaultValue, name, step = 1, // label
label, labelContentLeft, labelContent, labelPlacement = 'top', labelReversed, // scale
showScale, showRangeValues, scaleAlign = 'bottom', hideMinValueDiff, hideMaxValueDiff, // pointer
pointerSize = 'small', pointerVisibility = 'always', showCurrentValue, currentValueVisibility = 'always', // layout
orientation = 'horizontal', sliderAlign = 'left', reversed, valuePlacement, multipleStepSize = 10, // deprecated
rangeValuesPlacement: rangeValuesPlacementOld, // state
disabled, // events
onChange, onChangeCommitted, // a11y
ariaLabel, // scale
scaleTicks, // остальные HTMLAttributes идут на SliderContainer
...rest })=>{
    const isVertical = orientation === 'vertical';
    const [isHovered, setIsHovered] = useState(false);
    const clampedOuterValue = outerValue !== undefined ? clamp(outerValue, min, max) : undefined;
    const clampedDefaultValue = defaultValue !== undefined ? clamp(defaultValue, min, max) : undefined;
    const [dragValue, setDragValue] = useState(clampedDefaultValue ?? min);
    const value = clampedOuterValue ?? dragValue;
    // Округляем значение, если оно не кратно новому шагу
    useEffect(()=>{
        const remainder = (value - min) % step;
        if (Math.abs(remainder) > 0.000001) {
            const roundedValue = Math.round((value - min) / step) * step + min;
            const validValue = Math.max(min, Math.min(max, roundedValue));
            setDragValue(validValue);
            if (outerValue !== undefined) {
                emitChange(validValue);
            }
        }
    }, [
        step,
        min,
        max,
        value,
        outerValue
    ]);
    const { innerShowScale, innerShowCurrentValue, hasLabelContent, labelPlacementClass, rangeValuesPlacement, scaleAlignClass, labelVerticalPlacement, showPointer, currentValueStyle, progressSizeStyle, rangeMinValueOpacity, rangeMaxValueOpacity } = getSingleSliderLayout({
        value,
        min,
        max,
        isVertical,
        isHovered,
        reversed,
        scaleTicks,
        showRangeValues,
        showScale,
        showCurrentValue,
        currentValueVisibility,
        label,
        labelContentLeft,
        labelContent,
        labelPlacement,
        sliderAlign,
        rangeValuesPlacementOld,
        scaleAlign,
        pointerSize,
        pointerVisibility,
        valuePlacement
    });
    const emitChange = (newValue)=>{
        if (!onChange) return;
        if (outerValue !== undefined || !name) {
            onChange(newValue);
            return;
        }
        onChange({
            target: {
                value: newValue,
                name
            }
        });
    };
    const handleTickClick = (tick)=>{
        if (disabled) {
            return;
        }
        const clamped = clamp(tick, min, max);
        if (outerValue === undefined) {
            setDragValue(clamped);
        }
        emitChange(clamped);
        if (onChangeCommitted) {
            onChangeCommitted(clamped);
        }
    };
    const { handleChange, handleChangeCommitted, handleKeyDown } = useRangeHandlers({
        min,
        max,
        value,
        step,
        multipleStepSize,
        isControlled: outerValue !== undefined,
        onSetValue: setDragValue,
        onEmit: emitChange,
        onCommit: onChangeCommitted
    });
    return /*#__PURE__*/ React.createElement(SingleWrapper, {
        className: cls(labelPlacementClass, scaleAlignClass, {
            [classes.verticalOrientation]: isVertical,
            [classes.labelContentReversed]: labelReversed,
            [classes.labelPlacementBottom]: labelVerticalPlacement === 'bottom',
            [classes.labelAlignRight]: sliderAlign === 'left',
            [classes.labelAlignLeft]: sliderAlign === 'right',
            [classes.labelAlignCenter]: (sliderAlign === 'center' || sliderAlign === 'none') && !scaleTicks,
            [classes.scalePlacementTop]: scaleAlign === 'top',
            [classes.pointerHidden]: !showPointer
        }),
        hasTicks: Boolean(scaleTicks),
        onPointerEnter: ()=>setIsHovered(true),
        onPointerLeave: ()=>setIsHovered(false)
    }, hasLabelContent && /*#__PURE__*/ React.createElement(LabelWrapper, null, (labelContentLeft || labelContent) && /*#__PURE__*/ React.createElement(LabelContent, null, labelContent), label && /*#__PURE__*/ React.createElement(Label, null, label)), /*#__PURE__*/ React.createElement(SliderBaseWrapper, {
        className: cls({
            [classes.verticalOrientation]: isVertical,
            [classes.rangeValuesPlacementInner]: !isVertical && rangeValuesPlacement !== 'outer',
            [classes.rangeValuesPlacementOuter]: !isVertical && rangeValuesPlacement === 'outer',
            [classes.scalePlacementTop]: scaleAlign === 'top'
        })
    }, innerShowScale && /*#__PURE__*/ React.createElement(StyledRangeValue, {
        className: cls({
            [classes.hideMinValue]: showCurrentValue && (reversed ? hideMaxValueDiff && max - value <= hideMaxValueDiff : hideMinValueDiff && value - min <= hideMinValueDiff),
            [classes.activeRangeValue]: value === min
        }),
        style: {
            opacity: rangeMinValueOpacity
        }
    }, reversed ? max : min), /*#__PURE__*/ React.createElement(SliderContainer, {
        className: cls(isVertical && classes.verticalOrientation, reversed && classes.reversed, {
            [classes.valuePlacementNone]: valuePlacement === 'none',
            [classes.valuePlacementLeft]: valuePlacement === 'left',
            [classes.valuePlacementRight]: valuePlacement === 'right',
            [classes.valuePlacementTop]: valuePlacement === 'top',
            [classes.valuePlacementBottom]: valuePlacement === 'bottom'
        }),
        ...rest
    }, /*#__PURE__*/ React.createElement(StyledTrack, null), /*#__PURE__*/ React.createElement(StyledProgress, {
        style: progressSizeStyle
    }), /*#__PURE__*/ React.createElement(StyledRange, {
        type: "range",
        name: name,
        value: value,
        min: min,
        max: max,
        step: step,
        disabled: disabled,
        showPointer: showPointer,
        datatype: "slider-single",
        "aria-label": ariaLabel,
        "aria-valuemin": min,
        "aria-valuemax": max,
        "aria-valuenow": value,
        "aria-orientation": orientation,
        onChange: handleChange,
        onMouseUp: handleChangeCommitted,
        onTouchEnd: handleChangeCommitted,
        onKeyUp: handleChangeCommitted,
        onKeyDown: handleKeyDown
    }), innerShowCurrentValue && /*#__PURE__*/ React.createElement(StyledCurrentValue, {
        style: currentValueStyle
    }, value)), innerShowScale && /*#__PURE__*/ React.createElement(StyledRangeValue, {
        className: cls(classes.maxRangeValue, {
            [classes.hideMaxValue]: showCurrentValue && (reversed ? hideMinValueDiff && value - min <= hideMinValueDiff : hideMaxValueDiff && max - value <= hideMaxValueDiff),
            [classes.activeRangeValue]: value === max
        }),
        style: {
            opacity: rangeMaxValueOpacity
        }
    }, reversed ? min : max), scaleTicks && /*#__PURE__*/ React.createElement(ScaleTicksWrapper, {
        isVertical: isVertical,
        reversed: reversed
    }, scaleTicks.map((tick)=>{
        const tickStyle = getTickStyle({
            tick,
            min,
            max,
            isVertical,
            reversed: reversed ?? false
        });
        return /*#__PURE__*/ React.createElement(ScaleTick, {
            key: tick,
            tickValue: tick,
            isVertical: isVertical,
            sliderAlign: sliderAlign,
            scaleAlign: scaleAlign,
            style: tickStyle,
            onClick: ()=>handleTickClick(tick)
        }, /*#__PURE__*/ React.createElement(ScaleTickDot, {
            isVertical: isVertical,
            filled: tick <= value,
            reversed: reversed,
            scaleAlign: scaleAlign,
            sliderAlign: sliderAlign
        }));
    }))));
};
