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

// Mock the Helpers module
jest.mock('../../services/helpers', () => ({
  Helpers: {
    calculateArrowSize: jest.fn((width: number) => {
      if (width < 200) return 'nano';
      if (width < 300) return 'micro';
      if (width < 650) return 'small';
      if (width < 800) return 'compact';
      if (width < 1000) return 'medium';
      return 'large';
    }),
  },
}));

describe('useCarouselDimensions', () => {
  const createMockRef = (clientWidth: number): RefObject<HTMLDivElement> => ({
    current: {
      clientWidth,
    } as HTMLDivElement,
  });

  it('should calculate dimensions correctly for desktop with arrows', () => {
    const { result } = renderHook(() =>
      useCarouselDimensions({
        widgetWidth: 800,
        slideRef: createMockRef(800),
        hideArrows: false,
        hasItems: true,
        nbElems: 4,
        itemCount: 10,
        isMobile: false,
      }),
    );

    expect(result.current).toEqual({
      containerWidth: 800,
      arrowSize: 'medium',
      arrowSpace: 64, // (26 + 3*2) * 2 = 32 * 2 = 64
      contentWidth: 736, // 800 - 64
      itemWidth: Math.floor(736 / 4), // 184
    });
  });

  it('should honor forced arrow size when provided', () => {
    const { result } = renderHook(() =>
      useCarouselDimensions({
        widgetWidth: 400,
        slideRef: createMockRef(400),
        hideArrows: false,
        hasItems: true,
        nbElems: 3,
        itemCount: 6,
        isMobile: false,
        forcedArrowSize: 'medium',
      }),
    );

    expect(result.current.arrowSize).toBe('medium');
    expect(result.current.arrowSpace).toBe(64);
  });

  it('should calculate dimensions correctly for mobile', () => {
    const { result } = renderHook(() =>
      useCarouselDimensions({
        widgetWidth: 400,
        slideRef: createMockRef(400),
        hideArrows: false,
        hasItems: true,
        nbElems: 1,
        itemCount: 5,
        isMobile: true,
      }),
    );

    expect(result.current).toEqual({
      containerWidth: 400,
      arrowSize: 'medium', // Default when arrows not shown (mobile)
      arrowSpace: 0, // No arrows on mobile
      contentWidth: 400,
      itemWidth: 320, // 80% of 400
    });
  });

  it('should calculate dimensions correctly without arrows', () => {
    const { result } = renderHook(() =>
      useCarouselDimensions({
        widgetWidth: 600,
        slideRef: createMockRef(600),
        hideArrows: true,
        hasItems: true,
        nbElems: 3,
        itemCount: 6,
        isMobile: false,
      }),
    );

    expect(result.current).toEqual({
      containerWidth: 600,
      arrowSize: 'medium',
      arrowSpace: 0, // Arrows hidden
      contentWidth: 600,
      itemWidth: Math.floor(600 / 3), // 200
    });
  });

  it('should handle partial item width for even number of items', () => {
    const { result } = renderHook(() =>
      useCarouselDimensions({
        widgetWidth: 800,
        slideRef: createMockRef(800),
        hideArrows: false,
        hasItems: true,
        nbElems: 4, // Even number
        itemCount: 10,
        isMobile: false,
        partialItemWidth: 0.4,
      }),
    );

    const expectedArrowSpace = (26 + 3 * 2) * 2; // medium arrows: (26 + 3*2) * 2 = 64
    const expectedContentWidth = 800 - expectedArrowSpace;
    const expectedItemWidth = Math.floor(expectedContentWidth / (4 + 0.4)); // 4 items + 0.4 partial

    expect(result.current.itemWidth).toBe(expectedItemWidth);
  });

  it('should not add partial width for odd number of items', () => {
    const { result } = renderHook(() =>
      useCarouselDimensions({
        widgetWidth: 800,
        slideRef: createMockRef(800),
        hideArrows: false,
        hasItems: true,
        nbElems: 3, // Odd number
        itemCount: 10,
        isMobile: false,
        partialItemWidth: 0.4,
      }),
    );

    const expectedArrowSpace = (26 + 3 * 2) * 2; // medium arrows: (26 + 3*2) * 2 = 64
    const expectedContentWidth = 800 - expectedArrowSpace;
    const expectedItemWidth = Math.floor(expectedContentWidth / 3); // No partial width added

    expect(result.current.itemWidth).toBe(expectedItemWidth);
  });

  it('should fallback to slideRef width when widgetWidth is 0', () => {
    const { result } = renderHook(() =>
      useCarouselDimensions({
        widgetWidth: 0,
        slideRef: createMockRef(500),
        hideArrows: false,
        hasItems: true,
        nbElems: 2,
        itemCount: 4,
        isMobile: false,
      }),
    );

    expect(result.current.containerWidth).toBe(500);
  });

  it('should fallback to default width when both widgetWidth and slideRef are unavailable', () => {
    const { result } = renderHook(() =>
      useCarouselDimensions({
        widgetWidth: 0,
        slideRef: { current: null },
        hideArrows: false,
        hasItems: true,
        nbElems: 2,
        itemCount: 4,
        isMobile: false,
      }),
    );

    expect(result.current.containerWidth).toBe(600);
  });
});
