import { ref, watch, type Ref } from 'vue'

/**
 * Creates a debounced version of a ref value
 * @param value - The ref to debounce
 * @param delay - Debounce delay in milliseconds (default: 300)
 * @returns A tuple of [debouncedValue, cancel function]
 */
export function useDebouncedRef<T>(value: Ref<T>, delay = 300) {
  const debouncedValue = ref(value.value) as Ref<T>
  let timeout: ReturnType<typeof setTimeout> | null = null

  const cancel = () => {
    if (timeout) {
      clearTimeout(timeout)
      timeout = null
    }
  }

  watch(value, (newValue) => {
    cancel()
    timeout = setTimeout(() => {
      debouncedValue.value = newValue
    }, delay)
  })

  return { debouncedValue, cancel }
}

/**
 * Creates a debounced callback function
 * @param callback - The function to debounce
 * @param delay - Debounce delay in milliseconds (default: 300)
 * @returns A tuple of [debounced function, cancel function]
 */
export function useDebounce<T extends (...args: Parameters<T>) => void>(callback: T, delay = 300) {
  let timeout: ReturnType<typeof setTimeout> | null = null

  const cancel = () => {
    if (timeout) {
      clearTimeout(timeout)
      timeout = null
    }
  }

  const debouncedFn = (...args: Parameters<T>) => {
    cancel()
    timeout = setTimeout(() => {
      callback(...args)
    }, delay)
  }

  return { debouncedFn, cancel }
}
