"use client";

import React from "react";

/**
 * useDebouncedVisibility
 *
 * Delays the "show" transition and optionally enforces a minimum visible time.
 *
 * Typical use cases:
 * - Avoid flicker for fast loading indicators (e.g. show only after 300ms).
 * - Keep the indicator visible for at least X ms once shown (avoid blink).
 *
 * @param {boolean} isActive
 * @param {{ delayMs?: number, minVisibleMs?: number }} options
 * @returns {boolean}
 */
export function useDebouncedVisibility(
	isActive,
	{ delayMs = 200, minVisibleMs = 0 } = {},
) {
	const [visible, setVisible] = React.useState(false);

	const showTimerRef = React.useRef(null);
	const hideTimerRef = React.useRef(null);
	const visibleSinceRef = React.useRef(0);

	React.useEffect(() => {
		if (showTimerRef.current) {
			clearTimeout(showTimerRef.current);
			showTimerRef.current = null;
		}
		if (hideTimerRef.current) {
			clearTimeout(hideTimerRef.current);
			hideTimerRef.current = null;
		}

		if (isActive) {
			if (!visible) {
				showTimerRef.current = setTimeout(
					() => {
						visibleSinceRef.current = Date.now();
						setVisible(true);
					},
					Math.max(0, Number(delayMs) || 0),
				);
			}
			return;
		}

		if (!visible) return;

		const now = Date.now();
		const elapsed = now - (visibleSinceRef.current || now);
		const minMs = Math.max(0, Number(minVisibleMs) || 0);

		if (elapsed >= minMs) {
			setVisible(false);
			return;
		}

		hideTimerRef.current = setTimeout(() => {
			setVisible(false);
		}, minMs - elapsed);
	}, [isActive, delayMs, minVisibleMs, visible]);

	React.useEffect(() => {
		return () => {
			if (showTimerRef.current) clearTimeout(showTimerRef.current);
			if (hideTimerRef.current) clearTimeout(hideTimerRef.current);
		};
	}, []);

	return visible;
}
