import { renderHook } from '@testing-library/react';
import useSwipeNavigation from '../useSwipeNavigation';

describe('useSwipeNavigation', () => {
  let containerRef: { current: HTMLDivElement | null };
  let onSwipeLeft: jest.Mock;
  let onSwipeRight: jest.Mock;

  beforeEach(() => {
    // Create a mock container element
    containerRef = { current: document.createElement('div') };
    onSwipeLeft = jest.fn();
    onSwipeRight = jest.fn();

    // Mock addEventListener and removeEventListener
    containerRef.current!.addEventListener = jest.fn();
    containerRef.current!.removeEventListener = jest.fn();
  });

  test('calls onSwipeLeft when swiped left with sufficient distance', () => {
    renderHook(() =>
      useSwipeNavigation({
        containerRef,
        onSwipeLeft,
        onSwipeRight,
        threshold: 50,
      }),
    );

    // Get the touchstart handler
    const touchStartHandler = (containerRef.current!.addEventListener as jest.Mock).mock.calls.find(
      (call) => call[0] === 'touchstart',
    )[1];

    // Get the touchend handler
    const touchEndHandler = (containerRef.current!.addEventListener as jest.Mock).mock.calls.find(
      (call) => call[0] === 'touchend',
    )[1];

    // Simulate touchstart event
    const touchStartEvent = new TouchEvent('touchstart', {
      touches: [{ clientX: 200 } as Touch],
    });
    touchStartHandler(touchStartEvent);

    // Simulate touchend event with sufficient left swipe (startX > endX)
    const touchEndEvent = new TouchEvent('touchend', {
      changedTouches: [{ clientX: 120 } as Touch],
    });
    touchEndHandler(touchEndEvent);

    // Check if onSwipeLeft was called
    expect(onSwipeLeft).toHaveBeenCalledTimes(1);
    expect(onSwipeRight).not.toHaveBeenCalled();
  });

  test('calls onSwipeRight when swiped right with sufficient distance', () => {
    renderHook(() =>
      useSwipeNavigation({
        containerRef,
        onSwipeLeft,
        onSwipeRight,
        threshold: 50,
      }),
    );

    // Get the handlers
    const touchStartHandler = (containerRef.current!.addEventListener as jest.Mock).mock.calls.find(
      (call) => call[0] === 'touchstart',
    )[1];

    const touchEndHandler = (containerRef.current!.addEventListener as jest.Mock).mock.calls.find(
      (call) => call[0] === 'touchend',
    )[1];

    // Simulate touchstart event
    const touchStartEvent = new TouchEvent('touchstart', {
      touches: [{ clientX: 200 } as Touch],
    });
    touchStartHandler(touchStartEvent);

    // Simulate touchend event with sufficient right swipe (startX < endX)
    const touchEndEvent = new TouchEvent('touchend', {
      changedTouches: [{ clientX: 280 } as Touch],
    });
    touchEndHandler(touchEndEvent);

    // Check if onSwipeRight was called
    expect(onSwipeRight).toHaveBeenCalledTimes(1);
    expect(onSwipeLeft).not.toHaveBeenCalled();
  });

  test('does not trigger callbacks when swipe distance is below threshold', () => {
    renderHook(() =>
      useSwipeNavigation({
        containerRef,
        onSwipeLeft,
        onSwipeRight,
        threshold: 50,
      }),
    );

    // Get the handlers
    const touchStartHandler = (containerRef.current!.addEventListener as jest.Mock).mock.calls.find(
      (call) => call[0] === 'touchstart',
    )[1];

    const touchEndHandler = (containerRef.current!.addEventListener as jest.Mock).mock.calls.find(
      (call) => call[0] === 'touchend',
    )[1];

    // Test left swipe below threshold
    const touchStartEvent1 = new TouchEvent('touchstart', {
      touches: [{ clientX: 200 } as Touch],
    });
    touchStartHandler(touchStartEvent1);

    const touchEndEvent1 = new TouchEvent('touchend', {
      changedTouches: [{ clientX: 170 } as Touch],
    });
    touchEndHandler(touchEndEvent1);

    // Test right swipe below threshold
    const touchStartEvent2 = new TouchEvent('touchstart', {
      touches: [{ clientX: 200 } as Touch],
    });
    touchStartHandler(touchStartEvent2);

    const touchEndEvent2 = new TouchEvent('touchend', {
      changedTouches: [{ clientX: 230 } as Touch],
    });
    touchEndHandler(touchEndEvent2);

    // Check that neither callback was called
    expect(onSwipeLeft).not.toHaveBeenCalled();
    expect(onSwipeRight).not.toHaveBeenCalled();
  });
});
