"use client";

import Link, { type LinkProps } from "next/link";
import { usePathname, useRouter } from "next/navigation";
import {
  type MouseEvent,
  type ReactNode,
  useLayoutEffect,
} from "react";

const AUTH_ROUTE_EXIT_MS = 180;

function prefersReducedMotion() {
  return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
}

export function AuthTransitionFrame({
  children,
  className = "",
}: {
  children: ReactNode;
  className?: string;
}) {
  const pathname = usePathname();

  useLayoutEffect(() => {
    document.documentElement.classList.remove("auth-route-leaving");

    return () => {
      document.documentElement.classList.remove("auth-route-leaving");
    };
  }, [pathname]);

  return (
    <div
      key={pathname}
      className={`auth-route-frame auth-route-entering ${className}`}
    >
      {children}
    </div>
  );
}

export function AuthTransitionLink({
  children,
  className,
  href,
  ...props
}: LinkProps & {
  children: ReactNode;
  className?: string;
}) {
  const router = useRouter();

  function handleClick(event: MouseEvent<HTMLAnchorElement>) {
    if (
      event.defaultPrevented ||
      event.button !== 0 ||
      event.metaKey ||
      event.ctrlKey ||
      event.shiftKey ||
      event.altKey ||
      typeof href !== "string" ||
      !href.startsWith("/")
    ) {
      return;
    }

    event.preventDefault();

    if (document.documentElement.classList.contains("auth-route-leaving")) {
      return;
    }

    if (prefersReducedMotion()) {
      router.push(href);
      return;
    }

    document.documentElement.classList.add("auth-route-leaving");
    window.setTimeout(() => router.push(href), AUTH_ROUTE_EXIT_MS);
  }

  return (
    <Link {...props} href={href} className={className} onClick={handleClick}>
      {children}
    </Link>
  );
}
