import { useEffect, useRef, useState, } from 'react';
import { DEFAULT_DATE_MASK, DEFAULT_MAX_DATE, DEFAULT_MIN_DATE, useMaskedValue, useSelectedBaseDate, } from '../../DatePicker';
import { useForwardedRef } from '../../useForwardedRef';
import { usePopover } from '../../usePopover';
import { isMaskedDateSyntacticallyComplete } from '../../utils/date';
import { useBaseRangeDates } from './hooks';
import { getBoundaryDate } from './utils';
export const useLogic = ({ value, minDate = DEFAULT_MIN_DATE, maxDate = DEFAULT_MAX_DATE, mask = DEFAULT_DATE_MASK, onChange, onOpen, onClose, onBlur, }, forwardedRef) => {
    const ref = useForwardedRef(forwardedRef);
    const startInputRef = useRef(null);
    const endInputRef = useRef(null);
    const [hoveredDayDate, setHoveredDayDate] = useState();
    /**
     * Была ли выбрана start/end-дата после открытия поповера
     */
    const [isStartDateSelected, setIsStartDateSelected] = useState(false);
    const [isEndDateSelected, setIsEndDateSelected] = useState(false);
    const [activeInput, setActiveInput] = useState();
    const [isPopoverHovered, setIsPopoverHovered] = useState(false);
    const { isOpen, actions } = usePopover();
    const { open, close } = actions;
    useEffect(() => {
        setIsStartDateSelected(false);
        setIsEndDateSelected(false);
    }, [isOpen]);
    const selectedStartBaseDate = useSelectedBaseDate({
        currentValue: value?.start,
        minDate,
        maxDate,
    });
    const selectedEndBaseDate = useSelectedBaseDate({
        currentValue: value?.end,
        minDate,
        maxDate,
    });
    const { startBaseDate, endBaseDate } = useBaseRangeDates({
        minDate,
        maxDate,
        shouldReturnPrevValues: isOpen,
        selectedStartDate: selectedStartBaseDate,
        selectedEndDate: selectedEndBaseDate,
    });
    const handleChangeStartDate = (startDateValue, startMaskString) => {
        const isStartComplete = startDateValue != null &&
            startMaskString != null &&
            isMaskedDateSyntacticallyComplete(startMaskString, mask);
        if (isStartComplete &&
            value?.end &&
            startDateValue &&
            startDateValue > value.end) {
            onChange?.({ start: startDateValue, end: undefined });
            return;
        }
        onChange?.({ ...value, start: startDateValue });
    };
    const handleChangeEndDate = (endDateValue, endMaskString) => {
        const isEndComplete = endDateValue != null &&
            endMaskString != null &&
            isMaskedDateSyntacticallyComplete(endMaskString, mask);
        if (isEndComplete &&
            value?.start &&
            endDateValue &&
            endDateValue < value.start) {
            onChange?.({ start: undefined, end: endDateValue });
            return;
        }
        onChange?.({ ...value, end: endDateValue });
    };
    const { maskedValue: startMaskedValue, onMaskedValueChange: onMaskedStartValueChange, onMaskedValueBlur: onMaskedStartValueBlur, onMaskedDateChange: onMaskedStartDateChange, } = useMaskedValue({
        currentValue: value?.start,
        mask,
        onChangeValue: handleChangeStartDate,
    });
    const { maskedValue: endMaskedValue, onMaskedValueChange: onMaskedEndValueChange, onMaskedValueBlur: onMaskedEndValueBlur, onMaskedDateChange: onMaskedEndDateChange, } = useMaskedValue({
        currentValue: value?.end,
        mask,
        onChangeValue: handleChangeEndDate,
    });
    const handleOpen = (event) => {
        onOpen?.();
        open(event);
    };
    const flushActiveMaskedValueOnClose = () => {
        if (activeInput === 'startDate') {
            onMaskedStartValueBlur();
        }
        if (activeInput === 'endDate') {
            onMaskedEndValueBlur();
        }
    };
    const handleClose = () => {
        flushActiveMaskedValueOnClose();
        onBlur?.();
        onClose?.();
        close();
    };
    const handleStartInputBlur = () => {
        if (isOpen) {
            return;
        }
        onMaskedStartValueBlur();
    };
    const handleEndInputBlur = () => {
        if (isOpen) {
            return;
        }
        onMaskedEndValueBlur();
    };
    const handleClickStartInput = (e) => {
        setActiveInput('startDate');
        startInputRef.current?.focus();
        if (!isOpen) {
            handleOpen(e);
        }
    };
    const handleClickEndInput = (e) => {
        setActiveInput('endDate');
        endInputRef.current?.focus();
        if (!isOpen) {
            handleOpen(e);
        }
    };
    const pickStartDate = (pickedDate) => {
        onMaskedStartDateChange(pickedDate);
        setIsStartDateSelected(true);
        setActiveInput('endDate');
        endInputRef.current?.focus();
        if (isEndDateSelected) {
            handleClose();
        }
    };
    const pickEndDate = (pickedDate) => {
        onMaskedEndDateChange(pickedDate);
        setIsEndDateSelected(true);
        setActiveInput('startDate');
        startInputRef.current?.focus();
        if (isStartDateSelected) {
            handleClose();
        }
    };
    const handleDayPick = (pickedDate) => {
        if (activeInput === 'startDate') {
            pickStartDate(pickedDate);
        }
        if (activeInput === 'endDate') {
            pickEndDate(pickedDate);
        }
    };
    const handleAcceptStart = (_, maskRef) => {
        onMaskedStartValueChange(maskRef.value);
    };
    const handleAcceptEnd = (_, maskRef) => {
        onMaskedEndValueChange(maskRef.value);
    };
    const handlePopoverMouseEnter = () => setIsPopoverHovered(true);
    const handlePopoverMouseLeave = () => setIsPopoverHovered(false);
    return {
        ref,
        startDatePickerInputProps: {
            ref: startInputRef,
            value: startMaskedValue,
            onAccept: handleAcceptStart,
            onBlur: handleStartInputBlur,
            onClick: handleClickStartInput,
        },
        endDatePickerInputProps: {
            ref: endInputRef,
            value: endMaskedValue,
            onAccept: handleAcceptEnd,
            onBlur: handleEndInputBlur,
            onClick: handleClickEndInput,
        },
        popoverHoveredContextProviderProps: {
            popoverHovered: isPopoverHovered,
        },
        datePickerPopoverProps: {
            open: isOpen,
            anchorEl: ref.current,
            onMouseEnter: handlePopoverMouseEnter,
            onMouseLeave: handlePopoverMouseLeave,
            onClose: handleClose,
        },
        minMaxDateContextProviderProps: {
            minDate: isStartDateSelected
                ? getBoundaryDate({
                    reserve: minDate,
                    target: value?.start,
                })
                : minDate,
            maxDate: isEndDateSelected
                ? getBoundaryDate({
                    reserve: maxDate,
                    target: value?.end,
                })
                : maxDate,
        },
        startYearMonthDayPickerProps: {
            selectedDate: selectedStartBaseDate || selectedEndBaseDate,
            rangeDate: value?.end || value?.start,
            date: startBaseDate,
            hoveredDayDate,
            onDayHover: setHoveredDayDate,
            onChange: handleDayPick,
        },
        endYearMonthDayPickerProps: {
            selectedDate: selectedStartBaseDate || selectedEndBaseDate,
            rangeDate: value?.end || value?.start,
            date: endBaseDate,
            hoveredDayDate,
            onDayHover: setHoveredDayDate,
            onChange: handleDayPick,
        },
    };
};
