import { useMemo, useState } from 'react'
import { addDays, format } from 'date-fns'
import { DateRange, Matcher } from 'react-day-picker'

import { DisableCalendarDates } from '../CalendarTypes'

type Props = {
  disableCalendarDates?: DisableCalendarDates
  calendarRange?: DateRange
  updateCalendarMonthNavigation?: boolean
  updateCalendarDefaultMonth?: number
}

export const useUpdateDisabledDates = ({
  disableCalendarDates,
  calendarRange,
  updateCalendarMonthNavigation,
  updateCalendarDefaultMonth,
}: Props) => {
  const [overlappingDate, setOverlappingDate] = useState<
    DateRange[] | undefined
  >(undefined)

  const [lastPossibleCheckout, setLatsPossibleCheckout] = useState<Matcher>([])

  const newDisableCalendarDates = useMemo(() => {
    if (disableCalendarDates?.availableDates) {
      const dateFormat = 'dd-MM-yyyy'

      const { disabledDates } = disableCalendarDates

      const { updatedDisabledDates, newOverlappingDates } = (
        disabledDates || []
      ).reduce(
        (
          acc: {
            updatedDisabledDates: { to: Date; from: Date }[]
            newOverlappingDates: { to: Date; from: Date }[]
          },
          dateRange
        ) => {
          const formattedFromDate = format(dateRange.from, dateFormat)
          const formattedToDate = format(dateRange.to, dateFormat)

          const hasTwoOverlappingDates =
            disableCalendarDates.availableDates?.some(
              (item) =>
                format(item.lastCheckOut, dateFormat) === formattedFromDate &&
                format(item.lastCheckOut, dateFormat) === formattedToDate
            )

          const hasOneOverlappingDate =
            disableCalendarDates.availableDates?.some(
              (item) =>
                format(item.lastCheckOut, dateFormat) === formattedFromDate &&
                format(item.lastCheckOut, dateFormat) !== formattedToDate
            )

          if (hasTwoOverlappingDates) {
            acc.newOverlappingDates.push(dateRange)
          } else if (hasOneOverlappingDate) {
            acc.newOverlappingDates.push(dateRange)
            acc.updatedDisabledDates.push({
              ...dateRange,
              from: addDays(dateRange.from, 1),
            })
          } else {
            acc.updatedDisabledDates.push(dateRange)
          }

          return acc
        },
        { updatedDisabledDates: [], newOverlappingDates: [] }
      )

      // Find last possible checkout ( disable all dates after the last possible checkout )
      const lastPossibleCheckoutDate: Date | undefined =
        disableCalendarDates.availableDates.at(-1)?.lastCheckOut

      if (lastPossibleCheckoutDate) {
        setLatsPossibleCheckout({ after: lastPossibleCheckoutDate })
      }

      // Extract overlapping dates ( dates that are only available for checkout )
      if (newOverlappingDates.length) {
        setOverlappingDate([...newOverlappingDates])
      }

      const newDisableCalendarDates = {
        ...disableCalendarDates,
        disabledDates: updatedDisabledDates,
      }

      return newDisableCalendarDates
    }
    return disableCalendarDates
  }, [
    disableCalendarDates,
    calendarRange,
    updateCalendarMonthNavigation,
    updateCalendarDefaultMonth,
  ])

  return { newDisableCalendarDates, overlappingDate, lastPossibleCheckout }
}
