/**
 * <Pending> — indicateur de chargement de RÉGION, non bloquant et sans flou.
 *
 * Enveloppe un panneau/carte ; pendant le chargement, affiche un voile léger
 * (sans blur) + un spinner centré au-dessus de la zone concernée uniquement.
 * Réutilise la machine à états (délai avant affichage + durée minimale) pour ne
 * jamais clignoter sur les chargements rapides.
 */
import { useEffect, useRef, useState } from 'react';
import { cn } from '@/lib/utils';
import { Spinner } from '@/components/ui/spinner';
import { LoadingCore, type LoadingCoreOptions } from '@/lib/loading/loading-core';

/** Réflète un booléen `active` avec délai d'apparition et durée minimale visible. */
function useDeferredFlag(active: boolean, options: LoadingCoreOptions): boolean {
    const [shown, setShown] = useState(false);
    const coreRef = useRef<LoadingCore | null>(null);
    const prev = useRef(false);

    if (coreRef.current === null) {
        coreRef.current = new LoadingCore(setShown, options);
    }

    useEffect(() => {
        const core = coreRef.current!;
        if (active && !prev.current) core.start();
        else if (!active && prev.current) core.done();
        prev.current = active;
    }, [active]);

    useEffect(() => () => coreRef.current?.reset(), []);

    return shown;
}

export interface PendingProps {
    /** Vrai tant que la région charge. */
    pending: boolean;
    children: React.ReactNode;
    /** Message optionnel sous le spinner. */
    message?: string;
    /** Classes du conteneur relatif. */
    className?: string;
    /** Taille du spinner. */
    spinnerSize?: 'sm' | 'md' | 'lg';
    showDelay?: number;
    minVisible?: number;
}

export function Pending({
    pending,
    children,
    message,
    className,
    spinnerSize = 'md',
    showDelay = 150,
    minVisible = 300,
}: PendingProps) {
    const show = useDeferredFlag(pending, { showDelay, minVisible });

    return (
        <div className={cn('relative', className)}>
            {children}
            {show && (
                <div
                    role="status"
                    aria-live="polite"
                    className={cn(
                        'bg-background/60 absolute inset-0 z-10 flex flex-col items-center justify-center gap-2 rounded-[inherit]',
                        'animate-in fade-in-0 duration-150 motion-reduce:animate-none',
                    )}
                >
                    <Spinner size={spinnerSize} />
                    {message && <p className="text-muted-foreground max-w-xs text-center text-sm font-medium">{message}</p>}
                </div>
            )}
        </div>
    );
}
