import { useEffect, useRef } from 'react';

/**
 * FadingVideo Component
 * Custom requestAnimationFrame crossfade logic for looping background videos.
 * Opacity fades out at 0.55s before video ends and fades back in on loop start.
 */
export default function FadingVideo({ src, className, style }) {
  const videoRef = useRef(null);
  const rafIdRef = useRef(null);
  const fadingOutRef = useRef(false);

  const FADE_MS = 500;
  const FADE_OUT_LEAD = 0.55; // seconds before end to start fading out

  const fadeTo = (targetOpacity, duration) => {
    if (!videoRef.current) return;
    
    const video = videoRef.current;
    
    // Cancel any ongoing animation frame
    if (rafIdRef.current) {
      cancelAnimationFrame(rafIdRef.current);
    }

    const currentOpacity = parseFloat(video.style.opacity) || 0;
    const opacityDifference = targetOpacity - currentOpacity;
    
    if (opacityDifference === 0) return;

    const startTime = performance.now();

    const animate = (currentTime) => {
      const elapsed = currentTime - startTime;
      const progress = Math.min(elapsed / duration, 1);
      
      // Calculate next opacity
      const nextOpacity = currentOpacity + opacityDifference * progress;
      if (videoRef.current) {
        videoRef.current.style.opacity = nextOpacity.toString();
      }

      if (progress < 1) {
        rafIdRef.current = requestAnimationFrame(animate);
      }
    };

    rafIdRef.current = requestAnimationFrame(animate);
  };

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

    // Initially transparent
    video.style.opacity = '0';

    const handleLoadedData = () => {
      video.style.opacity = '0';
      video.play().catch(() => {});
      fadeTo(1, FADE_MS);
    };

    const handleTimeUpdate = () => {
      if (!video.duration) return;
      const remainingTime = video.duration - video.currentTime;

      // Start fade out at 0.55 seconds before end
      if (!fadingOutRef.current && remainingTime <= FADE_OUT_LEAD && remainingTime > 0) {
        fadingOutRef.current = true;
        fadeTo(0, FADE_MS);
      }
    };

    const handleEnded = () => {
      video.style.opacity = '0';
      
      setTimeout(() => {
        if (!videoRef.current) return;
        videoRef.current.currentTime = 0;
        videoRef.current.play().catch(() => {});
        fadingOutRef.current = false;
        fadeTo(1, FADE_MS);
      }, 100);
    };

    // Listeners
    video.addEventListener('loadeddata', handleLoadedData);
    video.addEventListener('timeupdate', handleTimeUpdate);
    video.addEventListener('ended', handleEnded);

    // If already loaded/ready
    if (video.readyState >= 2) {
      handleLoadedData();
    }

    return () => {
      if (rafIdRef.current) {
        cancelAnimationFrame(rafIdRef.current);
      }
      video.removeEventListener('loadeddata', handleLoadedData);
      video.removeEventListener('timeupdate', handleTimeUpdate);
      video.removeEventListener('ended', handleEnded);
    };
  }, [src]);

  return (
    <video
      ref={videoRef}
      src={src}
      className={className}
      style={{
        ...style,
        transition: 'none', // Ensure NO CSS transitions interfere with our rAF fades
      }}
      autoPlay
      muted
      playsInline
      preload="auto"
    />
  );
}
