import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useRef, forwardRef, useCallback } from 'react';
import styled, { css } from 'styled-components';
import { useConsolidatedRef, useFocusWithin, useI18n, useTestIds } from '../../../hooks';
import { defaultThemeProp } from '../../../theme';
import Flex from '../../Flex';
import FormField, { StyledFormField } from '../../FormField/FormField';
import DateRangePicker from '../Picker/DateRangePicker';
import { StyledRangeInputContainer } from '../../Input/Input.styles';
import { getDateRangeInputTestIds } from '../DateTime.test-ids';
import { withTestIds } from '../../../utils';
import DateInput from './DateInput';
import { parseToDate } from './utils';
import StyledDateInput from './DateTime.styles';
const StyledDateRangeInput = styled.div(props => {
    const { theme: { components: { input } } } = props;
    return css `
    border: 0;
    min-width: min-content;

    ${StyledFormField} {
      &:last-child > ${StyledDateInput} {
        margin-inline-start: -${input['border-width']};
      }
      & legend {
        align-self: center;
      }
      &:focus,
      &:hover,
      &:focus-within {
        z-index: 2;
      }
    }
  `;
});
StyledDateRangeInput.defaultProps = defaultThemeProp;
const convertToCallbackParameter = (v) => {
    return {
        valueAsISOString: v === undefined || Number.isNaN(v) ? undefined : new Date(v).toISOString(),
        valueAsTimestamp: v
    };
};
const prepareValue = (v, type) => {
    if (v === undefined || Number.isNaN(v)) {
        return v;
    }
    return type === 'start'
        ? new Date(v).setUTCHours(0, 0, 0, 0)
        : new Date(v).setUTCHours(23, 59, 59, 999);
};
const getSelected = (first, second) => {
    const selected = first ?? second;
    return selected ? parseToDate(selected) : undefined;
};
const parseValueToDate = (value) => {
    return value ? parseToDate(value) : undefined;
};
const DateRangeInput = forwardRef(function DateRangeInput({ testId, value = {}, min, max, label, fromLabel, toLabel, labelHidden, status, required, readOnly, disabled, onChange, onFocus, onBlur, showWeekNumber, autoFocus, fromAdditionalInfo, toAdditionalInfo, ...restProps }, ref) {
    const testIds = useTestIds(testId, getDateRangeInputTestIds);
    const t = useI18n();
    const endDateHandle = useRef(null);
    const start = value.start === undefined || value.start === ''
        ? undefined
        : prepareValue(parseToDate(value.start).getTime(), 'start');
    const end = value.end === undefined || value.end === ''
        ? undefined
        : prepareValue(parseToDate(value.end).getTime(), 'end');
    const startDateRef = useRef(convertToCallbackParameter(start));
    const endDateRef = useRef(convertToCallbackParameter(end));
    const onFocusChange = useCallback((focused) => {
        (focused ? onFocus : onBlur)?.({
            start: startDateRef.current,
            end: endDateRef.current
        });
    }, [onFocus, onBlur]);
    const containerRef = useConsolidatedRef(ref);
    useFocusWithin([containerRef], onFocusChange);
    const onStartDateChange = (selectedDate) => {
        const selected = selectedDate?.getTime();
        if (end && selected && selected > end) {
            startDateRef.current = convertToCallbackParameter(prepareValue(end, 'start'));
            endDateRef.current = convertToCallbackParameter(prepareValue(selected, 'end'));
            onChange({
                start: convertToCallbackParameter(prepareValue(end, 'start')),
                end: convertToCallbackParameter(prepareValue(selected, 'end'))
            });
        }
        else {
            startDateRef.current = convertToCallbackParameter(prepareValue(selected, 'start'));
            endDateRef.current = convertToCallbackParameter(end);
            onChange({
                start: convertToCallbackParameter(prepareValue(selected, 'start')),
                end: convertToCallbackParameter(end)
            });
        }
        endDateHandle.current?.setOpen(true);
    };
    const onEndDateChange = (selectedDate) => {
        const selected = selectedDate?.getTime();
        if (start && selected && selected < start) {
            endDateRef.current = convertToCallbackParameter(prepareValue(start, 'end'));
            startDateRef.current = convertToCallbackParameter(prepareValue(selected, 'start'));
            onChange({
                end: convertToCallbackParameter(prepareValue(start, 'end')),
                start: convertToCallbackParameter(prepareValue(selected, 'start'))
            });
        }
        else {
            endDateRef.current = convertToCallbackParameter(prepareValue(selected, 'end'));
            startDateRef.current = convertToCallbackParameter(start);
            onChange({
                start: convertToCallbackParameter(start),
                end: convertToCallbackParameter(prepareValue(selected, 'end'))
            });
        }
    };
    const getSelectedRange = () => {
        const startDate = parseValueToDate(start);
        const endDate = parseValueToDate(end);
        if (startDate && endDate && startDate > endDate)
            return undefined;
        return {
            startDate,
            endDate
        };
    };
    const commonProps = {
        required,
        readOnly,
        disabled,
        min,
        max,
        status
    };
    return (_jsx(FormField, { testId: testIds, as: StyledDateRangeInput, ...restProps, ref: containerRef, container: { wrap: 'nowrap' }, labelHidden: labelHidden, label: label, labelAs: 'legend', required: required, readOnly: readOnly, status: status, disabled: disabled, children: _jsxs(Flex, { container: true, as: StyledRangeInputContainer, children: [_jsx(DateInput, { testId: testIds.fromDate, ...commonProps, value: value.start, picker: {
                        renderer: DateRangePicker,
                        rendererProps: {
                            selected: getSelected(start, end),
                            selectedRange: getSelectedRange(),
                            onChange: onStartDateChange
                        }
                    }, onBlur: changedValue => {
                        const newValue = changedValue.state
                            ? changedValue
                            : convertToCallbackParameter(prepareValue(changedValue.valueAsTimestamp, 'start'));
                        startDateRef.current = newValue;
                        onChange({
                            start: newValue,
                            end: convertToCallbackParameter(prepareValue(end, 'end'))
                        });
                    }, additionalInfo: fromAdditionalInfo, label: fromLabel, "aria-label": `${t('range_from_datetime') + (label ? ` - ${label}` : '')}`, autoFocus: autoFocus }), _jsx(DateInput, { testId: testIds.toDate, ...commonProps, value: value.end, handle: endDateHandle, picker: {
                        renderer: DateRangePicker,
                        rendererProps: {
                            selected: getSelected(end, start),
                            selectedRange: getSelectedRange(),
                            onChange: onEndDateChange
                        }
                    }, onBlur: changedValue => {
                        const newValue = changedValue.state
                            ? changedValue
                            : convertToCallbackParameter(prepareValue(changedValue.valueAsTimestamp, 'end'));
                        endDateRef.current = newValue;
                        onChange({
                            start: convertToCallbackParameter(prepareValue(start, 'start')),
                            end: newValue
                        });
                    }, additionalInfo: toAdditionalInfo, label: toLabel, "aria-label": `${t('range_to_datetime') + (label ? ` - ${label}` : '')}` })] }) }));
});
export default withTestIds(DateRangeInput, getDateRangeInputTestIds);
//# sourceMappingURL=DateRangeInput.js.map