import React, { useMemo, useRef } from 'react';
import { observer } from 'mobx-react-lite';
import {
  Box,
  DatePicker,
  DatePickerProps,
  Text,
  TimeInput,
  Input,
  TimeInputProps,
} from '@wix/design-system';
import { DateRangePickerState } from '../../state';
import { TimeSmall } from '@wix/wix-ui-icons-common';
import { useWindowFlipPopoverProps } from '../../utils/useWindowFlipPopoverProps';
import { usePatternsTheme } from '../../themes/PatternsThemeProvider';

export interface DateRangePickerProps extends Partial<DatePickerProps> {
  state: DateRangePickerState;
}

function _DateRangePicker(props: DateRangePickerProps) {
  const { state, dataHook, popoverProps, ...rest } = props;
  const { translate: t, filterByTime } = state;
  const datePickerFrom = useRef<DatePicker>(null);
  const datePickerTo = useRef<DatePicker>(null);
  const { windowFlipPopoverProps } = useWindowFlipPopoverProps({
    popoverProps,
  });

  const { rangePicker } = usePatternsTheme();

  const commonInputProps = {
    size: rangePicker.size,
  };

  const commonDatePickerProps: Partial<DatePickerProps> = {
    ...commonInputProps,
    shouldCloseOnSelect: true,
    dateStyle: 'medium',
    width: filterByTime ? '100%' : rangePicker.width,
    zIndex: rangePicker.zIndex,
  };

  const commonTimeInputProps: Partial<TimeInputProps> = {
    ...commonInputProps,
    prefix: (
      <Input.IconAffix>
        <TimeSmall />
      </Input.IconAffix>
    ),
    popoverProps: windowFlipPopoverProps,
  };

  const filterDateFrom = useMemo(
    () => (date: Date) => state.filterDateFrom(date),
    [state.to],
  );
  const filterDateTo = useMemo(
    () => (date: Date) => state.filterDateTo(date),
    [state.from],
  );

  const filterDateTimeFrom = useMemo(
    () => (date: Date) => state.filterDateTimeFrom(date),
    [state.to, state.from, state.isToTimeSet],
  );
  const filterDateTimeTo = useMemo(
    () => (date: Date) => state.filterDateTimeTo(date),
    [state.from, state.to, state.isFromTimeSet],
  );

  const fromPicker = (
    <DatePicker
      ref={datePickerFrom}
      placeholderText={t('cairo.filtersPanel.date.title')}
      onChange={(from: Date) => state.onFromSelected(from)}
      value={state.from ?? undefined}
      filterDate={filterDateFrom}
      onClose={() => state.onFromClosed()}
      dataHook="date-range-picker-from"
      popoverProps={{
        ...windowFlipPopoverProps,
        placement: 'bottom-start',
      }}
      clearButton
      inputProps={{
        clearButtonAriaLabel: t(
          'cairo.filtersPanel.date.from.clearButton.ariaLabel',
        ),
      }}
      onClear={() => state.onFromSelected(null)}
      {...rest}
      {...commonDatePickerProps}
    />
  );

  const toPicker = (
    <DatePicker
      ref={datePickerTo}
      placeholderText={t('cairo.filtersPanel.date.title')}
      onChange={(to: Date) => state.onToSelected(to)}
      value={state.to ?? undefined}
      filterDate={filterDateTo}
      onClose={() => state.onToClosed()}
      dataHook="date-range-picker-to"
      popoverProps={{
        ...windowFlipPopoverProps,
        placement: 'bottom-end',
      }}
      clearButton
      inputProps={{
        clearButtonAriaLabel: t(
          'cairo.filtersPanel.date.to.clearButton.ariaLabel',
        ),
      }}
      onClear={() => state.onToSelected(null)}
      {...rest}
      {...commonDatePickerProps}
    />
  );

  return (
    <Box
      direction={filterByTime ? 'vertical' : 'horizontal'}
      gap="SP2"
      dataHook={dataHook}
      width="100%"
    >
      <Box direction="vertical" gap="SP1">
        <Text size="small">
          {t('cairo.filtersPanel.date.from.placeholder')}
        </Text>
        {filterByTime ? (
          <Box gap="SP2" width="100%">
            <Box flex={1}>{fromPicker}</Box>
            <TimeInput
              dataHook="date-range-picker-time-from"
              placeholder={t('cairo.filtersPanel.time.title')}
              value={state.isFromTimeSet ? state.from : null}
              onChange={({ date }) => state.onFromTimeSelected(date)}
              disabled={!state.from}
              filterTime={filterDateTimeFrom}
              size="small"
              {...commonTimeInputProps}
            />
          </Box>
        ) : (
          fromPicker
        )}
      </Box>

      <Box direction="vertical" gap="SP1">
        <Text size="small">{t('cairo.filtersPanel.date.to.placeholder')}</Text>
        {filterByTime ? (
          <Box gap="SP2" width="100%">
            <Box flex={1}>{toPicker}</Box>
            <TimeInput
              dataHook="date-range-picker-time-to"
              placeholder={t('cairo.filtersPanel.time.title')}
              value={state.isToTimeSet ? state.to : null}
              onChange={({ date }) => state.onToTimeSelected(date)}
              disabled={!state.to}
              filterTime={filterDateTimeTo}
              {...commonTimeInputProps}
            />
          </Box>
        ) : (
          toPicker
        )}
      </Box>
    </Box>
  );
}

export const DateRangePicker = observer(_DateRangePicker);
