import { UniDriver } from '@wix/wix-ui-test-utils/unidriver';
import {
  DatePickerUniDriver,
  DropdownBaseUniDriver,
  InputUniDriver,
  RadioGroupUniDriver,
  RadioUniDriver,
  TimeInputUniDriver,
} from '@wix/design-system/dist/testkit/unidriver';
import { baseUniDriverFactory } from '../../unidriver';
import { DatePickerUniDriver as DatePickerUniDriverAsync } from '../../unidriver/DatePicker.uni.driver';
import { UniDriverFactory } from '../uniDriverFactory';
import { DatePickerUniDriver as DatePickerUniDriverFactory } from '@wix/design-system/dist/types/DatePicker/DatePicker.uni.driver';

export function DateRangePickerUniDriver(base: UniDriver, body: UniDriver) {
  const getDatePickersContainer = () =>
    base.$(`[data-hook="date-range-picker"]`);

  const getDatePickerBase = (picker: 'from' | 'to') =>
    base.$(`[data-hook="date-range-picker-${picker}"]`);
  const getTimeInputBase = (picker: 'from' | 'to') =>
    base.$(`[data-hook="date-range-picker-time-${picker}"]`);

  const getDatePickerSync = (picker: 'from' | 'to') =>
    (DatePickerUniDriver as UniDriverFactory<DatePickerUniDriverFactory>)(
      getDatePickerBase(picker),
      body,
      {
        dataHook: `date-range-picker-${picker}`,
      },
    );

  const getDatePicker = async (picker: 'from' | 'to') =>
    DatePickerUniDriverAsync(getDatePickerBase(picker), body);

  const getTimeInput = (picker: 'from' | 'to') =>
    TimeInputUniDriver(getTimeInputBase(picker), body);

  const getRadioGroup = () =>
    RadioGroupUniDriver(base.$(`[data-hook="date-range-filter-group"]`), body);
  const getRadioItem = (preset: any) =>
    RadioUniDriver(
      base.$(`[data-hook="date-range-filter-option-${preset}"]`),
      body,
    );
  const openDatePicker = async (
    datePicker: ReturnType<typeof getDatePickerSync>,
  ) => {
    !(await datePicker.calendarDriver.exists()) &&
      (await datePicker.driver.open());
  };
  const chooseRandomDates = async () => {
    const dateFrom = await getDatePicker('from');
    const dateTo = await getDatePicker('to');
    await openDatePicker(dateFrom);
    await dateFrom.calendarDriver.clickOnNthDay(1);
    await dateTo.calendarDriver.clickOnNthDay(2);
    return {
      from: dateFrom,
      to: dateTo,
    };
  };

  const chooseDate = async (picker: 'from' | 'to', date: Date) => {
    const datePicker = await getDatePicker(picker);
    await openDatePicker(datePicker);
    await datePicker.calendarDriver.clickDay(date);
    return datePicker;
  };

  const choosePresetOption = async (option: string) => {
    const datesRadioGroup = getRadioGroup();
    await datesRadioGroup.selectByValue(option);
  };

  const getPresetOptions = async () => {
    const presetOptions = [];
    try {
      const datesRadioGroup = getRadioGroup();
      const numberOfRadios = await datesRadioGroup.getNumberOfRadios();
      for (let i = 0; i < numberOfRadios; i++) {
        presetOptions.push(await datesRadioGroup.getRadioValueAt(i));
      }
    } catch {}
    return presetOptions;
  };

  const getSelectedPresetTitle = async () => {
    const selectedRaido = await getRadioItem(await getSelectedPreset());
    return selectedRaido.getLabel();
  };

  const getSelectedPreset = () => {
    const datesRadioGroup = getRadioGroup();
    return datesRadioGroup.getSelectedValue();
  };

  const getTimeInputDriver = (picker: 'from' | 'to') =>
    InputUniDriver(
      getTimeInputBase(picker).$(`[data-hook="TimeInput-input"]`),
      body,
    );

  return {
    ...baseUniDriverFactory(base),
    _getRadioGroup: getRadioGroup,
    getDatePicker: getDatePickerSync,
    getDatePickersContainer,
    getTimeInput,
    isTimeSelected: async (picker: 'from' | 'to') => {
      return !!(await getTimeInputDriver(picker).getValue());
    },
    openTimeDropdown: async (picker: 'from' | 'to') => {
      await getTimeInputDriver(picker).click();
    },
    getTimeDropdown: (picker: 'from' | 'to') =>
      DropdownBaseUniDriver(
        getTimeInputBase(picker).$(`[data-hook="TimeInput-dropdown"]`),
        body,
      ),
    chooseRandomDates,
    chooseDate,
    choosePresetOption,
    getPresetOptions,
    getSelectedPreset,
    getSelectedPresetTitle,
    openDatePicker,
  };
}
