// Libs
// -----------------------------------------------------------------------------
import { screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom';
import { setupServer } from 'msw/node';

// App
// -----------------------------------------------------------------------------
import { testRenderWithProviders, handleLocaleFileRequest } from 'testingUtils';
import { LicenseActivationPage } from './LicenseActivationPage';
import { rest } from 'msw';

// Test data
// -----------------------------------------------------------------------------

const SERIAL_NUMBER = '22fe7bc2-60e3-44a7-a60e-13bf48088cdf';
const TOKEN = 'af5bf3f8-253a-4e34-a452-4558518d700c';

// Setup MSW server
// -----------------------------------------------------------------------------

const server = setupServer(
  handleLocaleFileRequest,
  rest.get(`/en/api/license/auto/${SERIAL_NUMBER}/`, (req, res, ctx) => {
    return res(ctx.json({ license: 'activated' }));
  }),
  rest.post('/en/api/license/manual', (req, res, ctx) => {
    return res(ctx.json({ license: 'activated' }));
  }),
  rest.get(`/en/api/license/token/${SERIAL_NUMBER}/`, (req, res, ctx) => {
    return res(ctx.json({ token: TOKEN }));
  }),
);

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

// Test cases
// -----------------------------------------------------------------------------

test('License activation page: initial render', async () => {
  testRenderWithProviders(<LicenseActivationPage />);

  await waitFor(() => {
    expect(screen.getByText('Activate new license')).toBeInTheDocument();
  });
});

test('License activation page: get token', async () => {
  // Эмулятор пользователя
  const user = userEvent.setup();

  // Отрендерить компонент
  testRenderWithProviders(<LicenseActivationPage />);

  // Дождаться первичной отрисовки по наличию заголовка карточки
  await waitFor(() => {
    expect(screen.getByText('Activate new license')).toBeInTheDocument();
  });

  // Элементы формы
  const serialInput = screen.getByLabelText('Serial');
  const tokenInput = screen.getByLabelText('Token');
  const getTokenButton = screen
    .getByText('Get token')
    .closest('button') as HTMLElement;

  // Поля ввода должны быть пустыми, кнопка получения токена заблокирована
  expect(serialInput).toHaveValue('');
  expect(tokenInput).toHaveValue('');
  expect(getTokenButton).toBeDisabled();

  // Ввести серийный номер
  await user.type(serialInput, SERIAL_NUMBER);

  // Серийный номер должен быть заполнен, кнопка разблокирована
  await waitFor(() => {
    expect(serialInput).toHaveValue(SERIAL_NUMBER);
    expect(tokenInput).toHaveValue('');
    expect(getTokenButton).not.toBeDisabled();
  });

  // Кликнуть на кнопку получения токена
  await user.click(getTokenButton);

  // Поля серийника и токена должны быть заполнены
  await waitFor(() => {
    expect(serialInput).toHaveValue(SERIAL_NUMBER);
    expect(tokenInput).toHaveValue(TOKEN);
  });
});

test('License activation page: send license file', async () => {
  // Эмулятор пользователя
  const user = userEvent.setup();

  // Отрендерить компонент
  testRenderWithProviders(<LicenseActivationPage />);

  // Дождаться первичной отрисовки по наличию заголовка карточки
  await waitFor(() => {
    expect(screen.getByText('Activate new license')).toBeInTheDocument();
  });

  // Элементы формы
  const licenseInput = screen.getByLabelText('License');
  const activateButton = screen
    .getByText('Activate')
    .closest('button') as HTMLElement;

  // Поле лицензии должно быть пустыми, кнопка активации заблокирована
  expect(licenseInput).toHaveValue('');
  expect(activateButton).toBeDisabled();

  // Виртуальный файл лицензии для загрузки
  const file = new File(['hello'], 'hello.png', { type: 'image/png' });

  // Прикрепить виртуальный файл
  await user.upload(licenseInput, file);

  // Поле лицензии заполненным, кнопка активации доступна
  expect(licenseInput).toHaveValue('C:\\fakepath\\hello.png');
  expect(activateButton).not.toBeDisabled();

  // Нажать кнопку активации
  await user.click(activateButton);

  // Дождаться уведомления об успешной активации
  await waitFor(() => {
    expect(screen.getByText('License has been activated')).toBeInTheDocument();
  });
});

test('License activation page: auto activation', async () => {
  // Эмулятор пользователя
  const user = userEvent.setup();

  // Отрендерить компонент
  testRenderWithProviders(<LicenseActivationPage />);

  // Дождаться первичной отрисовки по наличию заголовка карточки
  await waitFor(() => {
    expect(screen.getByText('Activate new license')).toBeInTheDocument();
  });

  // Элементы формы
  const manualSwitch = screen.getByLabelText('Manual activation');

  // Переключатель должен быть включен
  expect(manualSwitch).toBeChecked();

  // Кликнуть по переключателю
  await user.click(manualSwitch);

  // Переключатель должен быть выключен
  expect(manualSwitch).not.toBeChecked();

  // Элементы формы
  const serialInput = screen.getByLabelText('Serial');
  const activateButton = screen
    .getByText('Activate')
    .closest('button') as HTMLElement;

  // Поле серийного номера должно быть пустыми, кнопка активации заблокирована
  expect(serialInput).toHaveValue('');
  expect(activateButton).toBeDisabled();

  // Ввести серийный номер
  await user.type(serialInput, SERIAL_NUMBER);

  // Серийный номер должен быть заполнен, кнопка разблокирована
  expect(serialInput).toHaveValue(SERIAL_NUMBER);
  expect(activateButton).not.toBeDisabled();

  // Нажать кнопку активации
  await user.click(activateButton);

  // Дождаться уведомления об успешной активации
  await waitFor(() => {
    expect(screen.getByText('License has been activated')).toBeInTheDocument();
  });
});
