/* eslint-disable no-magic-numbers */
import { FIRST_ARRAY_ELEMENT } from '@/constants/common';
import { PLUGINS_MOCK } from '@/models/mocks/pluginsMock';
import { apiPath } from '@/redux/apiPath';
import {
  PLUGINS_INITIAL_STATE_LIST_MOCK,
  PLUGINS_INITIAL_STATE_MOCK,
} from '@/redux/plugins/plugins.mock';
import { StoreType } from '@/redux/store';
import { mockNetworkResponse } from '@/utils/mockNetworkResponse';
import { InitialStoreState } from '@/utils/testing/getReduxStoreActionsListener';
import { getReduxWrapperWithStore } from '@/utils/testing/getReduxWrapperWithStore';
import { render, screen } from '@testing-library/react';
import axios, { HttpStatusCode } from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { act } from 'react-dom/test-utils';
import { LoadPlugin, Props } from './LoadPlugin.component';

const mockedAxiosApiClient = mockNetworkResponse();
const mockedAxiosClient = new MockAdapter(axios);

const renderComponent = (
  { plugin }: Props,
  initialStore?: InitialStoreState,
): { store: StoreType } => {
  const { Wrapper, store } = getReduxWrapperWithStore(initialStore);
  return (
    render(
      <Wrapper>
        <LoadPlugin plugin={plugin} />
      </Wrapper>,
    ),
    {
      store,
    }
  );
};

describe('LoadPlugin - component', () => {
  describe('when always', () => {
    const plugin = PLUGINS_MOCK[FIRST_ARRAY_ELEMENT];

    it('renders plugin name', () => {
      renderComponent({ plugin });

      const title = screen.getByText(`${plugin.name} (${plugin.version})`);
      expect(title).toBeInTheDocument();
    });

    it('renders plugin load button', () => {
      renderComponent({ plugin });

      const loadButton = screen.getByText('Load');
      expect(loadButton.tagName).toBe('BUTTON');
      expect(loadButton).toBeInTheDocument();
    });
    it('should change button label to unload if plugin is active', () => {
      renderComponent(
        { plugin },
        {
          plugins: {
            ...PLUGINS_INITIAL_STATE_MOCK,
            activePlugins: {
              data: {
                [plugin.hash]: plugin,
              },
              pluginsId: [plugin.hash],
            },
            list: PLUGINS_INITIAL_STATE_LIST_MOCK,
          },
        },
      );

      expect(screen.queryByTestId('toggle-plugin')).toHaveTextContent('Unload');
    });
    it('should change button label to load if plugin is not active', () => {
      renderComponent({ plugin });
      expect(screen.queryByTestId('toggle-plugin')).toHaveTextContent('Load');
    });
    it('should unload plugin after click', async () => {
      mockedAxiosApiClient.onPost(apiPath.registerPluign()).reply(HttpStatusCode.Ok, plugin);
      mockedAxiosApiClient.onGet(apiPath.getPlugin(plugin.hash)).reply(HttpStatusCode.Ok, plugin);
      mockedAxiosClient.onGet(plugin.urls[0]).reply(HttpStatusCode.Ok, '');
      const { store } = renderComponent(
        { plugin },
        {
          plugins: {
            ...PLUGINS_INITIAL_STATE_MOCK,
            activePlugins: {
              data: {
                [plugin.hash]: plugin,
              },
              pluginsId: [plugin.hash],
            },
            list: PLUGINS_INITIAL_STATE_LIST_MOCK,
          },
        },
      );

      await act(() => {
        screen.queryByTestId('toggle-plugin')?.click();
      });

      const { activePlugins } = store.getState().plugins;
      expect(activePlugins.pluginsId).toEqual([]);
      expect(activePlugins.data).toEqual({});
    });
  });
});