"use client";
import { useState, useEffect, useRef, useCallback } from "react";
function useDebounce(value, delay) {
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(() => {
    const handler = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);
    return () => {
      clearTimeout(handler);
    };
  }, [value, delay]);
  return debouncedValue;
}
function useDebouncedCallback(callback, delay) {
  const callbackRef = useRef(callback);
  const timeoutRef = useRef(null);
  useEffect(() => {
    callbackRef.current = callback;
  }, [callback]);
  const debouncedCallback = useCallback(
    ((...args) => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
      timeoutRef.current = setTimeout(() => {
        callbackRef.current(...args);
      }, delay);
    }),
    [delay]
  );
  useEffect(() => {
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, []);
  return debouncedCallback;
}
function useThrottle(callback, delay) {
  const callbackRef = useRef(callback);
  const timeoutRef = useRef(null);
  const lastExecutedRef = useRef(0);
  useEffect(() => {
    callbackRef.current = callback;
  }, [callback]);
  const throttledCallback = useCallback(
    ((...args) => {
      const now = Date.now();
      const timeSinceLastExecution = now - lastExecutedRef.current;
      if (timeSinceLastExecution >= delay) {
        lastExecutedRef.current = now;
        callbackRef.current(...args);
      } else {
        if (timeoutRef.current) {
          clearTimeout(timeoutRef.current);
        }
        timeoutRef.current = setTimeout(() => {
          lastExecutedRef.current = Date.now();
          callbackRef.current(...args);
        }, delay - timeSinceLastExecution);
      }
    }),
    [delay]
  );
  useEffect(() => {
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, []);
  return throttledCallback;
}
function useDebouncedValidation(validateFn, delay = 300) {
  const debouncedValidate = useDebouncedCallback(validateFn, delay);
  return debouncedValidate;
}
export {
  useDebounce,
  useDebouncedCallback,
  useDebouncedValidation,
  useThrottle
};
