import { renderHook } from '@testing-library/react';
import { useCarouselHeight } from '../useCarouselHeight';
import React, { RefObject } from 'react';
import {
  activeSquareAspectRatio,
  activePortraitAspectRatio,
  activeStoriesAspectRatio,
  partialItemWidth as defaultPartialItemWidth,
} from '../../components/consts';

// Mock ResizeObserver since it's not available in JSDOM
class ResizeObserverMock {
  callback: ResizeObserverCallback;
  constructor(callback: ResizeObserverCallback) {
    this.callback = callback;
  }
  observe = jest.fn();
  unobserve = jest.fn();
  disconnect = jest.fn();
}

beforeAll(() => {
  global.ResizeObserver = ResizeObserverMock as any;
});

afterEach(() => {
  jest.clearAllMocks();
});

describe('useCarouselHeight', () => {
  it.each([
    { shape: 'square', ratio: activeSquareAspectRatio },
    { shape: 'portrait', ratio: activePortraitAspectRatio },
    { shape: 'stories', ratio: activeStoriesAspectRatio },
  ])('calculates correct height for shape $shape', ({ shape, ratio }) => {
    const mockElement = {
      offsetWidth: 1000,
    } as unknown as HTMLDivElement;

    const ref = {
      current: mockElement,
    } as RefObject<HTMLDivElement>;

    const contentSize = 3;
    const itemCount = 5;
    const partialItemWidth = defaultPartialItemWidth;
    const buffer = 40;

    const configuredVisibleItems = Math.max(contentSize, 1);
    const isEven = configuredVisibleItems % 2 === 0;
    const partialWidth = isEven ? partialItemWidth : 0;
    const itemWidth = mockElement.offsetWidth / (configuredVisibleItems + partialWidth);
    const aspectRatio = ratio / 100;
    const expectedHeight = itemWidth * aspectRatio + buffer;

    const { result } = renderHook(() =>
      useCarouselHeight({
        ref,
        shape: shape as any,
        contentSize,
        itemCount,
        partialItemWidth,
        buffer,
      })
    );

    expect(result.current).toBeCloseTo(expectedHeight, 2);
  });

  it('returns 0 if ref is null', () => {
    const ref = { current: null } as RefObject<HTMLDivElement>;

    const { result } = renderHook(() =>
      useCarouselHeight({
        ref,
        shape: 'square',
        contentSize: 3,
        itemCount: 3,
        partialItemWidth: defaultPartialItemWidth,
      })
    );

    expect(result.current).toBe(0);
  });

  it('uses configured content size even when item count is lower', () => {
    const mockElement = {
      offsetWidth: 800,
    } as unknown as HTMLDivElement;

    const ref = {
      current: mockElement,
    } as RefObject<HTMLDivElement>;

    const contentSize = 4;
    const itemCount = 1;
    const partialItemWidth = defaultPartialItemWidth;
    const buffer = 40;

    const configuredVisibleItems = contentSize;
    const partialWidth = partialItemWidth; // even number => partial width applied
    const aspectRatio = activeSquareAspectRatio / 100;
    const expectedHeight = (mockElement.offsetWidth / (configuredVisibleItems + partialWidth)) * aspectRatio + buffer;

    const { result } = renderHook(() =>
      useCarouselHeight({
        ref,
        shape: 'square',
        contentSize,
        itemCount,
        partialItemWidth,
        buffer,
      })
    );

    expect(result.current).toBeCloseTo(expectedHeight, 2);
  });
});
