import React, { useCallback, useMemo, useState } from 'react';
import MultiSlider from '@ptomasroos/react-native-multi-slider';

import type { LayoutChangeEvent, StyleProp, ViewStyle } from 'react-native';
import { View } from 'react-native';
import { useTheme } from '../../theme';
import { StyledMarker } from './StyledRangeSlider';
import {
  DISABLED_UNSELECTED_TRACK_OPACITY,
  DISABLED_SELECTED_TRACK_OPACITY,
} from './constants';

export type SliderRangeValue = {
  start: number;
  end: number;
};

interface RangeSliderProps {
  /**
   * Minimum value of the slider.
   */
  minimumValue: number;
  /**
   * Maximum value of the slider.
   */
  maximumValue: number;
  /**
   * Step value of the slider.
   * The value should be between 1 and (maximumValue - minimumValue).
   * Defaults to 1.
   */
  step?: number;
  /**
   * Range value of the slider.
   * Defaults to minimumValue.
   */
  value?: SliderRangeValue;
  /**
   * Whether the two markers should be allowed to overlap.
   * Defaults to false.
   */
  allowOverlap?: boolean;
  /**
   * Callback continuously called while the user is dragging the slider.
   */
  onValueChange?: (value: SliderRangeValue) => void;
  /**
   * Callback that is called when the user picks up the slider.
   * The initial value is passed as an argument to the callback handler.
   */
  onSlidingStart?: () => void;
  /**
   * Callback that is called when the user releases the slider, regardless if the value has changed.
   * The current value is passed as an argument to the callback handler.
   */
  onSlidingComplete?: (value: SliderRangeValue) => void;
  /**
   * Whether the slider is disabled.
   */
  disabled?: boolean;
  /**
   * Additional style.
   */
  style?: StyleProp<ViewStyle>;
  /**
   * Testing id of the component.
   */
  testID?: string;
}

const Slider = ({
  minimumValue,
  maximumValue,
  step = 1,
  value,
  onValueChange,
  onSlidingStart,
  onSlidingComplete,
  disabled = false,
  style,
  testID,
  allowOverlap = false,
}: RangeSliderProps) => {
  const theme = useTheme();
  const handleTwoWaySliderChange = React.useCallback(
    (values: number[]) => {
      if (onValueChange) {
        onValueChange({ start: values[0], end: values[1] });
      }
    },
    [onValueChange]
  );
  const [layoutSize, setLayoutSize] = useState({ width: 0, height: 0 });
  const nativeValue = useMemo(() => {
    return [value?.start ?? minimumValue, value?.end ?? maximumValue];
  }, [value?.start, value?.end, minimumValue, maximumValue]);

  const {
    unselectedTrack,
    disabledUnselectedTrack,
    selectedTrack,
    disabledSelectedTrack,
  } = theme.__hd__.slider.colors;

  const { trackHeight } = theme.__hd__.slider.sizes;

  // Define styles for disabled and enabled states
  const disabledStyles = {
    track: {
      opacity: DISABLED_UNSELECTED_TRACK_OPACITY,
      backgroundColor: disabledUnselectedTrack,
      height: trackHeight,
    },
    selected: {
      opacity: DISABLED_SELECTED_TRACK_OPACITY,
      backgroundColor: disabledSelectedTrack,
    },
  };

  const enabledStyles = {
    track: {
      backgroundColor: unselectedTrack,
      height: trackHeight,
    },
    selected: {
      backgroundColor: selectedTrack,
    },
  };

  // Use styles based on the `disabled` state
  const trackStyle = disabled ? disabledStyles.track : enabledStyles.track;
  const selectedStyle = disabled
    ? disabledStyles.selected
    : enabledStyles.selected;

  const handleOnValueChangeStart = useCallback(() => {
    if (onSlidingStart) {
      onSlidingStart();
    }
  }, [onSlidingStart]);

  const handleOnValueChangeFinish = useCallback(
    (values: number[]) => {
      if (onSlidingComplete) {
        onSlidingComplete({
          start: values[0],
          end: values[1],
        });
      }
    },
    [onSlidingComplete]
  );

  const onLayoutCallback = useCallback((event: LayoutChangeEvent) => {
    setLayoutSize({
      width: event.nativeEvent.layout.width,
      height: event.nativeEvent.layout.height,
    });
  }, []);

  const CustomMarker = useMemo(() => {
    return () => <StyledMarker themeDisabled={disabled} />;
  }, [disabled]);

  return (
    <View
      onLayout={onLayoutCallback}
      style={style}
      testID={testID}
      accessibilityState={{
        disabled,
      }}
    >
      <MultiSlider
        values={nativeValue}
        onValuesChange={handleTwoWaySliderChange}
        onValuesChangeStart={handleOnValueChangeStart}
        onValuesChangeFinish={handleOnValueChangeFinish}
        sliderLength={layoutSize.width}
        min={minimumValue}
        max={maximumValue}
        step={step}
        enabledOne={!disabled}
        enabledTwo={!disabled}
        allowOverlap={allowOverlap}
        trackStyle={trackStyle}
        selectedStyle={selectedStyle}
        customMarker={CustomMarker}
      />
    </View>
  );
};

export default Slider;
