import { useRef, useState } from 'react';
import CustomDayPicker from './CustomDayPicker';
import classNames from 'classnames';
import cleanFieldProps from '../utilities/cleanFieldProps';
import describeField from '../utilities/describeField';
import { isMatch } from 'date-fns';
import mergeIds from '../utilities/mergeIds';
import useLabelMask from '../TextField/useLabelMask';
import useClickOutsideHandler from '../utilities/useClickOutsideHandler';
import usePressEscapeHandler from '../utilities/usePressEscapeHandler';
import useId from '../utilities/useId';
import { CalendarIcon } from '../Icons/CalendarIcon';
import { DATE_MASK } from '../TextField/useLabelMask';
import { Label } from '../Label';
import { TextInput } from '../TextField';
import { t } from '../i18n';
import { useLabelProps } from '../Label/useLabelProps';
import { useHint } from '../Hint/useHint';
import { useInlineError } from '../InlineError/useInlineError';
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
/**
 * For information about how and when to use this component, refer to the
 * [Single Input Date Field](https://design.cms.gov/components/date-field/single-input-date-field/) and
 * [Calendar Picker](https://design.cms.gov/components/date-field/date-picker/) documentation pages.
 */
const SingleInputDateField = props => {
  const {
    className,
    onChange,
    defaultMonth,
    fromDate,
    fromMonth,
    fromYear,
    toDate,
    toMonth,
    toYear,
    ...remainingProps
  } = props;
  const withPicker = (fromDate != null || fromMonth != null || Number.isInteger(fromYear)) && (toDate != null || toMonth != null || Number.isInteger(toYear));
  const [pickerVisible, setPickerVisible] = useState(false);
  const id = useId('date-field--', props.id);
  const isControlled = remainingProps.value !== undefined;
  const [internalValueState, setInternalValueState] = useState(remainingProps.defaultValue);
  const value = isControlled ? remainingProps.value : internalValueState;

  // Set up change handlers
  const handleInputChange = event => {
    const updatedValue = event.currentTarget.value;
    if (onChange) {
      onChange(updatedValue, DATE_MASK(updatedValue, true));
    }
    if (!isControlled) {
      setInternalValueState(updatedValue);
    }
  };
  const handlePickerChange = date => {
    const updatedValue = `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`;
    const maskedValue = DATE_MASK(updatedValue);
    if (onChange) {
      onChange(maskedValue, DATE_MASK(updatedValue, true));
    }
    if (!isControlled) {
      setInternalValueState(maskedValue);
    }
    setPickerVisible(false);
    inputRef.current?.focus();
  };

  // Collect all the props and elements for the input and its labels
  const {
    errorId,
    topError,
    bottomError,
    invalid
  } = useInlineError({
    ...props,
    id
  });
  const {
    hintId,
    hintElement
  } = useHint({
    ...props,
    id
  });
  const labelProps = useLabelProps({
    ...props,
    id
  });
  const inputRef = useRef();
  const {
    labelMask,
    inputProps
  } = useLabelMask(DATE_MASK, {
    ...cleanFieldProps(remainingProps),
    value,
    id,
    onChange: handleInputChange,
    type: 'text',
    inputRef,
    'aria-invalid': invalid,
    'aria-describedby': describeField({
      ...props,
      errorId,
      hintId
    })
  });

  // Handle alternate ways of closing the day picker
  const dayPickerRef = useRef();
  const calendarButtonRef = useRef();
  useClickOutsideHandler([dayPickerRef, calendarButtonRef], () => setPickerVisible(false));
  usePressEscapeHandler(dayPickerRef, () => {
    setPickerVisible(false);
    inputRef.current?.focus();
  });

  // Validate the date string (value) and make date null if it's invalid. We don't want to pass
  // a bizarre date to DayPicker like `new Date('01/02')`, which is interpreted as `Jan 02, 2001`
  const dateString = DATE_MASK(props.value, true);
  const validDateString = isMatch(dateString, 'MM/dd/yyyy');
  const date = validDateString ? new Date(dateString) : null;
  return /*#__PURE__*/_jsxs("div", {
    className: classNames('ds-c-single-input-date-field', withPicker && 'ds-c-single-input-date-field--with-picker', className),
    children: [/*#__PURE__*/_jsx(Label, {
      ...labelProps,
      fieldId: id
    }), hintElement, topError, labelMask, /*#__PURE__*/_jsxs("div", {
      className: "ds-c-single-input-date-field__field-wrapper",
      children: [/*#__PURE__*/_jsx(TextInput, {
        ...inputProps
      }), withPicker && /*#__PURE__*/_jsx("button", {
        className: "ds-c-single-input-date-field__button",
        onClick: () => setPickerVisible(!pickerVisible),
        type: "button",
        ref: calendarButtonRef,
        "aria-describedby": mergeIds(labelProps.id, hintId),
        children: /*#__PURE__*/_jsx(CalendarIcon, {
          ariaHidden: false,
          title: t(pickerVisible ? 'singleInputDateField.close' : 'singleInputDateField.open'),
          id: `${id}__icon`
        })
      })]
    }), pickerVisible && /*#__PURE__*/_jsx("div", {
      ref: dayPickerRef,
      role: "dialog",
      children: /*#__PURE__*/_jsx(CustomDayPicker, {
        selected: date,
        onSelect: handlePickerChange,
        defaultMonth: date ?? defaultMonth,
        fromDate,
        fromMonth,
        fromYear,
        toDate,
        toMonth,
        toYear
      })
    }), bottomError]
  });
};
export default SingleInputDateField;