import { router } from '@inertiajs/react';
import { useEffect, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
import { Spinner } from '@/components/ui/spinner';

/** Evita un flash si la respuesta llega demasiado rápido tras cerrar el menú móvil. */
const MIN_VISIBLE_MS = 300;

function isPrefetchVisit(event: unknown): boolean {
    if (!event || typeof event !== 'object') {
        return false;
    }

    const visit =
        'detail' in event &&
        event.detail !== null &&
        typeof event.detail === 'object' &&
        'visit' in event.detail
            ? (event.detail as { visit?: { prefetch?: boolean } }).visit
            : event;

    return Boolean(visit && typeof visit === 'object' && 'prefetch' in visit && visit.prefetch);
}

export function InertiaNavigationLoader() {
    const [visible, setVisible] = useState(false);
    const [mounted, setMounted] = useState(false);
    const shownAtRef = useRef<number | null>(null);
    const hideTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);

    useEffect(() => {
        setMounted(true);
    }, []);

    useEffect(() => {
        function clearHideTimer() {
            if (hideTimerRef.current !== null) {
                clearTimeout(hideTimerRef.current);
                hideTimerRef.current = null;
            }
        }

        function hide() {
            clearHideTimer();
            const shownAt = shownAtRef.current;

            if (shownAt === null) {
                setVisible(false);

                return;
            }

            const remaining = MIN_VISIBLE_MS - (Date.now() - shownAt);

            if (remaining <= 0) {
                shownAtRef.current = null;
                setVisible(false);

                return;
            }

            hideTimerRef.current = setTimeout(() => {
                shownAtRef.current = null;
                setVisible(false);
                hideTimerRef.current = null;
            }, remaining);
        }

        function show(event: unknown) {
            if (isPrefetchVisit(event)) {
                return;
            }

            clearHideTimer();
            shownAtRef.current = Date.now();
            setVisible(true);
        }

        const offStart = router.on('start', show);
        const offFinish = router.on('finish', hide);
        const offCancel = router.on('cancel', hide);
        const offError = router.on('error', hide);

        return () => {
            offStart();
            offFinish();
            offCancel();
            offError();
            clearHideTimer();
        };
    }, []);

    if (!mounted || !visible) {
        return null;
    }

    return createPortal(
        <div
            aria-busy="true"
            aria-live="polite"
            className="fixed inset-0 z-[200] flex flex-col items-center justify-center gap-4 bg-background/95 backdrop-blur-sm"
            role="status"
        >
            <Spinner className="text-primary size-10" />
            <div className="space-y-1 text-center">
                <p className="text-foreground text-sm font-semibold">Cargando</p>
                <p className="text-muted-foreground text-xs">Un momento…</p>
            </div>
        </div>,
        document.body,
    );
}
