import clsx from 'clsx';
import { useRef, useState } from 'react';
import { Slider, SliderThumb, SliderTrack } from 'react-aria-components';
import { twMerge } from 'tailwind-merge';

import { Tooltip } from '@/components/tooltip/Tooltip';
import { InfoIcon } from '@/icons';
import {
  DEFAULT_CREATE_CONTROL_VALUE,
  SliderValueTooltipConfig,
} from '@/utils/constants';

type Props = {
  label: string;
  value?: number;
  onChange: (value: number) => void;
  onChangeEnd?: (value: number) => void;
  labelClassName?: string;
  vertical?: boolean;
  disabled?: boolean;
  defaultValue?: number;
  tooltips?: SliderValueTooltipConfig[];
  tooltipClassName?: string;
  infoTooltip?: string;
};

export const SimpleSlider: React.FC<Props> = ({
  label,
  value,
  disabled = false,
  onChange,
  onChangeEnd,
  labelClassName,
  defaultValue = DEFAULT_CREATE_CONTROL_VALUE,
  tooltips,
  tooltipClassName,
  infoTooltip,
}: Props) => {
  const [isEditing, setIsEditing] = useState(false);
  const [editValue, setEditValue] = useState('');
  const sliderStateRef = useRef<{
    setThumbValue: (index: number, value: number) => void;
  } | null>(null);

  const [valueClassName, setValueClassName] = useState<string>('');

  const getTooltipText = (
    currentValue: number
  ): SliderValueTooltipConfig | null => {
    if (!tooltips) return null;

    const matchingTooltip = tooltips.find(
      (tooltip) => currentValue >= tooltip.min && currentValue <= tooltip.max
    );

    return matchingTooltip ?? null;
  };

  const currentValue = value ?? defaultValue;

  const handleDoubleClick = () => {
    if (!disabled) {
      setIsEditing(true);
      setEditValue(currentValue.toString());
    }
  };

  const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
    if (e.key === 'Enter') {
      const newValue = Math.min(100, Math.max(0, parseInt(editValue) || 0));
      onChange(newValue);
      if (sliderStateRef.current) {
        sliderStateRef.current.setThumbValue(0, newValue);
      }
      setIsEditing(false);
    } else if (e.key === 'Escape') {
      setIsEditing(false);
    }
  };

  const handleBlur = () => {
    setIsEditing(false);
  };

  return (
    <div className='flex flex-1 items-center rounded-[10px] bg-background-primary px-4 py-2'>
      <div
        className={twMerge(
          'flex max-w-[140px] flex-1 items-center gap-1 pr-4 whitespace-nowrap',
          labelClassName || ''
        )}
      >
        <span
          className={clsx('text-sm', {
            'text-foreground-secondary': !disabled,
            'text-foreground-tertiary': disabled,
          })}
        >
          {label}
        </span>
        {infoTooltip && (
          <Tooltip label={infoTooltip} placement='top'>
            <InfoIcon className='h-5 w-5 text-foreground-secondary' />
          </Tooltip>
        )}
      </div>
      <div className='flex h-auto w-full flex-1 flex-row-reverse'>
        <Slider
          aria-label={label}
          value={currentValue}
          className={clsx('w-full', {
            'brightness-50': disabled,
          })}
          onChange={onChange}
          onChangeEnd={onChangeEnd}
          isDisabled={disabled}
        >
          <SliderTrack
            className={clsx('relative h-8 w-full bg-transparent', {
              'cursor-pointer': !disabled,
              'cursor-not-allowed': disabled,
            })}
          >
            {({ state }) => {
              sliderStateRef.current = state;
              const sliderValue = state.getThumbValue(0);
              const { text: tooltipText, valueClassName: _valueClassName } =
                getTooltipText(sliderValue) ?? {};
              if (_valueClassName !== valueClassName) {
                setValueClassName(_valueClassName ?? '');
              }

              return (
                <>
                  <div className='absolute top-0 right-0 bottom-0 left-0 flex flex-row justify-between bg-transparent'>
                    {Array.from({ length: 11 }).map((_, i: number) => {
                      const markerPct = i * 10;
                      const [minOpacity, maxOpacity] = [5, 50];
                      const whiteAlpha = Math.max(
                        maxOpacity - Math.abs(sliderValue - markerPct),
                        minOpacity
                      );
                      return (
                        <div
                          key={i}
                          className='h-8 w-[2px] rounded-full'
                          style={{
                            backgroundColor: `var(--color-foreground-primary)`,
                            opacity: whiteAlpha / 100.0,
                          }}
                        />
                      );
                    })}
                  </div>

                  <SliderThumb
                    className={clsx(
                      'absolute top-0 bottom-0 mt-4 h-full w-3 rounded-full bg-accent-brand shadow',
                      {
                        'cursor-pointer': !disabled,
                        'cursor-not-allowed': disabled,
                      }
                    )}
                  >
                    {tooltipText && !disabled && (
                      <Tooltip
                        label={tooltipText}
                        placement='top'
                        className={tooltipClassName}
                      >
                        <div
                          className='h-full w-full'
                          onDoubleClick={() => {
                            onChange(defaultValue);
                            state.setThumbValue(0, defaultValue);
                          }}
                        />
                      </Tooltip>
                    )}
                  </SliderThumb>
                </>
              );
            }}
          </SliderTrack>
        </Slider>
      </div>
      <div
        className={twMerge(
          'flex max-w-[60px] flex-1 flex-row-reverse whitespace-nowrap',
          labelClassName || ''
        )}
      >
        {isEditing ? (
          <input
            type='number'
            value={editValue}
            onChange={(e) => setEditValue(e.target.value)}
            onKeyDown={handleKeyDown}
            onBlur={handleBlur}
            className='w-12 rounded bg-background-secondary px-1 text-right text-sm text-foreground-secondary'
            min='0'
            max='100'
            autoFocus
          />
        ) : (
          <span
            className={twMerge(
              'cursor-pointer text-sm text-foreground-tertiary',
              valueClassName
            )}
            onDoubleClick={handleDoubleClick}
          >
            {`${currentValue}%`}
          </span>
        )}
      </div>
    </div>
  );
};
