"use client";

import { useEffect, useRef, useState } from "react";
import { AnimatePresence, motion, useReducedMotion } from "motion/react";
import { usePathname } from "next/navigation";

const MIN_MS = 450;
const MAX_MS = 4000;
const ease = [0.2, 0.7, 0.2, 1] as const;

/** Full-screen cover shown while a route change renders, so the scroll reset and first paint of the new page happen out of view. */
export default function RouteLoader() {
  const pathname = usePathname();
  const reduce = useReducedMotion();
  const [busy, setBusy] = useState(false);
  const pathRef = useRef(pathname);
  const startedAt = useRef(0);
  const maxTimer = useRef<number>(0);

  // Start on an internal click to another path, and on back/forward to another path.
  useEffect(() => {
    const start = () => {
      startedAt.current = performance.now();
      window.clearTimeout(maxTimer.current);
      maxTimer.current = window.setTimeout(() => setBusy(false), MAX_MS);
      setBusy(true);
    };
    // Capture phase runs before Next's Link handler, so modifier checks see the untouched event.
    const onClick = (e: MouseEvent) => {
      if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
      const a = (e.target as Element | null)?.closest?.("a[href]") as HTMLAnchorElement | null;
      if (!a || a.target === "_blank" || a.hasAttribute("download")) return;
      const url = new URL(a.href);
      if (url.origin !== window.location.origin || url.pathname === pathRef.current) return;
      start();
    };
    const onPop = () => {
      if (window.location.pathname !== pathRef.current) start();
    };
    document.addEventListener("click", onClick, true);
    window.addEventListener("popstate", onPop);
    return () => {
      document.removeEventListener("click", onClick, true);
      window.removeEventListener("popstate", onPop);
      window.clearTimeout(maxTimer.current);
    };
  }, []);

  // Hide once the new route has rendered and the minimum display time has passed.
  useEffect(() => {
    pathRef.current = pathname;
    const elapsed = performance.now() - startedAt.current;
    const t = window.setTimeout(() => {
      window.clearTimeout(maxTimer.current);
      setBusy(false);
    }, Math.max(0, MIN_MS - elapsed));
    return () => window.clearTimeout(t);
  }, [pathname]);

  return (
    <AnimatePresence>
      {busy && (
        <motion.div
          key="route-loader"
          className="route-loader"
          role="status"
          aria-live="polite"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: reduce ? 0 : 0.2, ease }}
        >
          <span className="route-loader-word" aria-hidden="true">Syria</span>
          <span className="route-loader-bar" aria-hidden="true" />
          <span className="sr-only">Loading page</span>
        </motion.div>
      )}
    </AnimatePresence>
  );
}
