'use client';
import { useCallback, useEffect, useRef } from 'react';
/** How often the idle checker wakes up to compare against the deadline. */
const CHECK_INTERVAL_MS = 30_000;
/**
 * Signs the user out after `timeoutMs` of no user activity, when enabled by
 * the Settings → Security "Idle auto-logout" policy. Optionally fires a
 * warning `warningMs` before the deadline so the UI can offer a
 * "Stay signed in" action (the returned `stayActive` resets the clock).
 *
 * Deliberately lightweight: activity events only stamp a ref (no state, no
 * re-renders), and a single coarse interval compares the last-activity stamp
 * against the deadline. Returning to a hidden tab re-checks immediately via
 * `visibilitychange`, so a tab left overnight logs out as soon as it's seen
 * (or at the next interval tick) rather than staying signed in.
 *
 * All listeners and the interval are torn down on unmount or when disabled.
 */
export function useIdleLogout(options) {
    const { enabled, timeoutMs, warningMs } = options;
    // Keep the latest callbacks without re-subscribing listeners on every render.
    const onIdleRef = useRef(options.onIdle);
    onIdleRef.current = options.onIdle;
    const onWarnRef = useRef(options.onWarn);
    onWarnRef.current = options.onWarn;
    const onWarnCancelledRef = useRef(options.onWarnCancelled);
    onWarnCancelledRef.current = options.onWarnCancelled;
    // The effect re-assigns this so `stayActive` always resets the live timer.
    const resetRef = useRef(() => undefined);
    useEffect(() => {
        if (!enabled || timeoutMs <= 0 || typeof window === 'undefined') {
            resetRef.current = () => undefined;
            return;
        }
        let lastActivity = Date.now();
        let fired = false;
        let warned = false;
        // Only meaningful when a warn callback exists and the window fits.
        const effectiveWarningMs = onWarnRef.current && warningMs && warningMs > 0 && warningMs < timeoutMs ? warningMs : 0;
        const markActivity = () => {
            lastActivity = Date.now();
            if (warned && !fired) {
                warned = false;
                onWarnCancelledRef.current?.();
            }
        };
        resetRef.current = markActivity;
        const checkIdle = () => {
            if (fired)
                return;
            const idleFor = Date.now() - lastActivity;
            if (idleFor >= timeoutMs) {
                fired = true;
                onIdleRef.current();
                return;
            }
            if (effectiveWarningMs > 0 && !warned && idleFor >= timeoutMs - effectiveWarningMs) {
                warned = true;
                onWarnRef.current?.();
            }
        };
        // Passive listeners — activity stamping must never block scrolling/typing.
        const activityEvents = [
            'pointermove',
            'pointerdown',
            'keydown',
            'scroll',
            'touchstart',
        ];
        for (const event of activityEvents) {
            window.addEventListener(event, markActivity, { passive: true });
        }
        // A tab becoming visible again is NOT user activity — check whether the
        // deadline passed while it was hidden and log out immediately if so.
        const onVisibility = () => {
            if (document.visibilityState === 'visible')
                checkIdle();
        };
        document.addEventListener('visibilitychange', onVisibility);
        // Tick often enough to hit the warning window, not just the deadline.
        const tick = effectiveWarningMs > 0
            ? Math.min(CHECK_INTERVAL_MS, timeoutMs, effectiveWarningMs)
            : Math.min(CHECK_INTERVAL_MS, timeoutMs);
        const interval = window.setInterval(checkIdle, tick);
        return () => {
            resetRef.current = () => undefined;
            for (const event of activityEvents) {
                window.removeEventListener(event, markActivity);
            }
            document.removeEventListener('visibilitychange', onVisibility);
            window.clearInterval(interval);
        };
    }, [enabled, timeoutMs, warningMs]);
    const stayActive = useCallback(() => {
        resetRef.current();
    }, []);
    return { stayActive };
}
//# sourceMappingURL=useIdleLogout.js.map