import React from 'react'
import classnames from 'classnames'
import {
  isPast,
  isSameDay,
  isAfter,
  isWithinInterval,
  endOfDay,
} from 'date-fns'
import Calendar from 'react-calendar'
import useBookedDays from '../helpers/useDaysBooked'
import { dateFormatBackend } from '../helpers/date'
import { getNextBigger, getNextSmaller } from '../helpers/array'
import Loading from './loading'

export default function MyCalendar({
  start,
  end,
  onChange = null,
  className,
}: {
  start?: string
  end?: string
  onChange?: (arg0: any) => void
  className?: string
}) {
  const { daysBooked, daysBookedError, daysBookedLoading } = useBookedDays()

  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))),
      'react-calendar__tile--not-interactive': !onChange,
    })
  }

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

  return (
    <div className={className}>
      <h2 className="text-xl">Belegungsplan</h2>
      <Loading className="booking_calendar" loading={daysBookedLoading}>
        <Calendar
          defaultActiveStartDate={startDate}
          minDate={new Date()}
          // @ts-ignore
          onClickDay={(
            date: Date,
            event: React.MouseEvent<HTMLInputElement>
          ) => {
            if (!onChange) {
              return
            }

            const dateAsBackendFormat = dateFormatBackend(date)

            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
            }

            // when startDate missing or both are already set
            if (!startDate || (!!startDate && !!endDate)) {
              onChange({ startDate: dateAsBackendFormat, endDate: null })
              return
            }

            // when startDate set, but end missing
            if (isAfter(date, startDate)) {
              onChange({ endDate: dateAsBackendFormat })
            } else {
              onChange({
                startDate: dateAsBackendFormat,
                endDate: dateAsBackendFormat,
              })
            }
          }}
          tileClassName={tileClassName}
          value={null}
        />
      </Loading>
      <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>
  )
}
