import {useCallback, useEffect, useRef, useState} from 'react';

import {VideoState, VideoStatus} from '../interfaces';

interface UseVideoSliderProps {
  currentTime: number;
  duration: number;
  status: VideoStatus;
  onSeekTime: (time: number) => void;
  onUpdateVideoState: (updates: Partial<VideoState>) => void;
  onInteraction: () => void;
}

export function useVideoSlider({
  currentTime,
  duration,
  status,
  onSeekTime,
  onUpdateVideoState,
  onInteraction,
}: UseVideoSliderProps) {
  const [sliderValue, setSliderValue] = useState(0);
  const [isSliding, setIsSliding] = useState(false);
  const progressRef = useRef<number>(0);

  // Update slider value based on current time
  useEffect(() => {
    if (!isSliding && duration > 0) {
      const newSliderValue = currentTime / duration;
      const currentProgress = Math.floor(currentTime);
      const lastProgress = progressRef.current;

      // Update if there's a whole second change OR if we're very close to the end
      const isNearEnd = newSliderValue >= 0.95;
      if (
        currentProgress !== lastProgress ||
        isNearEnd ||
        status === VideoStatus.Finished
      ) {
        // Allow seeking even when video is finished, but ensure we don't exceed bounds
        const finalValue = Math.min(1, Math.max(0, newSliderValue));
        setSliderValue(finalValue);
        progressRef.current = currentProgress;
      }
    }
  }, [currentTime, isSliding, duration, status]);

  // Reset slider when video is restarted after being finished
  useEffect(() => {
    if (status !== VideoStatus.Finished && currentTime === 0) {
      setSliderValue(0);
      progressRef.current = 0;
    }
  }, [status, currentTime]);

  const onSlidingStart = useCallback(() => {
    setIsSliding(true);
    onInteraction();
  }, [onInteraction]);

  const onValueChange = useCallback(
    (value: number) => {
      setSliderValue(value);
      onInteraction();
    },
    [onInteraction],
  );

  const onSlidingComplete = useCallback(
    (value: number) => {
      setIsSliding(false);
      const time = value * duration;
      onSeekTime(time);

      // Update status to paused when seeking to any position (except when seeking to 0)
      const newStatus = time === 0 ? VideoStatus.Playing : VideoStatus.Paused;
      onUpdateVideoState({currentTime: time, status: newStatus});
      onInteraction();
    },
    [onSeekTime, onUpdateVideoState, duration, onInteraction],
  );

  const onReplay = useCallback(() => {
    progressRef.current = -1;
    setSliderValue(0);
  }, []);

  return {
    sliderValue,
    isSliding,
    onSlidingStart,
    onValueChange,
    onSlidingComplete,
    onReplay,
  };
}
