"use client";

import { useEffect, useRef, useState, type MutableRefObject } from "react";
import Image from "next/image";
import { usePathname } from "next/navigation";

/**
 * LoadingScreen
 * ---------------------------------------------------------------------------
 * Route-transition loader only: a black full-screen overlay with a centered,
 * pulsing Doormile logo. It intentionally does not run on initial page render,
 * image loading, lazy component loading, API requests, or scroll.
 *
 * The App Router does not expose the old `next/router` routeChangeStart /
 * routeChangeComplete event API. This component provides the same behavior by
 * detecting internal route-link starts and completing when `usePathname()`
 * reports the committed route.
 */
type Phase = "hidden" | "visible" | "hiding";

const MIN_VISIBLE_MS = 420;
const MAX_VISIBLE_MS = 800;

function getRoutePath(url: URL) {
  return `${url.pathname}${url.search}`;
}

export default function LoadingScreen() {
  const pathname = usePathname();
  const [phase, setPhase] = useState<Phase>("hidden");
  const phaseRef = useRef<Phase>("hidden");
  const visibleSince = useRef(0);
  const pendingPath = useRef<string | null>(null);
  const currentRoutePath = useRef<string | null>(null);
  const hideTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const safetyTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  const setLoaderPhase = (nextPhase: Phase) => {
    phaseRef.current = nextPhase;
    setPhase(nextPhase);
  };

  const clearTimer = (timer: MutableRefObject<ReturnType<typeof setTimeout> | null>) => {
    if (!timer.current) return;
    clearTimeout(timer.current);
    timer.current = null;
  };

  const completeTransition = () => {
    pendingPath.current = null;
    clearTimer(safetyTimer);

    if (phaseRef.current === "hidden" || phaseRef.current === "hiding") return;

    const elapsed = performance.now() - visibleSince.current;
    const wait = Math.max(0, MIN_VISIBLE_MS - elapsed);
    clearTimer(hideTimer);
    hideTimer.current = setTimeout(() => {
      setLoaderPhase("hiding");
      hideTimer.current = setTimeout(() => setLoaderPhase("hidden"), 360);
    }, wait);
  };

  useEffect(() => {
    currentRoutePath.current = `${pathname}${window.location.search}`;
    completeTransition();
    // `phase` intentionally stays out of this dependency list. The route commit
    // is the completion signal; phase changes should not repeatedly restart hide.
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pathname]);

  useEffect(() => {
    const startTransition = (targetPath: string, force = false) => {
      if (!force && targetPath === getRoutePath(new URL(window.location.href))) return;
      if (pendingPath.current === targetPath && phaseRef.current === "visible") return;

      pendingPath.current = targetPath;
      clearTimer(hideTimer);
      clearTimer(safetyTimer);

      visibleSince.current = performance.now();
      setLoaderPhase("visible");

      safetyTimer.current = setTimeout(() => {
        completeTransition();
      }, MAX_VISIBLE_MS);
    };

    const getInternalRouteTarget = (anchor: HTMLAnchorElement) => {
      const rawHref = anchor.getAttribute("href");
      if (!rawHref || rawHref.startsWith("#")) return null;
      if (anchor.target && anchor.target !== "_self") return null;
      if (anchor.hasAttribute("download")) return null;
      if (/^(mailto:|tel:|sms:|javascript:)/i.test(rawHref)) return null;

      const url = new URL(rawHref, window.location.href);
      if (url.origin !== window.location.origin) return null;

      const current = new URL(window.location.href);
      const sameRoute = url.pathname === current.pathname && url.search === current.search;
      if (sameRoute) return null;

      return getRoutePath(url);
    };

    const handleDocumentClick = (event: MouseEvent) => {
      if (event.defaultPrevented) return;
      if (event.button !== 0) return;
      if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;

      const anchor = (event.target as Element | null)?.closest("a[href]");
      if (!anchor || !(anchor instanceof HTMLAnchorElement)) return;

      const targetPath = getInternalRouteTarget(anchor);
      if (targetPath) startTransition(targetPath);
    };

    const originalPushState = window.history.pushState;
    const originalReplaceState = window.history.replaceState;

    const scheduleHistoryTransition = (targetPath: string) => {
      const currentPath = getRoutePath(new URL(window.location.href));
      if (targetPath === currentPath) return;

      window.setTimeout(() => {
        startTransition(targetPath, true);
      }, 0);
    };

    window.history.pushState = function patchedPushState(...args) {
      const urlArg = args[2];
      if (typeof urlArg === "string" || urlArg instanceof URL) {
        const url = new URL(urlArg, window.location.href);
        if (url.origin === window.location.origin) scheduleHistoryTransition(getRoutePath(url));
      }
      return originalPushState.apply(this, args);
    };

    window.history.replaceState = function patchedReplaceState(...args) {
      const urlArg = args[2];
      if (typeof urlArg === "string" || urlArg instanceof URL) {
        const url = new URL(urlArg, window.location.href);
        if (url.origin === window.location.origin) scheduleHistoryTransition(getRoutePath(url));
      }
      return originalReplaceState.apply(this, args);
    };

    const handlePopState = () => {
      const targetPath = getRoutePath(new URL(window.location.href));
      if (targetPath !== currentRoutePath.current) startTransition(targetPath, true);
    };

    document.addEventListener("click", handleDocumentClick, true);
    window.addEventListener("popstate", handlePopState);

    return () => {
      document.removeEventListener("click", handleDocumentClick, true);
      window.removeEventListener("popstate", handlePopState);
      window.history.pushState = originalPushState;
      window.history.replaceState = originalReplaceState;
      clearTimer(hideTimer);
      clearTimer(safetyTimer);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  if (phase === "hidden") return null;

  return (
    <div
      className={`dm-loader${phase === "hiding" ? " is-hiding" : ""}`}
      role="status"
      aria-live="polite"
      aria-label="Loading"
      onTransitionEnd={(e) => {
        if (e.propertyName === "opacity" && phase === "hiding") {
          setPhase("hidden");
          phaseRef.current = "hidden";
        }
      }}
    >
      <div className="dm-loader__pulse">
        <Image
          src="/images/preloader.png"
          alt="Doormile"
          width={325}
          height={239}
          priority
          className="dm-loader__logo"
        />
      </div>

      <style>{`
        .dm-loader {
          position: fixed;
          inset: 0;
          z-index: 100000;
          display: grid;
          place-items: center;
          background: #000;
          opacity: 1;
          transition: opacity 0.32s ease;
          will-change: opacity;
        }
        .dm-loader.is-hiding { opacity: 0; pointer-events: none; }
        .dm-loader__pulse { animation: dmLoaderPulse 1.5s linear infinite; display: grid; place-items: center; }
        .dm-loader__logo { display: block; margin: 0 auto; width: clamp(120px, 32vw, 180px); height: auto; }
        @keyframes dmLoaderPulse {
          50%  { transform: scale(0.85); }
          100% { transform: scale(1); }
        }
        @media (prefers-reduced-motion: reduce) {
          .dm-loader__pulse { animation: none; }
        }
      `}</style>
    </div>
  );
}
