"use client";

import React, { useEffect } from "react";
import { usePathname } from "next/navigation";
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";

/**
 * AnimationProvider
 * Initializes GSAP + ScrollTrigger globally, refreshes on route changes,
 * and provides smooth defaults.
 */
export default function AnimationProvider({ children }: { children: React.ReactNode }) {
  const pathname = usePathname();

  const initDecorativeBlocks = () => {
    // Clean up previous block triggers to avoid duplicates
    ScrollTrigger.getAll().forEach((t) => {
      if (t.vars && (t.vars as { id?: string }).id === "block-deco") {
        t.kill();
      }
    });

    const vh = window.innerHeight || document.documentElement.clientHeight;
    const decorativeBlocks = document.querySelectorAll(".block-decoration");
    decorativeBlocks.forEach((block) => {
      ScrollTrigger.create({
        id: "block-deco",
        trigger: block,
        start: "top 92%",
        onEnter: () => {
          setTimeout(() => {
            block.classList.add("animated");
          }, 150);
        },
        onEnterBack: () => {
          setTimeout(() => {
            block.classList.add("animated");
          }, 150);
        },
        onLeave: () => {
          block.classList.remove("animated");
        },
        onLeaveBack: () => {
          block.classList.remove("animated");
        },
      });

      // ScrollTrigger does not fire onEnter for blocks already in view at
      // creation — on larger / taller screens those stayed un-animated.
      // Reveal any block already intersecting the viewport.
      const r = block.getBoundingClientRect();
      if (r.top < vh && r.bottom > 0) {
        block.classList.add("animated");
      }
    });
  };

  useEffect(() => {
    gsap.registerPlugin(ScrollTrigger);

    // Global GSAP defaults for buttery animations
    gsap.defaults({
      ease: "power3.out",
      duration: 0.8,
    });

    // Mobile browsers fire `resize` when the address bar shows/hides while
    // scrolling. Refreshing ScrollTrigger on every one of those caused jumpy /
    // re-hidden animations on phones. Ignore those spurious resizes.
    ScrollTrigger.config({ ignoreMobileResize: true });

    // Run initializations
    initDecorativeBlocks();

    // Refresh on full window load (when all images, styles, and fonts are in place)
    const handleLoad = () => {
      initDecorativeBlocks();
      ScrollTrigger.refresh(true);
    };
    window.addEventListener("load", handleLoad);

    // Refresh on window resize — debounced so dragging the window across
    // breakpoints recomputes trigger positions once it settles, instead of
    // thrashing on every intermediate pixel.
    let resizeTimer: ReturnType<typeof setTimeout>;
    const handleResize = () => {
      clearTimeout(resizeTimer);
      resizeTimer = setTimeout(() => {
        initDecorativeBlocks();
        ScrollTrigger.refresh(true);
      }, 200);
    };
    window.addEventListener("resize", handleResize);

    return () => {
      clearTimeout(resizeTimer);
      window.removeEventListener("load", handleLoad);
      window.removeEventListener("resize", handleResize);
      ScrollTrigger.getAll().forEach((t) => t.kill());
    };
  }, []);

  // Listen for route changes and refresh ScrollTriggers so newly rendered content animates in correctly
  useEffect(() => {
    const refreshAnimations = () => {
      initDecorativeBlocks();
      ScrollTrigger.refresh(true);
    };

    // Run route change handler immediately on navigation
    refreshAnimations();

    // Staggered refreshes to accommodate page layout calculations and paint frames
    const timers = [
      setTimeout(refreshAnimations, 100),
      setTimeout(refreshAnimations, 400),
      setTimeout(refreshAnimations, 800),
      setTimeout(refreshAnimations, 1500),
    ];

    return () => {
      timers.forEach(clearTimeout);
    };
  }, [pathname]);

  return <>{children}</>;
}

