import React, {useCallback, useState} from 'react';
import {Keyboard, View} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useFormContext} from 'react-hook-form';
import {Typography} from '@components/_core/Typography';
import {DatePicker, DatePickerProps} from '@components/_HuGo/DatePicker';
import {Dialog} from '@components/_HuGo/Dialog';
import {useTheme} from '@shared/theme';
import {format, getDate} from '@shared/utils';

import {
  useInputController,
  UseInputControllerProps,
} from '../../hooks/useInputController';
import {InputAccessibilities, InputCommonProps} from '../../interfaces';
import {INPUT_ICONS} from '../../constants';
import {InputCore} from '../InputCore';
import {InputBox} from '../InputBox';
import {styles} from './styles';

export type InputDateCalendarOpenContext = {
  anchorDate: Date | undefined;
};

export interface InputDateProps
  extends InputCommonProps,
    InputAccessibilities,
    DatePickerProps {
  onClear?: () => void;
  onCalendarOpen?: (context: InputDateCalendarOpenContext) => void;
  onCalendarClose?: () => void;
  // When provided, overrides the locale-based display format.
  // Useful for forms that require a specific format (e.g. MM/dd/yyyy).
  dateFormat?: string;
}

export function InputDate({
  label,
  helper,
  helperNumberOfLines,
  isError,
  isSuccess,
  disabled,
  onChange,
  onClear,
  placeholder,
  value,
  minDate,
  maxDate,
  size,
  initialDate,
  onMonthChange,
  disabledDates,
  disabledDatesTextStyle,
  onCalendarOpen,
  onCalendarClose,
  dateFormat,
}: InputDateProps) {
  const {t, i18n} = useTranslation();
  const {theme, iconSizes} = useTheme();
  const [focused, setFocused] = useState(false);
  const [calendarPickerDate, setCalendarPickerDate] = useState<
    Date | undefined
  >(value ?? undefined);
  const selectedDate = value
    ? dateFormat
      ? format(value, dateFormat)
      : getDate(value, i18n.language)
    : null;
  const withClear = value != null && !!onClear;
  const textColor = theme.text.neutral[disabled ? 'disabled' : 'default'];

  const onInputPress = () => {
    Keyboard.dismiss();
    setFocused(true);
    onCalendarOpen?.({
      anchorDate: initialDate ?? value ?? undefined,
    });
  };

  const onDialogClose = () => {
    setCalendarPickerDate(undefined);
    setFocused(false);
    onCalendarClose?.();
  };

  const onSelectPress = () => {
    calendarPickerDate && onChange?.(calendarPickerDate);
    onDialogClose();
  };

  const onClearSelection = () => {
    onClear?.();
    onDialogClose();
  };

  return (
    <>
      <InputCore
        label={label}
        helper={helper}
        helperNumberOfLines={helperNumberOfLines}
        isSuccess={isSuccess}
        isError={isError}
        focused={focused}
        disabled={disabled}>
        <InputBox
          isSuccess={isSuccess}
          isError={isError}
          disabled={disabled}
          focused={focused}
          onPress={onInputPress}
          size={size}
          RightComponent={
            <INPUT_ICONS.calendar size={iconSizes.x6} color={textColor} />
          }>
          <View style={styles.dateContainer}>
            {selectedDate ? (
              <Typography style={styles.dateText} color={textColor}>
                {selectedDate}
              </Typography>
            ) : placeholder ? (
              <Typography
                color={theme.text.neutral[disabled ? 'disabled' : 'lighter']}>
                {placeholder}
              </Typography>
            ) : null}
          </View>
        </InputBox>
      </InputCore>
      <Dialog
        isVisible={focused}
        onClose={onDialogClose}
        title={label}
        footer={{
          primaryButton: {
            text: t('general.apply'),
            onPress: onSelectPress,
          },
          secondaryButton: {
            text: t(`general.${withClear ? 'reset_selection' : 'close'}`),
            onPress: withClear ? onClearSelection : onDialogClose,
          },
        }}>
        <DatePicker
          value={value ?? undefined}
          onChange={setCalendarPickerDate}
          minDate={minDate}
          maxDate={maxDate}
          initialDate={initialDate ?? undefined}
          onMonthChange={onMonthChange}
          disabledDates={disabledDates}
          disabledDatesTextStyle={disabledDatesTextStyle}
        />
      </Dialog>
    </>
  );
}

type InputDateControllerProps = InputDateProps & UseInputControllerProps;

export const InputDateController = ({
  name,
  showSuccess,
  helper,
  ...props
}: InputDateControllerProps) => {
  const {setValue} = useFormContext();
  const inputController = useInputController({
    name,
    showSuccess,
    helperText: helper,
  });

  const onClearInput = useCallback(() => {
    setValue(name, null);
  }, [name, setValue]);

  return <InputDate {...props} {...inputController} onClear={onClearInput} />;
};
