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

export interface MediaSyncState {
  currentTime: number;
  duration: number;
  isPlaying: boolean;
  playbackRate: number;
  volume: number;
  isMuted: boolean;
  videoRef: React.RefObject<HTMLVideoElement | null>;
  seekTo: (time: number) => void;
  setPlaybackRate: (rate: number) => void;
  togglePlay: () => void;
  setVolume: (v: number) => void;
  toggleMute: () => void;
}

/**
 * Shared playback state hook. Owns the <video> ref and exposes
 * current time, duration, play state, rate, volume, and control actions.
 * Attach `videoRef` to a <video> element — the hook listens for
 * timeupdate, play, pause, ratechange, volumechange, and loadedmetadata.
 */
export function useMediaSync(): MediaSyncState {
  const videoRef = useRef<HTMLVideoElement | null>(null);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);
  const [playbackRate, setPlaybackRateState] = useState(1);
  const [volume, setVolumeState] = useState(1);
  const [isMuted, setIsMuted] = useState(false);

  useEffect(() => {
    const el = videoRef.current;
    if (!el) return;

    const onTimeUpdate = () => setCurrentTime(el.currentTime);
    const onDurationChange = () => setDuration(el.duration || 0);
    const onPlay = () => setIsPlaying(true);
    const onPause = () => setIsPlaying(false);
    const onRateChange = () => setPlaybackRateState(el.playbackRate);
    const onVolumeChange = () => {
      setVolumeState(el.volume);
      setIsMuted(el.muted);
    };
    const onLoadedMetadata = () => {
      setDuration(el.duration || 0);
      setCurrentTime(el.currentTime);
    };

    el.addEventListener("timeupdate", onTimeUpdate);
    el.addEventListener("durationchange", onDurationChange);
    el.addEventListener("play", onPlay);
    el.addEventListener("pause", onPause);
    el.addEventListener("ratechange", onRateChange);
    el.addEventListener("volumechange", onVolumeChange);
    el.addEventListener("loadedmetadata", onLoadedMetadata);

    return () => {
      el.removeEventListener("timeupdate", onTimeUpdate);
      el.removeEventListener("durationchange", onDurationChange);
      el.removeEventListener("play", onPlay);
      el.removeEventListener("pause", onPause);
      el.removeEventListener("ratechange", onRateChange);
      el.removeEventListener("volumechange", onVolumeChange);
      el.removeEventListener("loadedmetadata", onLoadedMetadata);
    };
  }, []);

  const seekTo = useCallback((time: number) => {
    const el = videoRef.current;
    if (!el) return;
    const safe = Number.isFinite(time) && time >= 0 ? time : 0;
    el.currentTime = Math.min(safe, el.duration || 0);
  }, []);

  const setPlaybackRate = useCallback((rate: number) => {
    const el = videoRef.current;
    if (!el) return;
    const clamped = Math.max(0.5, Math.min(2, rate));
    el.playbackRate = clamped;
  }, []);

  const togglePlay = useCallback(() => {
    const el = videoRef.current;
    if (!el) return;
    if (el.paused) {
      void el.play();
    } else {
      el.pause();
    }
  }, []);

  const setVolume = useCallback((v: number) => {
    const el = videoRef.current;
    if (!el) return;
    el.volume = Math.max(0, Math.min(1, v));
  }, []);

  const toggleMute = useCallback(() => {
    const el = videoRef.current;
    if (!el) return;
    el.muted = !el.muted;
  }, []);

  return {
    currentTime,
    duration,
    isPlaying,
    playbackRate,
    volume,
    isMuted,
    videoRef,
    seekTo,
    setPlaybackRate,
    togglePlay,
    setVolume,
    toggleMute,
  };
}
