/* eslint-disable no-magic-numbers */
import { MODELS_MOCK } from '@/redux/compartmentPathways/compartmentPathways.mock';
import { initialMapDataFixture, openedMapsThreeSubmapsFixture } from '@/redux/map/map.fixtures';
import { MODELS_DATA_MOCK_WITH_MAIN_MAP } from '@/redux/models/models.mock';
import { StoreType } from '@/redux/store';
import { PluginsEventBus } from '@/services/pluginsManager/pluginsEventBus';
import {
  InitialStoreState,
  getReduxWrapperWithStore,
} from '@/utils/testing/getReduxWrapperWithStore';
import { act, render, screen, within } from '@testing-library/react';
import { HISTAMINE_MAP_ID, MAIN_MAP_ID } from '@/constants/mocks';
import MapBackgroundsEnum from '@/redux/map/map.enums';
import { MapNavigation } from './MapNavigation.component';

const renderComponent = (initialStoreState: InitialStoreState = {}): { store: StoreType } => {
  const { Wrapper, store } = getReduxWrapperWithStore(initialStoreState);

  return (
    render(
      <Wrapper>
        <MapNavigation />
      </Wrapper>,
    ),
    {
      store,
    }
  );
};

describe('MapNavigation - component', () => {
  it('should render list of currently opened maps, main map should not have close button', async () => {
    renderComponent({
      map: {
        data: { ...initialMapDataFixture },
        loading: 'succeeded',
        error: { message: '', name: '' },
        openedMaps: openedMapsThreeSubmapsFixture,
        backgroundType: MapBackgroundsEnum.SEMANTIC,
      },
    });

    const mainMapButton = screen.getByRole('button', { name: 'Main map' });
    expect(mainMapButton).toBeInTheDocument();

    const histamineMapButton = screen.getByRole('button', { name: 'Histamine signaling' });
    expect(histamineMapButton).toBeInTheDocument();

    const prknMapButton = screen.getByRole('button', { name: 'PRKN substrates' });
    expect(prknMapButton).toBeInTheDocument();
  });

  it('all maps should have close button expect main map', async () => {
    renderComponent({
      map: {
        data: { ...initialMapDataFixture },
        loading: 'succeeded',
        error: { message: '', name: '' },
        openedMaps: openedMapsThreeSubmapsFixture,
        backgroundType: MapBackgroundsEnum.SEMANTIC,
      },
    });

    const mainMapButton = screen.getByRole('button', { name: 'Main map' });
    const mainMapCloseButton = await within(mainMapButton).queryByTestId('close-icon');
    expect(mainMapCloseButton).not.toBeInTheDocument();

    const histamineMapButton = screen.getByRole('button', { name: 'Histamine signaling' });
    const histamineMapCloseButton = await within(histamineMapButton).getByTestId('close-icon');
    expect(histamineMapCloseButton).toBeInTheDocument();

    const prknMapButton = screen.getByRole('button', { name: 'PRKN substrates' });
    const prknMapCloseButton = await within(prknMapButton).getByTestId('close-icon');
    expect(prknMapCloseButton).toBeInTheDocument();
  });

  it('should close map tab when clicking on close button while', async () => {
    const { store } = renderComponent({
      map: {
        data: {
          ...initialMapDataFixture,
          modelId: MAIN_MAP_ID,
        },
        loading: 'succeeded',
        error: { message: '', name: '' },
        openedMaps: openedMapsThreeSubmapsFixture,
        backgroundType: MapBackgroundsEnum.SEMANTIC,
      },
    });

    const histamineMapButton = screen.getByRole('button', { name: 'Histamine signaling' });
    const histamineMapCloseButton = await within(histamineMapButton).getByTestId('close-icon');
    await act(() => {
      histamineMapCloseButton.click();
    });

    const {
      map: {
        data: { modelId },
        openedMaps,
      },
    } = store.getState();

    const isHistamineMapOpened = openedMaps.some(map => map.modelName === 'Histamine signaling');

    expect(isHistamineMapOpened).toBe(false);
    expect(modelId).toBe(MAIN_MAP_ID);
  });

  it('should close currently selected map map and open main map', async () => {
    const { store } = renderComponent({
      map: {
        data: {
          ...initialMapDataFixture,
          modelId: HISTAMINE_MAP_ID,
        },
        openedMaps: openedMapsThreeSubmapsFixture,
        backgroundType: MapBackgroundsEnum.SEMANTIC,
        loading: 'succeeded',
        error: { message: '', name: '' },
      },
      models: {
        loading: 'succeeded',
        error: { message: '', name: '' },
        data: MODELS_MOCK,
      },
    });

    const histamineMapButton = screen.getByRole('button', { name: 'Histamine signaling' });
    const histamineMapCloseButton = await within(histamineMapButton).getByTestId('close-icon');
    await act(() => {
      histamineMapCloseButton.click();
    });

    const {
      map: {
        data: { modelId },
        openedMaps,
      },
    } = store.getState();

    const isHistamineMapOpened = openedMaps.some(map => map.modelName === 'Histamine signaling');

    expect(isHistamineMapOpened).toBe(false);
    expect(modelId).toBe(MAIN_MAP_ID);
  });
  describe('plugin event bus', () => {
    beforeEach(() => {
      PluginsEventBus.events = [];
    });
    afterEach(() => {
      jest.clearAllMocks();
    });
    it('should dispatch event if it closes active map and set main map as active', async () => {
      const dispatchEventMock = jest.spyOn(PluginsEventBus, 'dispatchEvent');

      renderComponent({
        models: MODELS_DATA_MOCK_WITH_MAIN_MAP,
        map: {
          data: {
            ...initialMapDataFixture,
            modelId: HISTAMINE_MAP_ID,
          },
          openedMaps: openedMapsThreeSubmapsFixture,
          backgroundType: MapBackgroundsEnum.SEMANTIC,
          loading: 'succeeded',
          error: { message: '', name: '' },
        },
      });

      const histamineMapButton = screen.getByRole('button', { name: 'Histamine signaling' });
      const histamineMapCloseButton = await within(histamineMapButton).getByTestId('close-icon');
      await act(() => {
        histamineMapCloseButton.click();
      });

      expect(dispatchEventMock).toHaveBeenCalledTimes(2);
      expect(dispatchEventMock).toHaveBeenCalledWith('onSubmapClose', 5052);
      expect(dispatchEventMock).toHaveBeenCalledWith('onSubmapOpen', 52);
    });
    it('should not dispatch event if it closes not active map', async () => {
      const dispatchEventMock = jest.spyOn(PluginsEventBus, 'dispatchEvent');

      renderComponent({
        models: MODELS_DATA_MOCK_WITH_MAIN_MAP,
        map: {
          data: {
            ...initialMapDataFixture,
            modelId: HISTAMINE_MAP_ID,
          },
          openedMaps: openedMapsThreeSubmapsFixture,
          backgroundType: MapBackgroundsEnum.SEMANTIC,
          loading: 'succeeded',
          error: { message: '', name: '' },
        },
      });

      const prknMapButton = screen.getByRole('button', { name: 'PRKN substrates' });
      const prknMapCloseButton = await within(prknMapButton).getByTestId('close-icon');
      await act(() => {
        prknMapCloseButton.click();
      });

      expect(dispatchEventMock).toHaveBeenCalledTimes(0);
    });
    it('should dispatch event if it switches to new tab and set is as active map', async () => {
      const dispatchEventMock = jest.spyOn(PluginsEventBus, 'dispatchEvent');

      renderComponent({
        models: MODELS_DATA_MOCK_WITH_MAIN_MAP,
        map: {
          data: {
            ...initialMapDataFixture,
            modelId: HISTAMINE_MAP_ID,
          },
          openedMaps: openedMapsThreeSubmapsFixture,
          backgroundType: MapBackgroundsEnum.SEMANTIC,
          loading: 'succeeded',
          error: { message: '', name: '' },
        },
      });

      const prknMapButton = screen.getByRole('button', { name: 'PRKN substrates' });

      await act(() => {
        prknMapButton.click();
      });

      expect(dispatchEventMock).toHaveBeenCalledTimes(2);
      expect(dispatchEventMock).toHaveBeenCalledWith('onSubmapClose', 5052);
      expect(dispatchEventMock).toHaveBeenCalledWith('onSubmapOpen', 5054);
    });
  });
});