import { addDays, endOfDay, isAfter, isBefore } from 'date-fns'
import { DateRange, Matcher } from 'react-day-picker'

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

type Props = {
  calendarRange?: DateRange
  disabledDates?: Matcher[]
  overlappingDate?: DateRange[]
  rangeContext?: RangeContext
  findFirstPossibleRangeContextCheckIn?: NonNullable<
    DisableCalendarDates['availableDates']
  >['0']
  findLastPossibleRangeContextCheckOut?: NonNullable<
    DisableCalendarDates['availableDates']
  >['0']
  currentSelectionLastCheckoutDate?: NonNullable<
    DisableCalendarDates['availableDates']
  >['0']
}

export const handleCalendarModifiers = ({
  calendarRange,
  disabledDates,
  overlappingDate,
  rangeContext,
  findFirstPossibleRangeContextCheckIn,
  findLastPossibleRangeContextCheckOut,
  currentSelectionLastCheckoutDate,
}: Props) => {
  // Parse data
  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)

  const filteredOverlappingDates = overlappingDate
    ? overlappingDate
        .filter((date) => {
          const dateFrom = date.from ? endOfDay(date.from) : null
          const isBeforeRange =
            dateFrom &&
            findFirstPossibleRangeContextCheckIn?.checkIn &&
            isBefore(dateFrom, findFirstPossibleRangeContextCheckIn?.checkIn)
          const isAfterRange =
            dateFrom &&
            findLastPossibleRangeContextCheckOut?.lastCheckOut &&
            isAfter(
              dateFrom,
              endOfDay(findLastPossibleRangeContextCheckOut?.lastCheckOut)
            )

          return !(isBeforeRange || isAfterRange)
        })
        .map((date) => ({ from: date.from }))
    : []

  return {
    booked: disabledDates || [],

    disabledAfterCheckIn: calendarRangeFrom
      ? [{ after: calendarRangeFrom }]
      : [],

    overlappingDate:
      !calendarRangeFrom && !!filteredOverlappingDates.length
        ? filteredOverlappingDates.map((date) => ({ from: date.from }))
        : [],

    noActiveSelectionStart: rangeContextFrom || [],

    noActiveSelectionMid: [
      rangeContextFrom && rangeContextTo
        ? { after: rangeContextFrom, before: rangeContextTo }
        : [],
    ],

    noActiveSelectionEnd: rangeContextTo || [],

    checkoutOptionsMid: [
      ...(calendarRangeFrom &&
      !calendarRangeTo &&
      currentSelectionLastCheckoutDate?.lastCheckOut
        ? [
            {
              after: calendarRangeFrom,
              before: addDays(currentSelectionLastCheckoutDate.lastCheckOut, 1),
            },
          ]
        : []),
    ],

    checkInOnly: [
      ...(findFirstPossibleRangeContextCheckIn?.checkIn &&
      rangeContext &&
      rangeContextFrom
        ? [
            {
              from: findFirstPossibleRangeContextCheckIn.checkIn,
              to: addDays(rangeContextFrom, -1),
            },
          ]
        : []),
    ],

    checkOutOnly: [
      ...(findLastPossibleRangeContextCheckOut?.checkIn &&
      findLastPossibleRangeContextCheckOut.lastCheckOut
        ? [
            {
              from: addDays(findLastPossibleRangeContextCheckOut.checkIn, 1),
              to: findLastPossibleRangeContextCheckOut.lastCheckOut,
            },
          ]
        : []),
    ],
  }
}
