import './AvailabilityCalendarForm.scss'
import React, { useMemo, useCallback } from 'react'
import AvailabilityCalendar from 'components/AvailabilityCalendar'
import { FieldTimeRange } from 'components/Form/FormListTimeRangeField'
import { FormikProps } from 'formik'
import { Experience1to1FormValues } from '../FormModel/initial-values'
import { DATE_FORTMAT } from 'utils/available-periods'
import { ArrayServices } from 'utils/array'
import SelectTimeZone from 'components/SelectTimeZone'

interface AvailabilityCalendarFormProps {
  isBooked: boolean
  timezone: string
  setTimezone: (value: React.SetStateAction<string>) => void
  availablePeriods: Map<string, FieldTimeRange[]>
  bookingDates: string[]
  setAvailablePeriods: (
    value: React.SetStateAction<Map<string, FieldTimeRange[]>>
  ) => void
}

const AvailabilityCalendarForm: React.FC<
  FormikProps<Experience1to1FormValues> & AvailabilityCalendarFormProps
> = ({
  isBooked = false,
  timezone,
  setTimezone,
  availablePeriods,
  bookingDates,
  setAvailablePeriods,
  ...props
}) => {
  const descriptionTimeRange = useMemo(() => {
    const selected = props.values.selectedDate?.[0]
    if (selected)
      return `What hours are you available on ${selected.format(
        'DD MMMM, YYYY'
      )}?`
    return `What hours are you available?`
  }, [props.values.selectedDate])

  const upsertAvailablePeriods = (key: string, value: FieldTimeRange[]) => {
    setAvailablePeriods(prev => new Map(prev).set(key, value))
  }

  const handleChangeDateSelected = useCallback(
    (selected: moment.Moment) => {
      props.setFieldValue(
        'periods',
        availablePeriods?.get(selected.clone().format(DATE_FORTMAT)) || []
      )
      props.setFieldValue('selectedDate', [selected])
    },
    [availablePeriods]
  )

  const handleAddTimeRange = useCallback(
    (value: FieldTimeRange, selectedDate: moment.Moment[]) => {
      const date = selectedDate?.[0].clone().format(DATE_FORTMAT)
      const periods = ArrayServices.append(
        availablePeriods?.get(date) || [],
        value
      )
      upsertAvailablePeriods(date, periods)
    },
    [availablePeriods]
  )

  const handleEditTimeRange = useCallback(
    (
      index: number,
      oldvalue: FieldTimeRange,
      newvalue: FieldTimeRange,
      selectedDate: moment.Moment[]
    ) => {
      const date = selectedDate?.[0].clone().format(DATE_FORTMAT)
      const periods = ArrayServices.updateWithIndex(
        availablePeriods?.get(date) || [],
        index,
        newvalue
      )
      upsertAvailablePeriods(date, periods)
    },
    [availablePeriods]
  )

  const handleDeleteTimeRange = useCallback(
    (index: number, value: FieldTimeRange, selectedDate: moment.Moment[]) => {
      const date = selectedDate?.[0].clone().format(DATE_FORTMAT)
      const periods = ArrayServices.removeWithIndex(
        availablePeriods?.get(date) || [],
        index
      )
      upsertAvailablePeriods(date, periods)
    },
    [availablePeriods]
  )

  const dayHasAvailablePeriods = useMemo(() => {
    const days = []
    for (const [key, value] of availablePeriods) {
      // get day have periods > 0
      if (Array.isArray(value) && value.length > 0) {
        days.push(key)
      }
    }
    return days
  }, [availablePeriods])

  return (
    <React.Fragment>
      <AvailabilityCalendar
        className="availability-calendar"
        dayHasAvailablePeriods={dayHasAvailablePeriods}
        selected={props.values.selectedDate}
        selectedTimezone={timezone}
        onDayClickCallback={handleChangeDateSelected}
      />
      <SelectTimeZone
        defaultTimeZone={timezone}
        onChange={value => setTimezone(value.timezone)}
      />
      <div className="availability-form__content m__t--24">
        <FieldTimeRange
          {...props}
          selectedTimeZone={timezone}
          bookingDates={bookingDates}
          description={descriptionTimeRange}
          isBooked={isBooked}
          descriptionClassName="text--regular18 m__b--20"
          onAdd={handleAddTimeRange}
          onEdit={handleEditTimeRange}
          onRemove={handleDeleteTimeRange}
        />
      </div>
    </React.Fragment>
  )
}

export default AvailabilityCalendarForm
