import { useEffect } from 'react'
import { DateRange } from 'react-day-picker'
import {
  isAfter,
  isEqual,
  isBefore,
  endOfDay,
  isWithinInterval,
  areIntervalsOverlapping,
} from 'date-fns'

import { DisableCalendarDates, RangeContext } from '../CalendarTypes'

type Props = {
  setCalendarHasError?: (arg: boolean) => void
  rangeContext?: RangeContext
  calendarRange?: DateRange
  calendarHasError?: boolean
  disabledDates?: DisableCalendarDates['disabledDates']
}

// Case: If the selected dates do not overlap with the rangeContext during continuous selection,
//       set setCalendarHasError to true. This will display an error message and
//       prevent the submission of the selected dates.

export const checkForContinuousSelection = ({
  setCalendarHasError,
  rangeContext,
  calendarRange,
  calendarHasError,
  disabledDates,
}: Props) => {
  const calendarRangeFrom = calendarRange?.from && endOfDay(calendarRange.from)
  const calendarRangeTo = calendarRange?.to && endOfDay(calendarRange.to)
  const rangeContextFrom = rangeContext?.from && endOfDay(rangeContext.from)
  const rangeContextTo = rangeContext?.to && endOfDay(rangeContext.to)

  // Checking if rangeFrom is equal to or before rangeContextTo
  const startIsEqualOrBeforeRangeContextEnd =
    calendarRangeFrom && rangeContextTo
      ? isBefore(calendarRangeFrom, rangeContextTo) ||
        isEqual(calendarRangeFrom, rangeContextTo)
      : null

  // Checking if rangeTo is equal to or after rangeContextFrom
  const endIsEqualOrAfterRangeContextStart =
    calendarRangeTo && rangeContextFrom && rangeContextTo
      ? isAfter(calendarRangeTo, rangeContextFrom) ||
        isEqual(calendarRangeTo, rangeContextFrom)
      : null

  // Check if selection overlapping unavailable dates
  const selectionOverlappingUnavailableDate = disabledDates?.find((range) => {
    const rangeFrom = endOfDay(range.from)
    const rangeTo = endOfDay(range.to)

    return (
      rangeContextFrom &&
      rangeContextTo &&
      areIntervalsOverlapping(
        { start: rangeContextFrom, end: rangeContextTo },
        { start: rangeFrom, end: rangeTo }
      ) &&
      calendarRangeFrom &&
      calendarRangeTo &&
      areIntervalsOverlapping(
        { start: calendarRangeFrom, end: calendarRangeTo },
        { start: rangeFrom, end: rangeTo }
      )
    )
  })

  useEffect(() => {
    if (
      (rangeContext &&
        calendarRangeFrom &&
        !startIsEqualOrBeforeRangeContextEnd) ||
      (rangeContext &&
        calendarRangeTo &&
        !endIsEqualOrAfterRangeContextStart) ||
      selectionOverlappingUnavailableDate
    ) {
      !!(setCalendarHasError && !calendarHasError) && setCalendarHasError(true)
    }
  })
}
