import React, { useState, useCallback } from 'react';
import { Platform, ScrollView, TouchableOpacity, View } from 'react-native';

import BottomSheet from '../BottomSheet';
import Button from '../Button';
import Calendar from '../Calendar';
import type { CalendarProps } from '../Calendar/types';
import TextInput from '../TextInput';
import useCalculateDate from './hooks/useCalculateDate';
import useFormatDate from './hooks/useFormatDate';
import type { DatePickerProps } from './types';

const InternalCalendar = ({
  minDate,
  maxDate,
  value,
  onChange,
  onToggleMonthPicker,
  monthPickerConfirmLabel,
  monthPickerCancelLabel,
}: Pick<
  CalendarProps,
  | 'minDate'
  | 'maxDate'
  | 'value'
  | 'onChange'
  | 'onToggleMonthPicker'
  | 'monthPickerConfirmLabel'
  | 'monthPickerCancelLabel'
>) => {
  const [visibleDate, setVisibleDate] = useState(value || new Date());
  const [selectingDate, setSelectingDate] = useState<Date>(value || new Date());
  return (
    <Calendar
      testID="calendar"
      value={selectingDate}
      visibleDate={visibleDate}
      onChange={(date) => {
        setSelectingDate(date);
        if (onChange) {
          onChange(date);
        }
      }}
      onPreviousPress={() =>
        setVisibleDate(
          new Date(visibleDate.getFullYear(), visibleDate.getMonth() - 1, 1)
        )
      }
      onNextPress={() =>
        setVisibleDate(
          new Date(visibleDate.getFullYear(), visibleDate.getMonth() + 1, 1)
        )
      }
      minDate={minDate}
      maxDate={maxDate}
      onMonthChange={(date) => setVisibleDate(date)}
      onToggleMonthPicker={onToggleMonthPicker}
      monthPickerConfirmLabel={monthPickerConfirmLabel}
      monthPickerCancelLabel={monthPickerCancelLabel}
    />
  );
};

const DatePickerCalendar = ({
  value,
  minDate = new Date('1900-01-01T00:00:00.000Z'),
  maxDate = new Date('2100-01-01T00:00:00.000Z'),
  label,
  placeholder,
  onChange,
  confirmLabel,
  displayFormat,
  disabled = false,
  required,
  error,
  helpText,
  style,
  testID,
  monthPickerConfirmLabel,
  monthPickerCancelLabel,
  supportedOrientations = ['portrait'],
  renderSelectedValue,
  locale,
}: Omit<DatePickerProps, 'variant'>) => {
  const [open, setOpen] = useState(false);
  const [monthPickerVisible, setMonthPickerVisible] = useState(false);
  const shouldHideToolbar = Platform.OS === 'ios' && monthPickerVisible;

  const [selectingDate, setSelectingDate] = useState<Date>(value || new Date());

  const { displayValue } = useFormatDate({
    value,
    displayFormat,
    locale,
  });

  useCalculateDate({ minDate, maxDate, onChange, value });

  const onPress = useCallback(() => {
    setOpen(true);
  }, []);

  return (
    <TouchableOpacity
      onPress={onPress}
      disabled={disabled}
      testID="date-picker-calendar-touchable-opacity"
    >
      <View pointerEvents="none" testID="datePickerCalendar">
        <TextInput
          label={label}
          value={displayValue}
          suffix="calendar-dates-outlined"
          placeholder={placeholder || displayFormat}
          disabled={disabled}
          error={error}
          required={required}
          helpText={helpText}
          testID={testID}
          style={style}
          renderInputValue={
            renderSelectedValue !== undefined && !!value
              ? (inputProps) =>
                  renderSelectedValue(
                    {
                      date: value,
                      formattedDateString: displayValue,
                    },
                    inputProps
                  )
              : undefined
          }
        />
      </View>
      <BottomSheet
        open={open}
        onRequestClose={() => setOpen(false)}
        header={label}
        footer={
          shouldHideToolbar ? undefined : (
            <Button
              variant="text"
              text={confirmLabel}
              onPress={() => {
                if (selectingDate) {
                  onChange(selectingDate);
                }
                setOpen(false);
              }}
            />
          )
        }
        supportedOrientations={supportedOrientations}
      >
        <ScrollView>
          <InternalCalendar
            minDate={minDate}
            maxDate={maxDate}
            value={value}
            onChange={setSelectingDate}
            monthPickerConfirmLabel={monthPickerConfirmLabel}
            monthPickerCancelLabel={monthPickerCancelLabel}
            onToggleMonthPicker={(visible) => setMonthPickerVisible(visible)}
          />
        </ScrollView>
      </BottomSheet>
    </TouchableOpacity>
  );
};

export default DatePickerCalendar;
