import { renderHook, act } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { useDebounce } from './useDebounce';

describe('useDebounce', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });

  afterEach(() => {
    vi.useRealTimers();
  });

  it('should return initial value immediately', () => {
    const { result } = renderHook(() => useDebounce('test', 500));

    expect(result.current).toBe('test');
  });

  it('should debounce value changes', () => {
    const { result, rerender } = renderHook(
      ({ value, delay }) => useDebounce(value, delay),
      { initialProps: { value: 'initial', delay: 500 } },
    );

    expect(result.current).toBe('initial');

    rerender({ value: 'updated', delay: 500 });

    // La valeur ne devrait pas changer immédiatement
    expect(result.current).toBe('initial');

    // Après le délai, la valeur devrait être mise à jour
    act(() => {
      vi.advanceTimersByTime(500);
    });

    expect(result.current).toBe('updated');
  });

  it('should handle rapid value changes', () => {
    const { result, rerender } = renderHook(
      ({ value }) => useDebounce(value, 500),
      { initialProps: { value: 'value1' } },
    );

    rerender({ value: 'value2' });
    rerender({ value: 'value3' });
    rerender({ value: 'value4' });

    // La valeur devrait toujours être 'value1' car le délai n'est pas écoulé
    expect(result.current).toBe('value1');

    act(() => {
      vi.advanceTimersByTime(500);
    });

    expect(result.current).toBe('value4');
  });
});
