import React from 'react';
import { waitFor, fireEvent } from '@testing-library/react';
import renderWithTheme from '../../../../testUtils/renderWithTheme';

import Calendar from '../index';

describe('rendering', () => {
  it('renders calendar correctly', async () => {
    const { getByText, getByTestId } = renderWithTheme(
      <Calendar
        selectedDate={new Date(2021, 1, 19)}
        minDate={new Date(2021, 1, 1)}
        maxDate={new Date(2021, 1, 23)}
      />
    );

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

      // shows month in select
      expect(monthSelect).toSelectItem('Feb');
      // shows year in select
      expect(yearSelect).toSelectItem('2021');
      // shows days of week
      expect(getByText('Su')).toBeInTheDocument();
      expect(getByText('Mo')).toBeInTheDocument();
      expect(getByText('Tu')).toBeInTheDocument();
      expect(getByText('We')).toBeInTheDocument();
      expect(getByText('Th')).toBeInTheDocument();
      expect(getByText('Fr')).toBeInTheDocument();
      expect(getByText('Sa')).toBeInTheDocument();
      // shows selected date
      expect(getByText('19')).toBeInTheDocument();
      // shows disabled date
      expect(getByText('31')).toBeInTheDocument();
      expect(getByText('24')).toBeInTheDocument();
      // shows normal date
      expect(getByText('18')).toBeInTheDocument();
    });
  });
});

describe('interaction', () => {
  it('allows to select month and year', async () => {
    const { getByText, getByTestId } = renderWithTheme(
      <Calendar selectedDate={new Date(2021, 1, 19)} />
    );

    const monthSelect = getByTestId('month-select');
    const yearSelect = getByTestId('year-select');

    fireEvent.click(monthSelect);
    fireEvent.click(getByText('Mar'));

    await waitFor(() => {
      expect(monthSelect).toSelectItem('Mar');
    });

    fireEvent.click(yearSelect);
    fireEvent.click(getByText('2025'));

    await waitFor(() => {
      expect(yearSelect).toSelectItem('2025');
    });
  });

  it('allows to select a new date', async () => {
    const onSelectDate = jest.fn();
    const { getByText, getByTestId } = renderWithTheme(
      <Calendar
        selectedDate={new Date(2021, 1, 19)}
        onSelectDate={onSelectDate}
      />
    );

    fireEvent.click(getByTestId('month-select'));
    fireEvent.click(getByText('Mar'));
    fireEvent.click(getByTestId('year-select'));
    fireEvent.click(getByText('2025'));
    fireEvent.click(getByText('10'));

    await waitFor(() => {
      expect(onSelectDate).toHaveBeenCalledTimes(1);
      expect(onSelectDate).toHaveBeenCalledWith(new Date(2025, 2, 10));
    });
  });

  it('does not allow to select a new date out of range', async () => {
    const onSelectDate = jest.fn();
    const { getByText } = renderWithTheme(
      <Calendar
        selectedDate={new Date(2021, 1, 19)}
        minDate={new Date(2021, 1, 3)}
        maxDate={new Date(2021, 1, 20)}
        onSelectDate={onSelectDate}
      />
    );

    fireEvent.click(getByText('28'));

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