/* eslint-disable react-hooks/exhaustive-deps */
import clsx from "clsx";
import {
  useEffect,
  useRef,
  useState,
  MouseEvent as ReactMouseEvent,
  TouchEvent as ReactTouchEvent,
} from "react";

interface IMultiRangeSlider {
  min: number;
  max: number;
  currentMin: number;
  currentMax: number;
  offset: number;
  disabled?: boolean;
  label: string;
  onChange: (value: [number, number]) => void;
}

function MultiRangeSlider({
  currentMax,
  currentMin,
  max,
  min,
  onChange,
  offset,
  label,
  disabled = false,
}: IMultiRangeSlider) {
  const [current, setCurrent] = useState<"min" | "max" | null>(null);

  const rangeRef = useRef<HTMLDivElement>(null);

  function calculateValue(clientX: number, isMin: boolean) {
    if (!rangeRef.current) return;

    const rect = rangeRef.current.getBoundingClientRect();
    const percentage = (clientX - rect.x) / rect.width;
    const newValue = min + percentage * (max - min);

    return isMin
      ? Math.max(Math.min(newValue, currentMax - offset), min)
      : Math.min(Math.max(newValue, currentMin + offset), max);
  }

  const [value, setValue] = useState<[number, number]>([
    currentMin,
    currentMax,
  ]);

  useEffect(() => {
    setValue([currentMin, currentMax]);
  }, [currentMin, currentMax]);

  function handleChange(
    e: MouseEvent | TouchEvent | ReactMouseEvent | ReactTouchEvent
  ) {
    if (!current || disabled) return;

    const { clientX } = "touches" in e ? e.touches[0] : e;
    const newValue = calculateValue(clientX, current === "min");

    if (newValue !== undefined) {
      if (current === "min") setValue([newValue, currentMax]);
      else setValue([currentMin, newValue]);
    }
  }

  function handleMouseUp() {
    setCurrent(null);
    onChange(value.map(Math.ceil) as [number, number]);
  }

  useEffect(() => {
    if (!current) return;
    document.addEventListener("mousemove", handleChange as EventListener);
    document.addEventListener("mouseup", handleMouseUp);
    document.addEventListener("mouseleave", handleMouseUp);
    document.addEventListener("touchmove", handleChange as EventListener);
    document.addEventListener("touchend", handleMouseUp);
    document.addEventListener("touchcancel", handleMouseUp);
    return () => {
      document.removeEventListener("mousemove", handleChange as EventListener);
      document.removeEventListener("mouseup", handleMouseUp);
      document.removeEventListener("mouseleave", handleMouseUp);
      document.removeEventListener("touchmove", handleChange as EventListener);
      document.removeEventListener("touchend", handleMouseUp);
      document.removeEventListener("touchcancel", handleMouseUp);
    };
  }, [current, value]);

  const getThumbStyle = (newValue: number) => ({
    left: `${((newValue - min) / (max - min)) * 100}%`,
  });

  return (
    <div className="2xl:space-y-[0.556vw] space-y-2">
      <p className="text-s text-[#0D1922]/70">{label}</p>
      <div className="bg-white/80 2xl:rounded-[0.833vw] rounded-xl relative 2xl:px-[1.111vw] 2xl:py-[0.972vw] px-4 py-3.5 flex justify-between 2xl:ring-[0.069vw] ring-1 ring-[#E2E2DC]">
        <p className={clsx("text-s", disabled && "text-[#0D1922]/40")}>
          {Intl.NumberFormat("en").format(Math.ceil(value[0]))}
        </p>
        <p className={clsx("text-s", disabled && "text-[#0D1922]/40")}>
          {Intl.NumberFormat("en").format(Math.ceil(value[1]))}
        </p>
        <div className="absolute bottom-0 left-0 w-full 2xl:px-[1.111vw] px-4 translate-y-1/2">
          <div
            className="relative flex 2xl:h-[1.111vw] h-4"
            ref={rangeRef}
            onMouseMove={
              handleChange as React.MouseEventHandler<HTMLDivElement>
            }
            onTouchMove={
              handleChange as React.TouchEventHandler<HTMLDivElement>
            }
          >
            <div
              style={{
                width: `${((value[1] - value[0]) / (max - min)) * 100}%`,
                left: `${((value[0] - min) / (max - min)) * 100}%`,
              }}
              className={clsx(
                "2xl:h-[0.139vw] h-0.5 self-center relative",
                disabled ? "bg-[#D2D2D2]" : "bg-[#00BED7]"
              )}
            />
            {["min", "max"].map((type) => (
              <div
                key={type}
                onMouseDown={() => setCurrent(type as "min" | "max")}
                onTouchStart={() => setCurrent(type as "min" | "max")}
                style={getThumbStyle(type === "min" ? value[0] : value[1])}
                className={clsx(
                  "rounded-full 2xl:w-[1.111vw] 2xl:h-[1.111vw] w-4 h-4 absolute bottom-0 -translate-x-1/2",
                  current === type ? "cursor-grabbing" : "cursor-grab",
                  disabled ? "bg-[#D2D2D2] !cursor-default" : "bg-[#00BED7]"
                )}
              />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

export default MultiRangeSlider;
