import React from 'react';
import { waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import renderWithTheme from '../../../testUtils/renderWithTheme';

import MonthPicker from '../MonthPicker';

describe('rendering', () => {
  it('renders date input and calendar', async () => {
    const { getByText, getByDisplayValue, getByTestId } = renderWithTheme(
      <MonthPicker value="02/2021" />
    );

    await waitFor(() => {
      expect(getByDisplayValue('02/2021')).toBeInTheDocument();
    });

    userEvent.click(getByDisplayValue('02/2021'));

    await waitFor(() => {
      const yearSelect = getByTestId('year-select');
      expect(yearSelect).toSelectItem('2021');
      expect(getByText('Jan')).toBeInTheDocument();
      expect(getByText('Feb')).toBeInTheDocument();
    });
  });

  it('renders date input with correct format', async () => {
    const { getByDisplayValue } = renderWithTheme(
      <MonthPicker value="2021/05" format="yyyy/MM" />
    );

    await waitFor(() => {
      expect(getByDisplayValue('2021/05')).toBeInTheDocument();
    });
  });
});

describe('interaction', () => {
  it('allows to blur', async () => {
    const onBlur = jest.fn();
    const { getByDisplayValue } = renderWithTheme(
      <MonthPicker value="06/2021" onBlur={onBlur} />
    );

    userEvent.click(getByDisplayValue('06/2021'));
    userEvent.click(document.body);
    expect(onBlur).toHaveBeenCalledTimes(1);
  });

  it('allows to pick a month', async () => {
    const onChange = jest.fn();
    const { getByDisplayValue, getByText } = renderWithTheme(
      <MonthPicker value="06/2021" onChange={onChange} />
    );

    userEvent.click(getByDisplayValue('06/2021'));
    userEvent.click(getByText('May'));

    await waitFor(() => {
      expect(onChange).toHaveBeenCalledTimes(1);
      expect(onChange).toHaveBeenCalledWith('05/2021');
    });
  });

  it('does not allow to pick a date out of range', async () => {
    const onChange = jest.fn();
    const { getByDisplayValue, getByText } = renderWithTheme(
      <MonthPicker
        value="03/2021"
        onChange={onChange}
        minDate={new Date(2021, 2)}
        maxDate={new Date(2022, 5)}
      />
    );

    userEvent.click(getByDisplayValue('03/2021'));
    await waitFor(() => {
      expect(() => userEvent.click(getByText('Jan'))).toThrowError(
        'unable to click element as it has or inherits pointer-events set to "none".'
      );
    });
  });

  it('allows to pick a month by changing input value', async () => {
    const onChange = jest.fn();
    const { getByPlaceholderText } = renderWithTheme(
      <MonthPicker onChange={onChange} placeholder="Birthday" />
    );

    userEvent.type(getByPlaceholderText('Birthday'), '02/2021');

    await waitFor(() => {
      expect(onChange).toHaveBeenCalledTimes(7);
      expect(onChange).toHaveBeenCalledWith('0');
      expect(onChange).toHaveBeenCalledWith('2');
      expect(onChange).toHaveBeenCalledWith('/');
    });
  });

  it('shows current date when input value is invalid date', async () => {
    jest.useFakeTimers('modern');
    jest.setSystemTime(new Date(2022, 1));

    const { getByText, getByDisplayValue, getByTestId } = renderWithTheme(
      <MonthPicker value="111/4/34" />
    );

    userEvent.click(getByDisplayValue('111/4/34'));

    await waitFor(() => {
      const yearSelect = getByTestId('year-select');

      expect(getByText('Feb')).toBeInTheDocument();
      expect(yearSelect).toSelectItem('2022');
    });
  });

  it('does not allow to edit disabled Month Picker', async () => {
    const onChange = jest.fn();
    const { queryByText, getByDisplayValue } = renderWithTheme(
      <MonthPicker value="02/2021" onChange={onChange} disabled />
    );

    userEvent.click(getByDisplayValue('02/2021'));

    await waitFor(() => {
      expect(queryByText('May')).not.toBeInTheDocument();
    });

    userEvent.type(getByDisplayValue('02/2021'), '04/2022');

    await waitFor(() => {
      expect(onChange).not.toHaveBeenCalled();
    });
  });
});
