import * as formatting from '@transferwise/formatting';
import { shallow } from 'enzyme';
import { useIntl } from 'react-intl';

import MonthCalendarTable from '.';

jest.mock('react-intl');
jest.mock('@transferwise/formatting', () => ({
  formatDate: jest.fn().mockReturnValue('MonthName'),
}));

describe('MonthCalendarTable', () => {
  const locale = 'en-GB';
  let component;
  let props;

  beforeEach(() => {
    props = {
      viewYear: 2018,
      placeholder: 'Enter date..',
      onSelect: jest.fn(),
    };
    useIntl.mockReturnValue({ locale });
    component = shallow(<MonthCalendarTable {...props} />);
  });

  it('generates 3x4 table', () => {
    expect(component.find('tbody tr')).toHaveLength(3);
    expect(component.find('tbody td')).toHaveLength(12);
    expect(getTableLink()).toHaveLength(12);
  });

  it('starts with month 0 and end with 11', () => {
    expect(getTableLinkAt(0).prop('item')).toBe(0);
    expect(getTableLinkAt(11).prop('item')).toBe(11);
  });

  it('passes month value and type to TableLink', () => {
    expect(getTableLinkAt(0).prop('item')).toBe(0);
    expect(getTableLinkAt(0).prop('type')).toBe('month');
  });

  it('shows formatted months', () => {
    expect(getTableLinkAt(0).prop('title')).toBe('MonthName');
    expect(formatting.formatDate).toHaveBeenCalledWith(new Date(2018, 0), locale, {
      month: 'short',
    });
  });

  it('show selectedDate as active', () => {
    component.setProps({ selectedDate: new Date(2018, 11, 27) });
    expect(getTableLinkAt(10).prop('active')).toBe(false);
    expect(getTableLinkAt(11).prop('active')).toBe(true);
  });

  it('disables dates outside of min and max range', () => {
    component.setProps({
      selectedDate: new Date(2018, 6, 1),
      min: new Date(2018, 6, 1),
      max: new Date(2018, 7, 31),
    });
    expect(getTableLinkAt(5).prop('disabled')).toBe(true);
    expect(getTableLinkAt(6).prop('disabled')).toBe(false);
    expect(getTableLinkAt(7).prop('disabled')).toBe(false);
    expect(getTableLinkAt(8).prop('disabled')).toBe(true);
  });

  it('highlights today', () => {
    const today = new Date();
    component.setProps({
      selectedDate: today,
      viewYear: today.getFullYear(),
    });
    expect(getTableLink().find({ today: true }).prop('item')).toBe(today.getMonth());
  });

  it('passes onSelect to TableLink', () => {
    expect(getTableLinkAt(0).prop('onClick')).toBe(props.onSelect);
  });

  it('shows placeholder for screen-readers', () => {
    expect(component.find('.sr-only').text()).toBe('Enter date..');
  });

  it('sets autofocus to true when June is the selected month', () => {
    component.setProps({ selectedDate: new Date(2018, 5, 1) });
    expect(getTableLinkAt(5).prop('autofocus')).toBe(true);
  });

  it('does not set autofocus to true when June is the selected month but not the right year', () => {
    component.setProps({ selectedDate: new Date(2017, 5, 1) });
    expect(getTableLinkAt(5).prop('autofocus')).toBe(false);
  });

  it('sets autofocus to true when selected date is null and current month is visible', () => {
    const today = new Date();
    component.setProps({
      selectedDate: null,
      viewYear: today.getFullYear(),
      viewMonth: today.getMonth(),
    });
    expect(getTableLink().find({ today: true }).prop('autofocus')).toBe(true);
  });

  it('sets autofocus to true on the second month when the first month is disabled', () => {
    component.setProps({
      selectedDate: null,
      viewYear: 2022,
      min: new Date(2022, 1, 28),
      viewMonth: 0,
      isDisabled: (month) => month === 0,
    });

    expect(getTableLinkAt(0).prop('autofocus')).toBe(false);
    expect(getTableLinkAt(1).prop('autofocus')).toBe(true);
  });

  const getTableLinkAt = (i) => component.find('[title="MonthName"]').at(i);
  const getTableLink = () => component.find('[title="MonthName"]');
});
