import moment from 'moment';
import { Dispatch, SetStateAction, useEffect } from 'react';
import { fillShortGapsDates } from '../commonFunctions';

type DateSetter = Dispatch<SetStateAction<Date | null>>;

const useFirstAvailableCheckInDate = (
  unavailableDates: string[],
  checkInDate: Date | null,
  setCheckInDate: DateSetter,
  setCheckOutDate?: DateSetter,
  checkOutDate?: Date | null
): void => {
  useEffect(() => {
    if (!checkInDate || !setCheckInDate || !Array.isArray(unavailableDates)) return;

    const filledDates = fillShortGapsDates(unavailableDates);
    const unavailableSet = new Set(filledDates.map(date => moment(date).format('YYYY-MM-DD')));

    const hasUnavailableInRange = (start: moment.Moment, end: moment.Moment): boolean => {
      const current = start.clone();
      while (current.isSameOrBefore(end, 'day')) {
        if (unavailableSet.has(current.format('YYYY-MM-DD'))) return true;
        current.add(1, 'day');
      }
      return false;
    };

    // 🆕 1. If checkout is before check-in, validate 7 days before checkout
    if (
      checkOutDate &&
      moment(checkOutDate).isBefore(moment(checkInDate), 'day')
    ) {
      const newCheckOut = moment(checkOutDate);
      const newCheckIn = newCheckOut.clone().subtract(8, 'days');

      const isRangeValid = !hasUnavailableInRange(newCheckIn, newCheckOut);

      if (isRangeValid) {
        setCheckInDate(newCheckIn.toDate());
        if (setCheckOutDate) setCheckOutDate(newCheckOut.toDate());
        return; // ✅ handled, skip rest of logic
      }
    }

    // 🔁 2. Continue with original logic
    let candidateCheckIn = moment(checkInDate);
    const candidateCheckOut = candidateCheckIn.clone().add(7, 'days');

    const isUserSelectedCheckInValid = !unavailableSet.has(candidateCheckIn.format('YYYY-MM-DD'))
      && !hasUnavailableInRange(candidateCheckIn, candidateCheckOut);

    if (isUserSelectedCheckInValid) {
      if (
        setCheckOutDate &&
        (
          !checkOutDate ||
          moment(checkOutDate).isBefore(candidateCheckIn.clone().add(7, 'days'), 'day') ||
          hasUnavailableInRange(candidateCheckIn, moment(checkOutDate))
        )
      ) {
        setCheckOutDate(candidateCheckIn.clone().add(7, 'days').toDate());
      }
      return;
    }

    while (true) {
      const candidateCheckOutLoop = candidateCheckIn.clone().add(7, 'days');
      if (!unavailableSet.has(candidateCheckIn.format('YYYY-MM-DD')) &&
        !hasUnavailableInRange(candidateCheckIn, candidateCheckOutLoop)) {

        if (!moment(checkInDate).isSame(candidateCheckIn, 'day')) {
          setCheckInDate(candidateCheckIn.toDate());
        }

        if (setCheckOutDate) {
          setCheckOutDate(candidateCheckOutLoop.toDate());
        }

        break;
      }

      candidateCheckIn.add(1, 'day');
    }

  }, [unavailableDates, checkInDate, setCheckInDate, setCheckOutDate, checkOutDate]);
};

export default useFirstAvailableCheckInDate;
