"use client";

import { Player, PlayerEvent } from "@lottiefiles/react-lottie-player";
import { usePathname } from "next/navigation";
import { useState, useEffect, useRef } from "react";
import styles from "./lottie-loader.module.css";

const LottieLoader = () => {
  const pathname = usePathname();
  const [isLoading, setIsLoading] = useState(true);
  const [isInitialLoad, setIsInitialLoad] = useState(true);
  const [isMounted, setIsMounted] = useState(false);
  const [shouldAutoplay, setShouldAutoplay] = useState(true);
  const [isFadingOut, setIsFadingOut] = useState(false);
  const hasCompletedRef = useRef(false);
  const isFadingOutRef = useRef(false);
  const timerRef = useRef<NodeJS.Timeout | null>(null);
  const fadeOutTimerRef = useRef<NodeJS.Timeout | null>(null);
  const previousPathnameRef = useRef<string | null>(null);
  const playerKeyRef = useRef(0);
  const lottieInstanceRef = useRef<{
    stop: () => void;
    pause: () => void;
  } | null>(null);

  useEffect(() => {
    setIsMounted(true);
    // Set initial pathname
    previousPathnameRef.current = pathname;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  useEffect(() => {
    // Handle initial page load
    if (
      isInitialLoad &&
      isMounted &&
      !hasCompletedRef.current &&
      !isFadingOutRef.current
    ) {
      // Fallback timer - animation is ~6.6 seconds (191 frames / 30fps / 0.96 speed)
      // Add buffer for smooth transition
      timerRef.current = setTimeout(() => {
        if (!hasCompletedRef.current && !isFadingOutRef.current) {
          hasCompletedRef.current = true;
          isFadingOutRef.current = true;
          setIsFadingOut(true);
          fadeOutTimerRef.current = setTimeout(() => {
            setIsInitialLoad(false);
            setIsLoading(false);
          }, 400); // Match the CSS transition duration
        }
      }, 5300);

      return () => {
        if (timerRef.current) {
          clearTimeout(timerRef.current);
        }
        if (fadeOutTimerRef.current) {
          clearTimeout(fadeOutTimerRef.current);
        }
      };
    }
  }, [isInitialLoad, isMounted]);

  useEffect(() => {
    // Handle route changes - show loader for actual transition duration
    // Only trigger if pathname actually changed and it's not the initial load
    if (
      !isInitialLoad &&
      isMounted &&
      previousPathnameRef.current !== null &&
      previousPathnameRef.current !== pathname
    ) {
      // Immediately reset all states for new route - do this synchronously
      hasCompletedRef.current = false;
      isFadingOutRef.current = false;
      setShouldAutoplay(true);
      setIsFadingOut(false);
      setIsLoading(true); // This must be set BEFORE any return null can happen
      lottieInstanceRef.current = null;
      playerKeyRef.current += 1; // Force Player remount with new key

      // Detect when the new page is loaded/ready
      // Use multiple strategies to detect page readiness
      const checkPageReady = () => {
        // Strategy 1: Check if main content is rendered
        const mainContent = document.querySelector("main");
        if (mainContent && mainContent.children.length > 0) {
          return true;
        }
        // Strategy 2: Check if document is ready
        if (document.readyState === "complete") {
          return true;
        }
        return false;
      };

      // Use requestAnimationFrame to wait for next paint cycle
      // This ensures React has rendered the new route
      const rafId = requestAnimationFrame(() => {
        // Double RAF to ensure rendering is complete
        requestAnimationFrame(() => {
          // Small delay to ensure all content is loaded
          const checkReady = () => {
            if (checkPageReady() && !isFadingOutRef.current) {
              // Page is ready, start fade-out
              isFadingOutRef.current = true;
              setIsFadingOut(true);
              fadeOutTimerRef.current = setTimeout(() => {
                setIsLoading(false);
              }, 400); // Match the CSS transition duration
            } else {
              // Page not ready yet, check again
              setTimeout(checkReady, 50); // Check every 50ms
            }
          };

          // Start checking after a small initial delay
          setTimeout(checkReady, 100);
        });
      });

      return () => {
        cancelAnimationFrame(rafId);
        if (fadeOutTimerRef.current) {
          clearTimeout(fadeOutTimerRef.current);
        }
      };
    }

    // Update previous pathname after checking
    previousPathnameRef.current = pathname;
  }, [pathname, isInitialLoad, isMounted]);

  const handleLottieRef = (
    instance: { stop: () => void; pause: () => void } | null
  ) => {
    lottieInstanceRef.current = instance;
  };

  const handleEvent = (event: PlayerEvent) => {
    if (
      event === PlayerEvent.Complete &&
      !hasCompletedRef.current &&
      !isFadingOutRef.current
    ) {
      hasCompletedRef.current = true;
      isFadingOutRef.current = true;
      // Stop the animation instance to prevent restart
      if (lottieInstanceRef.current) {
        try {
          lottieInstanceRef.current.stop();
          lottieInstanceRef.current.pause();
        } catch {
          // Ignore errors if instance is not available
        }
      }
      // Disable autoplay to prevent restart
      setShouldAutoplay(false);
      // Clear the fallback timer
      if (timerRef.current) {
        clearTimeout(timerRef.current);
        timerRef.current = null;
      }
      // Start fade-out transition immediately
      setIsFadingOut(true);
      // Wait for fade-out transition to complete before unmounting
      fadeOutTimerRef.current = setTimeout(() => {
        setIsInitialLoad(false);
        setIsLoading(false);
      }, 400); // Match the CSS transition duration (400ms)
    }
  };

  // Keep component mounted to detect route changes
  if (!isMounted) return null;

  // Only render the loader when it should be visible
  // But keep the component mounted (return null, don't unmount) to detect route changes
  if (!isLoading && !isFadingOut) {
    // Component stays mounted but doesn't render - this allows useEffect to detect route changes
    return null;
  }

  return (
    <div
      className={`${styles.logoReveal} ${isFadingOut ? styles.fadingOut : ""}`}
    >
      <div className={styles.playerWrapper}>
        <Player
          key={`lottie-loader-player-${pathname}-${playerKeyRef.current}`}
          lottieRef={handleLottieRef}
          autoplay={shouldAutoplay}
          className={styles.lottiePlayer}
          src="/animations/nre_logo_anim.json"
          speed={1.2}
          loop={false}
          onEvent={handleEvent}
          keepLastFrame={true}
          rendererSettings={{
            preserveAspectRatio: "xMidYMid meet",
          }}
        />
      </div>
    </div>
  );
};

export default LottieLoader;
