import { useState, useEffect, useCallback, useRef } from 'react';

/**
 * useDebounce Hook
 *
 * 創建一個防抖版本的函數，在指定延遲後執行
 * 如果在延遲期間再次調用，會取消前一次並重新開始計時
 *
 * @param callback 要防抖的函數
 * @param delay 延遲時間（毫秒）
 * @returns 防抖後的函數
 */
export const useDebounce = <T extends (...args: any[]) => any>(
  callback: T,
  delay: number
): T => {
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);

  const debouncedCallback = useCallback(
    (...args: Parameters<T>) => {
      // 清除之前的定時器
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }

      // 設置新的定時器
      timeoutRef.current = setTimeout(() => {
        callback(...args);
      }, delay);
    },
    [callback, delay]
  ) as T;

  // 清理函數，組件卸載時清除定時器
  const cancel = useCallback(() => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = null;
    }
  }, []);

  // 為返回的函數添加 cancel 方法
  (debouncedCallback as any).cancel = cancel;

  return debouncedCallback;
};

/**
 * useDebouncedValue Hook
 *
 * 創建一個防抖版本的值，只有在值穩定一段時間後才更新
 *
 * @param value 要防抖的值
 * @param delay 延遲時間（毫秒）
 * @returns 防抖後的值
 */
export const useDebouncedValue = <T>(value: T, delay: number): T => {
  const [debouncedValue, setDebouncedValue] = useState(value);
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);

  useEffect(() => {
    // 清除之前的定時器
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
    }

    // 設置新的定時器
    timeoutRef.current = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    // 清理函數
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, [value, delay]);

  return debouncedValue;
};

