import React, { useContext } from 'react'
import classnames from 'classnames'
import {
  isPast,
  isSameDay,
  isAfter,
  isWithinInterval,
  endOfDay,
} from 'date-fns'
import Calendar from 'react-calendar'
import { dateFormatBackend } from '../../helpers/date'
import { getNextBigger, getNextSmaller } from '../../helpers/array'
import { WizardContext } from './context/wizardStore'

export default function MyCalendar({ ...props }) {
  const { onChange, state, daysBooked, daysBookedErrorMessage } = useContext(
    WizardContext
  )
  const { startDate: start, endDate: end } = state.formData
  const startDate = (start && new Date(start)) || null
  const endDate = (end && new Date(end)) || null

  const inSelection = !!start && !end
  const prevBooked = inSelection && getNextSmaller(daysBooked, start)
  const nextBooked = inSelection && getNextBigger(daysBooked, start)

  function isDateSelected(date: Date) {
    if (!startDate) {
      return false
    }

    if (isSameDay(date, startDate)) {
      return true
    }

    // if end is before start, it is not within
    if (endDate && !isAfter(endDate, startDate)) {
      return false
    }

    return isWithinInterval(date, {
      start: startDate,
      end: endDate || startDate,
    })
  }

  function tileClassName({ date, view }) {
    const isMonthView = view === 'month'
    const isDaysBookedLoaded = !!daysBooked
    const isInPast = isPast(endOfDay(date))
    const isBooked = daysBooked?.includes(dateFormatBackend(date))
    const isSelected = isDateSelected(date)
    return classnames({
      'react-calendar__tile--past': isMonthView && isInPast,
      'react-calendar__tile--booked':
        isMonthView && isDaysBookedLoaded && isBooked && !isInPast,
      'react-calendar__tile--free':
        isMonthView &&
        isDaysBookedLoaded &&
        !isBooked &&
        !isInPast &&
        !isSelected,
      'react-calendar__tile--selected-start':
        isMonthView && isSameDay(date, startDate),
      'react-calendar__tile--selected-end':
        isMonthView && isSameDay(date, endDate),
      'react-calendar__tile--selected': isSelected,
      'react-calendar__tile--unselectable':
        inSelection &&
        ((prevBooked && date < new Date(prevBooked)) ||
          (nextBooked && date > new Date(nextBooked))),
    })
  }

  if (daysBookedErrorMessage) {
    return (
      <div>
        Entschuldigen Sie, aber die Buchungszeiten konnten nicht geladen werden.
        Versuchen Sie es später nochmals.
      </div>
    )
  }

  return (
    <div {...props}>
      <h2 className="text-xl">Belegungsplan</h2>
      <Calendar
        minDate={new Date()}
        // @ts-ignore
        onClickDay={(date: Date, event: React.MouseEvent<HTMLInputElement>) => {
          event.preventDefault()
          event.stopPropagation()

          const targetClassList = event.currentTarget.classList

          if (
            targetClassList.contains('react-calendar__tile--past') ||
            targetClassList.contains('react-calendar__tile--booked') ||
            targetClassList.contains('react-calendar__tile--unselectable')
          ) {
            return
          }

          if (!startDate || !!endDate) {
            onChange({ startDate: dateFormatBackend(date), endDate: null })
            return
          }

          // when startDate set, but end missing
          if (isAfter(date, startDate)) {
            onChange({ endDate: dateFormatBackend(date) })
          } else {
            onChange({ startDate: dateFormatBackend(date), endDate: start })
          }
        }}
        tileClassName={tileClassName}
        value={null}
      />
      <div className="mt-3 flex justify-center">
        <div>
          <div className="inline-block w-5 h-5 bg-green-200 rounded align-text-bottom"></div>
          <span className="ml-2">Frei</span>
        </div>
        <div>
          <div className="ml-6 inline-block w-5 h-5 bg-red-200 rounded align-text-bottom"></div>
          <span className="ml-2">Belegt</span>
        </div>
      </div>
    </div>
  )
}
