/* eslint-disable react/display-name */

import React, { useState, forwardRef } from 'react';
import { DayPickerProps, DayModifiers } from 'react-day-picker';
import DateInputComponent from 'react-day-picker/DayPickerInput';
import 'react-day-picker/lib/style.css';
import moment from 'moment';
import { TextInput } from '../TextInput';
import { Button } from '../Button';
import { Flex } from '../Flex';
import { Box } from '../Box';
import { Icon } from '../Icon';
import * as icons from '../../assets/images/icons';
import * as sc from './styles';

export interface DateInputProps {
  name?: string;
  placeholder?: string;
  popperPlacement?: string;
  dateFormat?: string;
  invalid?: boolean;
  autoFocus?: boolean;
  noExpiryOption?: boolean;
  noExpiryCopy?: string;
  value?: any;
  onChange?: (state: any) => void;
  onBlur?: (state: any) => void;
  inputProps?: any;
  dayPickerProps?: Partial<DayPickerProps>;
  minDate?: Date;
  maxDate?: Date;
  hasIcon?: boolean;
}

const formatDate = (date: Date, dateFormat: string) =>
  moment(date).format(dateFormat);

export function DateInput({
  value,
  onChange,
  onBlur,
  autoFocus,
  placeholder = 'Date',
  dateFormat = 'MM/DD/YYYY',
  invalid,
  noExpiryOption,
  noExpiryCopy = 'No expiry',
  inputProps,
  dayPickerProps,
  minDate,
  maxDate,
  hasIcon,
  ...props
}: DateInputProps) {
  const isNoExpiry =
    noExpiryOption &&
    (value === undefined || value === null || value === noExpiryCopy);
  const [currentSelected, setCurrentSelected] = useState(
    isNoExpiry
      ? noExpiryCopy
      : value === undefined
      ? undefined
      : formatDate(value, dateFormat)
  );
  const pickerProps = dayPickerProps || {};

  if (minDate || maxDate) {
    if (minDate) pickerProps.fromMonth = minDate;
    if (maxDate) pickerProps.toMonth = maxDate;
    pickerProps.disabledDays = [
      ...(minDate ? [{ before: minDate }] : []),
      ...(maxDate ? [{ after: maxDate }] : []),
    ];
  }

  const handleChange = (selectedDate: Date, modifiers: DayModifiers) => {
    if (modifiers.disabled) return;
    const formattedDate = formatDate(selectedDate, dateFormat);
    setCurrentSelected(formattedDate);
    if (onChange) onChange(selectedDate);
  };

  const handleNoExpiry = () => {
    setCurrentSelected(noExpiryCopy);
    if (onChange) onChange(null);
  };

  return (
    <DateInputComponent
      component={forwardRef((componentProps, ref) => (
        <TextInput
          {...componentProps}
          {...{ onBlur, autoFocus, placeholder, invalid }}
          // eslint-disable-next-line
          // @ts-ignore
          inputRef={ref}
          value={currentSelected}
          {...(hasIcon
            ? {
                unit: (
                  <Icon
                    Asset={icons.SvgCalendar}
                    width={16}
                    height={16}
                    color="gray.3"
                  />
                ),
              }
            : {})}
          {...inputProps}
        />
      ))}
      overlayComponent={({ children, ...overlayProps }: any) => (
        <sc.Overlay
          borderRadius="3"
          boxShadow="2"
          borderColor="gray.4"
          border="1px solid"
          p="m"
          {...overlayProps}
        >
          <Flex flexDirection="column">
            {children}
            {noExpiryOption && (
              <Box mt="s">
                <Button variant="ghost" onClick={handleNoExpiry}>
                  {noExpiryCopy}
                </Button>
              </Box>
            )}
          </Flex>
        </sc.Overlay>
      )}
      dayPickerProps={{
        onDayClick: handleChange,
        month:
          currentSelected && currentSelected !== noExpiryCopy
            ? new Date(currentSelected)
            : undefined,
        selectedDays:
          currentSelected && currentSelected !== noExpiryCopy
            ? [new Date(currentSelected)]
            : undefined,
        ...pickerProps,
      }}
      {...props}
    />
  );
}

DateInput.displayName = 'DateInput';
