import { renderHook, act } from '@testing-library/react';
import React, {ReactNode, createElement} from 'react';
import useCarouselThumbnailVideoLoading from '../useCarouselThumbnailVideoLoading';
import { StoreContext, initial, StoreState } from '../../services/store';
import { IMedia } from '../../types';

const makeMedia = (index: number, type: IMedia['type'] = 'video'): IMedia => ({
  id: `post-${index}`,
  type,
  caption: `Caption ${index}`,
  source: 'instagram',
  post: `https://post.com/${index}`,
  image: `https://image.com/${index}.jpg`,
  thumbnail: `https://thumb.com/${index}.jpg`,
  video: `https://video.com/${index}.mp4`,
  postIndex: index,
  productsLinked: {},
});

const medias = [makeMedia(0), makeMedia(1), makeMedia(2)];

const makeStore = (overrides: Partial<StoreState> = {}): StoreState => ({
  ...initial,
  isMobile: true,
  currentPosition: 1,
  data: {
    settings: {
      type: 'carousel',
      shop_this_look_display: 'default',
    } as any,
    content: { medias },
    id: 'widget-1',
  },
  setStoreState: jest.fn(),
  ...overrides,
});

describe('useCarouselThumbnailVideoLoading', () => {
  let store: StoreState;

  const makeWrapper = () => ({ children }: { children: ReactNode }) =>
    createElement(StoreContext.Provider, { value: store }, children);

  beforeEach(() => {
    store = makeStore();
    jest.clearAllMocks();
  });

  it('loads the active carousel video immediately and keeps shoulders locked at first', () => {
    const { result: activeResult } = renderHook(() => useCarouselThumbnailVideoLoading(medias[1]), {
      wrapper: makeWrapper(),
    });
    const { result: shoulderResult } = renderHook(() => useCarouselThumbnailVideoLoading(medias[0]), {
      wrapper: makeWrapper(),
    });

    expect(activeResult.current.isCarouselThumbnailVideoEnabled).toBe(true);
    expect(activeResult.current.shouldLoadCarouselVideo).toBe(true);
    expect(shoulderResult.current.shouldLoadCarouselVideo).toBe(false);
  });

  it('unlocks shoulder videos when the active carousel video becomes ready', () => {
    const { result } = renderHook(() => useCarouselThumbnailVideoLoading(medias[1]), {
      wrapper: makeWrapper(),
    });

    act(() => {
      result.current.handleCarouselVideoReady();
    });

    expect(store.setStoreState).toHaveBeenCalledTimes(1);
    const update = (store.setStoreState as jest.Mock).mock.calls[0][0] as (state: StoreState) => StoreState;
    store = update(store);

    expect(store.unlockedShouldersForCarouselPostId).toBe('post-1');
  });

  it('loads shoulder videos after the active carousel video unlocks them', () => {
    const { result, rerender } = renderHook(() => useCarouselThumbnailVideoLoading(medias[0]), {
      wrapper: makeWrapper(),
    });

    expect(result.current.shouldLoadCarouselVideo).toBe(false);

    store = makeStore({ unlockedShouldersForCarouselPostId: 'post-1' });
    rerender();

    expect(result.current.shouldLoadCarouselVideo).toBe(true);
  });

  it('relocks shoulders when the active carousel slide changes', () => {
    store = makeStore({ unlockedShouldersForCarouselPostId: 'post-1' });

    const { result, rerender } = renderHook(() => useCarouselThumbnailVideoLoading(medias[0]), {
      wrapper: makeWrapper(),
    });

    expect(result.current.shouldLoadCarouselVideo).toBe(true);

    store = makeStore({
      currentPosition: 2,
      unlockedShouldersForCarouselPostId: 'post-1',
    });
    rerender();

    expect(result.current.shouldLoadCarouselVideo).toBe(false);
  });
});