import React from 'react';
import extend from 'extend';
import isEqual from 'lodash/isEqual';
import { mount } from 'enzyme';
import { FilterItem } from 'karmadata';
import renderer from 'react-test-renderer';
import { ANY, ENTER, USER_SPECIFIED_OPTION } from '../../constants';

import KdSelectString from '../../components/KdSelectString';
import karmadataTheme from '../../themes/karmadata.scss';
import { chicklets, events, autoCompleteOptions } from '../__utils';

const defaultOptions = [{
  value: 'string1',
  label: 'string1',
  EntityType: null,
}, {
  value: 'string2',
  label: 'string2',
  EntityType: null,
}];


const mainSelectorOptions = {
  visible: true,
  notSelectedOption: { label: 'Any label' },
  userSpecifiedOption: { label: 'Select...' },
  optionGroups: [
    {
      label: 'group 1',
      options: [
        { values: ['test1', 'test2'], label: 'two' },
        { values: ['test'], label: 'test' },
      ],
    },
  ],
};

const props = {
  mainSelector: mainSelectorOptions,
  autoComplete: autoCompleteOptions,
  events,
  chicklets,
};

describe('KdSelectString', () => {
  let mainSelector;
  let kdFilterModel;
  let initialValues;
  beforeEach(() => {
    mainSelector = extend(true, {}, mainSelectorOptions);
    kdFilterModel = FilterItem('KdDrugClassEPC', 'KdLabel', 'String', 'Eq', ['String1']);
    initialValues = kdFilterModel.getSelected();
  });

  describe('Setup', () => {
    it('renders correctly', () => {
      const tree = renderer.create(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          theme={karmadataTheme}
          {...props}
        />
      ).toJSON();
      expect(tree).toMatchSnapshot();
    });

    it('should set initialValues', () => {
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          theme={karmadataTheme}
          {...props}
          selectBehavior="AddChicklet"
        />);
      expect(wrapper.instance().getChicklets().length).toBe(initialValues.length);
      expect(kdFilterModel.getSelected().length).toBe(initialValues.length);
    });
  });

  describe('Values Limit', () => {
    const customProps = { ...props, selectBehavior: 'AddChicklet', mainSelector };
    const values = ['test1', 'test2', 'test3'];

    it('without limit', () => {
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={FilterItem('KdDrugClassEPC', 'KdLabel', 'String')}
          theme={karmadataTheme}
          {...customProps}
          mainSelector={{ userSpecifiedOption: { label: 'search' } }}
        />);
      const input = wrapper.find('.c-kd__input');
      values.forEach((v) => {
        input.simulate('keyUp', { keyCode: ENTER, target: { value: v } });
      });
      expect(wrapper.instance().getChicklets().length).toBe(values.length);
    });

    it('limit and initial values', () => {
      const limit = 2;
      const filter = FilterItem('KdDrugClassEPC', 'KdLabel', 'String', 'Eq', ['s1', 's2', 's3']);
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={filter}
          theme={karmadataTheme}
          {...customProps}
          mainSelector={{ userSpecifiedOption: { label: 'search' } }}
          valuesLimit={limit}
        />);
      expect(wrapper.instance().getChicklets().length).toBe(limit);
      expect(filter.getSelected().length).toBe(limit);
    });


    it('add value', () => {
      const limit = 2;
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          theme={karmadataTheme}
          {...props}
          mainSelector={{ userSpecifiedOption: { label: 'search' } }}
          valuesLimit={limit}
        />);
      const input = wrapper.find('.c-kd__input');
      values.forEach((v) => {
        input.simulate('keyUp', { keyCode: ENTER, target: { value: v } });
      });
      expect(wrapper.instance().getChicklets().length).toBe(limit);
    });

    it('uses last values', () => {
      const limit = 2;
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          theme={karmadataTheme}
          {...props}
          mainSelector={{ userSpecifiedOption: { label: 'search' } }}
          valuesLimit={limit}
        />);
      const input = wrapper.find('.c-kd__input');
      values.forEach((v) => {
        input.simulate('keyUp', { keyCode: ENTER, target: { value: v } });
      });
      const kdChicklets = wrapper.instance().getChicklets().map(v => v.value);
      expect(isEqual(kdChicklets.slice(-limit), values.slice(-limit))).toBe(true);
      expect(wrapper.instance().getChicklets().length).toBe(limit);
    });
  });


  describe('ANY Option', () => {
    it('Visible', () => {
      mainSelector.notSelectedOption = { lable: 'Select...' };
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          theme={karmadataTheme}
          {...customProps}
        />);
      expect(wrapper.find(`option[value="${ANY}"]`).length).toBe(1);
    });

    it('On select clear values', () => {
      mainSelector.notSelectedOption = { lable: 'Select...' };
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          theme={karmadataTheme}
          {...customProps}
        />);
      expect(wrapper.instance().getChicklets().length).toBe(initialValues.length);
      wrapper.find('select').simulate('change', { target: { value: ANY } });
      expect(wrapper.instance().getChicklets().length).toBe(0);
      expect(kdFilterModel.getSelected().length).toBe(0);
    });
  });

  describe('USER_SPECIFIED_OPTION', () => {
    it('Visible', () => {
      mainSelector.userSpecifiedOption = { label: 'search' };
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          theme={karmadataTheme}
          {...customProps}
        />);
      expect(wrapper.find(`option[value="${USER_SPECIFIED_OPTION}"]`).length).toBe(1);
    });

    it('Select shows input', () => {
      mainSelector.userSpecifiedOption = { label: 'search' };
      mainSelector.optionGroups = [];
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={FilterItem('KdDrugClassEPC', 'KdLabel', 'String')}
          theme={karmadataTheme}
          {...customProps}
        />);
      expect(wrapper.find(`option[value="${USER_SPECIFIED_OPTION}"]`).length).toBe(1);
      expect(wrapper.find('.c-kd__input').length).toBe(0);
      wrapper.find('select').simulate('change', { target: { value: USER_SPECIFIED_OPTION } });
      expect(wrapper.find('.c-kd__input').length).toBe(1);
    });

    it('Select and add value', () => {
      mainSelector.userSpecifiedOption = { label: 'search' };
      const customProps = { ...props, selectBehavior: 'AddChicklet', mainSelector };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          theme={karmadataTheme}
          {...customProps}
        />);
      const input = wrapper.find('.c-kd__input');
      input.simulate('keyUp', { keyCode: ENTER, target: { value: 'stringTest' } });
      const kdChicklets = wrapper.instance().getChicklets().map(v => v.value);
      expect(kdChicklets.includes('stringTest')).toBe(true);
      expect(kdChicklets.length).toBe(initialValues.length + 1);
      expect(kdFilterModel.getSelected().includes('%stringTest%')).toBe(true);
      expect(wrapper.find('.c-kd-item-selected-text').length).toBe(initialValues.length + 1);
      expect(wrapper.find('.c-kd-item-selected').length).toBe(initialValues.length + 1);
    });

    it('Remove Item', () => {
      const customProps = { ...props, selectBehavior: 'AddChicklet', mainSelector };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          theme={karmadataTheme}
          {...customProps}
        />);
      wrapper.find('.o-remove').simulate('click');
      expect(wrapper.instance().getChicklets().length).toBe(initialValues.length - 1);
    });
  });

  describe('Behavior', () => {
    it('None', () => {
      const customProps = { ...props, selectBehavior: 'None' };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={FilterItem('KdDrugClassEPC', 'KdLabel', 'String')}
          {...customProps}
        />);

      wrapper.find('select').simulate('change', { target: { value: 'test' } });
      expect(wrapper.find('.c-kd-selected-chicklets').length).toBe(0);
      expect(wrapper.instance().getChicklets()[0].value).toBe('test');
    });

    it('AddChicklet', () => {
      const customProps = { ...props, selectBehavior: 'AddChicklet' };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={FilterItem('KdDrugClassEPC', 'KdLabel', 'String')}
          {...customProps}
        />
      );

      wrapper.find('select').simulate('change', { target: { value: 'test1,test2' } });
      expect(wrapper.find('.c-kd-selected-chicklets').children().length).toBe(2);
      expect(wrapper.instance().getChicklets().map(c => c.value)).toEqual(['test1', 'test2']);
    });

    it('AddChicklet - multipleSelection', () => {
      mainSelector.multipleSelection = true;
      const customProps = { ...props, mainSelector, selectBehavior: 'AddChicklet' };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={FilterItem('KdDrugClassEPC', 'KdLabel', 'String')}
          {...customProps}
        />
      );

      wrapper.find('select').simulate('change', { target: { value: 'test' } });
      expect(wrapper.find('.c-kd-selected-chicklets').length).toBe(1);
      expect(wrapper.find('.c-kd-selected-chicklets').children().length).toBe(1);

      wrapper.find('select').simulate('change', { target: { value: 'test1,test2' } });
      expect(wrapper.find('.c-kd-selected-chicklets').children().length).toBe(3);
      expect(wrapper.instance().getChicklets().length).toBe(3);
      expect(wrapper.instance().getChicklets()[0].value).toBe('test');
    });

    it('AddChickletSingle', () => {
      const customProps = { ...props, selectBehavior: 'AddChickletSingle' };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={FilterItem('KdDrugClassEPC', 'KdLabel', 'String')}
          {...customProps}
        />
      );

      wrapper.find('select').simulate('change', { target: { value: 'test' } });
      expect(wrapper.find('.c-kd-selected-chicklets').length).toBe(1);
      expect(wrapper.find('.c-kd-selected-chicklets').children().length).toBe(1);

      wrapper.find('select').simulate('change', { target: { value: 'test1,test2' } });
      expect(wrapper.find('.c-kd-selected-chicklets').children().length).toBe(2);
      expect(wrapper.instance().getChicklets().length).toBe(2);
      expect(wrapper.instance().getChicklets()[0].value).toBe('test1');
    });
  });

  describe('mainSelector', () => {
    it('visible', () => {
      mainSelector.visible = true;
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          {...customProps}
        />
      );

      expect(wrapper.find('select').length).toBe(1);
    });

    it('not visible', () => {
      mainSelector.visible = false;
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          {...customProps}
        />
      );

      expect(wrapper.find('select').length).toBe(0);
    });
  });

  describe('events', () => {
    it('onChange', () => {
      mainSelector.visible = true;
      const onChange = jest.fn();
      const customProps = { ...props, mainSelector, events: { onChange } };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          {...customProps}
        />
      );

      wrapper.find('select').simulate('change', { target: { value: 'test' } });
      expect(onChange.mock.calls.length).toBe(1);
    });

    it('onChange with user input', () => {
      mainSelector.visible = false;
      const onChange = jest.fn();
      const customProps = { ...props, mainSelector, events: { onChange } };
      const wrapper = mount(
        <KdSelectString
          kdFilterModel={kdFilterModel}
          {...customProps}
        />
      );

      const input = wrapper.find('.c-kd__input');
      input.simulate('keyUp', { keyCode: ENTER, target: { value: 'stringTest' } });
      expect(onChange.mock.calls.length).toBe(1);
    });
  });
});
