import React from 'react';
import { mount } from 'enzyme';
import { FilterItem } from 'karmadata';
import renderer from 'react-test-renderer';
import moment from 'moment';
import isEqual from 'lodash/isEqual';

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

const mainSelectorOptions = {
  visible: true,
  notSelectedOption: { label: 'Any' },
  optionGroups: [
    {
      label: 'fg',
      options: [
        { operator: 'Eq', label: 'Equal To' },
        { operator: 'NotEq', label: 'Not Equal To' },
        { operator: 'Gt', label: 'Greater Than' },
        { operator: 'Gte', label: 'Greater Than Or Equal To' },
        { operator: 'Lt', label: 'Less Than' },
        { operator: 'Lte', label: 'Less Than Or Equal To' },
        { operator: 'Between', label: 'Between' },
        {
          label: '1',
          operator: 'Eq',
          values: [1, 2, 3, 4],
        },
        {
          label: 'Gtt',
          operator: 'Gt',
          values: [2],
        },
        {
          label: 'Bettt',
          operator: 'Between',
          values: [1, 4],
        },
      ],
    },
  ],
};

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

describe('KdSelectNumber', () => {
  let mainSelector;
  let kdFilterModel;
  let initialValues;
  beforeEach(() => {
    mainSelector = mainSelectorOptions;
    kdFilterModel = FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number');
    initialValues = kdFilterModel.getSelected();
  });

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

    it('should set initialValues', () => {
      const wrapper = mount(
        <KdSelectNumber
          kdFilterModel={FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number', 'Eq', [1, 2])}
          theme={karmadataTheme}
          {...props}
        />
      );
      expect(wrapper.instance().getChicklets().length).toBe(2);
    });
  });

  describe('Values Limit', () => {
    const customProps = { ...props, selectBehavior: 'AddChicklet', mainSelector };
    const values = [10, 20, 30];

    it('without limit', () => {
      const wrapper = mount(
        <KdSelectNumber
          kdFilterModel={FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number')}
          theme={karmadataTheme}
          {...customProps}
        />
      );
      wrapper.find('select').simulate('change', { target: { value: 'defaultEq' } });
      const input = wrapper.find('.c-kd__input');
      values.forEach((v) => {
        input.simulate('keyup', { key: 'Enter', target: { value: v } });
      });
      expect(wrapper.instance().getChicklets().length).toBe(values.length);
    });

    it('limit and initial values', () => {
      const limit = 2;
      const filter = FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number', 'Eq', values);
      const wrapper = mount(
        <KdSelectNumber
          kdFilterModel={filter}
          theme={karmadataTheme}
          {...customProps}
          valuesLimit={limit}
        />
      );
      expect(wrapper.instance().getChicklets().length).toBe(limit);
      expect(filter.getSelected().length).toBe(limit);
    });

    it('add value', () => {
      const limit = 2;
      const wrapper = mount(
        <KdSelectNumber
          kdFilterModel={FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number')}
          theme={karmadataTheme}
          {...props}
          valuesLimit={limit}
        />
      );
      wrapper.find('select').simulate('change', { target: { value: 'defaultEq' } });
      const input = wrapper.find('.c-kd__input');
      values.forEach((v) => {
        input.simulate('keyup', { key: 'Enter', target: { value: v } });
      });
      expect(wrapper.instance().getChicklets().length).toBe(limit);
    });

    it('uses last values', () => {
      const limit = 2;
      const wrapper = mount(
        <KdSelectNumber
          kdFilterModel={FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number')}
          theme={karmadataTheme}
          {...props}
          valuesLimit={limit}
        />
      );
      wrapper.find('select').simulate('change', { target: { value: 'defaultEq' } });
      const input = wrapper.find('.c-kd__input');
      values.forEach((v) => {
        input.simulate('keyup', { key: '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('NotSelected Option', () => {
    it('Visible', () => {
      mainSelector.notSelectedOption = { label: 'Not Selected ' };
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectNumber kdFilterModel={kdFilterModel} theme={karmadataTheme} {...customProps} />
      );
      expect(wrapper.find('option[value="defaultAny"]').length).toBe(1);
    });

    it('Not Visible', () => {
      mainSelector.notSelectedOption = null;
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectNumber kdFilterModel={kdFilterModel} theme={karmadataTheme} {...customProps} />
      );
      expect(wrapper.find('option[value="defaultAny"]').length).toBe(0);
    });

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

  describe('After Option - Gt', () => {
    beforeEach(() => {
      const optionGroups = [{ label: 'fg', options: [{ operator: 'Gt', label: 'Gte' }] }];
      mainSelector.optionGroups = optionGroups;
    });

    it('Visible', () => {
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectNumber kdFilterModel={kdFilterModel} theme={karmadataTheme} {...customProps} />
      );
      expect(wrapper.find('option[value="defaultGt"]').length).toBe(1);
    });

    it('Select shows input', () => {
      const customProps = { ...props, mainSelector };
      const wrapper = mount(
        <KdSelectNumber
          kdFilterModel={FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number')}
          theme={karmadataTheme}
          {...customProps}
        />
      );
      expect(wrapper.find('option[value="defaultGt"]').length).toBe(1);
      expect(wrapper.find('.c-kd__input').length).toBe(0);
      wrapper.find('select').simulate('change', { target: { value: 'defaultGt' } });
      expect(wrapper.find('.c-kd__input').length).toBe(1);
    });

    it('Select and add a value', () => {
      const customProps = { ...props, selectBehavior: 'AddChickletSingle', mainSelector };
      const model = FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number');
      const wrapper = mount(
        <KdSelectNumber kdFilterModel={model} theme={karmadataTheme} {...customProps} />
      );
      wrapper.find('select').simulate('change', { target: { value: 'defaultGt' } });
      const input = wrapper.find('.c-kd__input');
      input.simulate('keyup', { key: 'Enter', target: { value: '1' } });
      const kdChicklets = wrapper
        .instance()
        .getChicklets()
        .map(v => v.value);
      expect(kdChicklets.includes('1')).toBe(true);
      expect(kdChicklets.length).toBe(1);
      expect(wrapper.find('.c-kd-item-selected-text').length).toBe(1);
      expect(wrapper.find('.c-kd-item-selected').length).toBe(1);
    });

    it('Remove Item', () => {
      const wrapper = mount(
        <KdSelectNumber
          kdFilterModel={FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number', 'Eq', [1, 2])}
          theme={karmadataTheme}
        />
      );
      wrapper
        .find('.o-remove')
        .first()
        .simulate('click');
      expect(wrapper.instance().getChicklets().length).toBe(1);
    });
  });

  describe('Behavior', () => {
    beforeEach(() => {
      mainSelector.optionGroups = [{ label: 'fg', options: [{ operator: 'Gt', label: 'Gte' }] }];
    });

    it('None behavior', () => {
      const customProps = { ...props, selectBehavior: 'None', mainSelector };
      const wrapper = mount(<KdSelectNumber kdFilterModel={kdFilterModel} {...customProps} />);
      expect(wrapper.find('.c-kd-selected-chicklets--chicklet_none')).not.toBeNull();
      expect(wrapper.find('.c-kd-selected-chicklets--chicklet_none > div').length).toBe(0);

      wrapper.find('select').simulate('change', { target: { value: 'defaultGt' } });
      const input = wrapper.find('.c-kd__input');
      input.simulate('keyup', { key: 'Enter', target: { value: '1' } });
      expect(wrapper.find('.c-kd-selected-chicklets--chicklet_none')).not.toBeNull();
      expect(wrapper.find('.c-kd-selected-chicklets--chicklet_none > div').length).toBe(0);
    });

    it('AddChickletSingle', () => {
      mainSelector.optionGroups = [
        {
          label: 'fg',
          options: [{ operator: 'Gt', label: 'Gte' }, { operator: 'Lt', label: 'Lte' }],
        },
      ];

      const customProps = { ...props, selectBehavior: 'AddChickletSingle', mainSelector };
      const wrapper = mount(<KdSelectNumber kdFilterModel={kdFilterModel} {...customProps} />);
      expect(wrapper.find('.c-kd-selected-chicklets')).not.toBeNull();

      wrapper.find('select').simulate('change', { target: { value: 'defaultGt' } });
      const input = wrapper.find('.c-kd__input');
      input.simulate('keyup', { key: 'Enter', target: { value: '1' } });
      expect(wrapper.find('.c-kd-selected-chicklets').children().length).toBe(1);
      expect(wrapper.instance().getChicklets().length).toBe(1);

      wrapper.find('select').simulate('change', { target: { value: 'defaultLt' } });
      input.simulate('keyup', { key: 'Enter', target: { value: '0' } });
      expect(wrapper.find('.c-kd-selected-chicklets').children().length).toBe(1);
      expect(wrapper.instance().getChicklets().length).toBe(1);
    });

    it('disabled', () => {
      const customProps = { ...props, disabled: true };
      const wrapper = mount(<KdSelectNumber kdFilterModel={kdFilterModel} {...customProps} />);
      expect(wrapper.find('.u-disabled')).not.toBeNull();
    });
  });

  describe('validation', () => {
    beforeEach(() => {
      mainSelector.optionGroups = [
        {
          label: 'fg',
          options: [{ operator: 'Eq', label: 'Eq' }],
        },
      ];
    });

    it('min max', () => {
      const customProps = { ...props, min: 10, max: 20 };
      const wrapper = mount(<KdSelectNumber kdFilterModel={kdFilterModel} {...customProps} />);

      wrapper.find('select').simulate('change', { target: { value: 'defaultEq' } });
      const input = wrapper.find('.c-kd__input');
      input.simulate('keyup', { key: 'Enter', target: { value: '5' } });
      expect(wrapper.instance().getChicklets().length).toBe(0);

      input.simulate('keyup', { key: 'Enter', target: { value: '25' } });
      expect(wrapper.instance().getChicklets().length).toBe(0);

      input.simulate('keyup', { key: 'Enter', target: { value: '15' } });
      expect(wrapper.instance().getChicklets()[0].value).toBe('15');
    });

    it('percentage', () => {
      const customProps = { ...props, type: 'percentage' };
      const wrapper = mount(<KdSelectNumber kdFilterModel={kdFilterModel} {...customProps} />);

      wrapper.find('select').simulate('change', { target: { value: 'defaultEq' } });
      const input = wrapper.find('.c-kd__input');
      input.simulate('keyup', { key: 'Enter', target: { value: '15' } });

      expect(wrapper.find('.c-kd-select-number__unit')).not.toBeNull();
      expect(wrapper.find('.c-kd-select-number__unit').props().children).toBe('%');
    });
  });

  describe('between', () => {
    beforeEach(() => {
      mainSelector.optionGroups = [
        {
          label: 'fg',
          options: [{ operator: 'Between', label: 'Between' }],
        },
      ];
    });
    it('Show option', () => {
      const customProps = { ...props };
      const wrapper = mount(<KdSelectNumber kdFilterModel={kdFilterModel} {...customProps} />);

      expect(wrapper.find('option[value="defaultBetween"]').length).toBe(1);
    });

    it('Render component', () => {
      const customProps = { ...props };
      const wrapper = mount(
        <KdSelectNumber
          kdFilterModel={FilterItem('KdDrugRxNorm', 'DrugScheduleDEA', 'Number')}
          {...customProps}
        />
      );

      wrapper.find('select').simulate('change', { target: { value: 'defaultBetween' } });
      expect(wrapper.find('.c-kd-select-number__slider').length).toBe(1);
    });
  });

  describe('custom options', () => {
    beforeEach(() => {
      mainSelector.optionGroups = [
        {
          label: 'fg',
          options: [{ operator: 'Eq', values: [1, 2, 3], label: '123' }],
        },
      ];
    });

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

      expect(wrapper.find('option[value="customEq123"]').length).toBe(1);
    });

    it('add chicklet for each value', () => {
      const customProps = { ...props };
      const wrapper = mount(<KdSelectNumber kdFilterModel={kdFilterModel} {...customProps} />);

      wrapper.find('select').simulate('change', { target: { value: 'customEq123' } });
      expect(wrapper.instance().getChicklets().length).toBe(3);
    });
  });
});
