import { useEffect, useRef, useState, useContext } from "react";
import Hls from "hls.js";

import { OutletContext } from "../AppMainLayout";

const useVideoPlayer = ({ src, streamSrc }) => {
  const videoRef = useRef(null);
  const [isReady, setIsReady] = useState(false);
  const [isBuffering, setIsBuffering] = useState(false);
  const [isPlaying, setIsPlaying] = useState(false);
  const [error, setError] = useState(null);
  const [progress, setProgress] = useState({ currentTime: 0, duration: 0 });
  const { accessToken, generalData } = useContext(OutletContext);

  const accountId = generalData?.selectedAccount?.id;

  const url = src || streamSrc;

  const play = () => {
    if (videoRef.current && isReady) {
      videoRef.current.play();
    }
  };

  const pause = () => {
    if (videoRef.current && isReady) {
      videoRef.current.pause();
    }
  };

  const stop = () => {
    if (videoRef.current && isReady) {
      videoRef.current.pause();
      videoRef.current.currentTime = 0;
    }
  };

  useEffect(() => {
    const video = videoRef.current;
    let hls;

    const handlePlay = () => setIsPlaying(true);
    const handlePause = () => setIsPlaying(false);
    const handleEnded = () => setIsPlaying(false);
    const handleTimeUpdate = () => {
      setProgress({
        currentTime: video.currentTime,
        duration: video.duration,
      });
    };

    const handleWaiting = () => setIsBuffering(true);
    const handleCanPlay = () => {
      setIsBuffering(false);
      setIsReady(true);
    };

    const attachEvents = () => {
      video.addEventListener("play", handlePlay);
      video.addEventListener("pause", handlePause);
      video.addEventListener("ended", handleEnded);
      video.addEventListener("timeupdate", handleTimeUpdate);
      video.addEventListener("waiting", handleWaiting);
      video.addEventListener("canplay", handleCanPlay);
    };

    const detachEvents = () => {
      video.removeEventListener("play", handlePlay);
      video.removeEventListener("pause", handlePause);
      video.removeEventListener("ended", handleEnded);
      video.removeEventListener("timeupdate", handleTimeUpdate);
      video.removeEventListener("waiting", handleWaiting);
      video.removeEventListener("canplay", handleCanPlay);
    };

    if (!src && Hls.isSupported()) {
      hls = new Hls({
        xhrSetup: function (xhr, url) {
          // Don't add _account to presigned URLs (they already have signatures)
          const isPresignedUrl = url.includes('X-Amz-Algorithm') || url.includes('digitaloceanspaces.com');
          const modifiedURL = isPresignedUrl ? url : `${url}?_account=${accountId}`;
          xhr.open("GET", modifiedURL, true);
          // Don't add auth headers to presigned URLs
          if (!isPresignedUrl && accessToken) {
            xhr.setRequestHeader("Authorization", `Bearer ${accessToken}`);
          }
        },
        lowLatencyMode: true,
      });

      hls.attachMedia(video);
      hls.loadSource(url);

      hls.on(Hls.Events.MANIFEST_PARSED, () => {
        setIsReady(true);
        setError(null);
      });

      hls.on(Hls.Events.BUFFER_STALLED, () => setIsBuffering(true));
      hls.on(Hls.Events.BUFFER_APPENDED, () => setIsBuffering(false));

      hls.on(Hls.Events.ERROR, (event, data) => {
        console.warn("HLS error", data);
        setError(data);
        if (data.fatal) {
          if (data.type === Hls.ErrorTypes.NETWORK_ERROR) {
            hls.startLoad();
          } else if (data.type === Hls.ErrorTypes.MEDIA_ERROR) {
            hls.recoverMediaError();
          } else {
            hls.destroy();
          }
        }
      });
    } else if (video.canPlayType("application/vnd.apple.mpegurl") && !src) {
      video.src = url;
      video.addEventListener("loadedmetadata", () => {
        setIsReady(true);
      });
    } else {
      video.src = src;
      video.load();
      setIsReady(true);
    }

    attachEvents();

    return () => {
      if (hls) hls.destroy();
      detachEvents();
    };
  }, [src, streamSrc, accountId, accessToken]);

  return {
    videoRef,
    isReady,
    isPlaying,
    isBuffering,
    progress,
    error,
    play,
    pause,
    stop,
  };
};

export default useVideoPlayer;
