import { FieldTimeRange } from 'components/Form/FormListTimeRangeField'
import { AvailablePeriod } from 'models/availability-calendar/availability-calendar.model'
import { DateRange } from 'moment-range'
import { ArrayServices } from './array'
import { isSameDay } from 'utils/date'
import moment from 'moment'
import momentTZ from 'moment-timezone'

export const DATE_FORTMAT = 'YYYY-MM-DD'

export const isOverlapsTimeRange = (
  ranges: DateRange[] = [],
  range: DateRange
): boolean => {
  if (!ranges || !ranges.length || (Array.isArray(ranges) && ranges.length < 1))
    return false
  for (let i = 0; i < ranges.length; i++) {
    if (range.overlaps(ranges[i])) {
      return true
    }
  }
  return false
}

export const getFirstAvailablePeriods = (
  availablePeriods: Map<string, FieldTimeRange[]>
) => {
  for (const [date, periods] of availablePeriods) {
    if (
      moment(date).isSameOrAfter(moment()) ||
      isSameDay(moment(date as string), moment())
    ) {
      return { date, periods }
    }
  }
  return null
}

export const availablePeriodsToMap = (
  periods: AvailablePeriod[],
  timezone: string
): Map<string, FieldTimeRange[]> => {
  const map = periods.reduce((acc, curr) => {
    const startTimeTZ = momentTZ.tz(curr.start, timezone)
    const endTimeTZ = momentTZ.tz(curr.end, timezone)
    const startTimeF = startTimeTZ.clone().format(DATE_FORTMAT)
    const endTimeF = endTimeTZ.clone().format(DATE_FORTMAT)
    if (startTimeF === endTimeF) {
      const key = startTimeTZ.clone().format(DATE_FORTMAT)
      const value = {
        startTime: startTimeTZ,
        endTime: endTimeTZ
      }
      acc.set(key, ArrayServices.append(acc.get(key) || [], value))
    } else {
      const keyStart = startTimeTZ.clone().format(DATE_FORTMAT)
      const keyEnd = endTimeTZ.clone().format(DATE_FORTMAT)
      const value1 = {
        startTime: startTimeTZ,
        endTime: startTimeTZ.clone().startOf('day').hours(23).minutes(30)
      }
      const value2 = {
        startTime: endTimeTZ.clone().startOf('day'),
        endTime: endTimeTZ
      }
      acc.set(keyStart, ArrayServices.append(acc.get(keyStart) || [], value1))
      acc.set(keyEnd, ArrayServices.append(acc.get(keyEnd) || [], value2))
    }
    return acc
  }, new Map<string, FieldTimeRange[]>())
  return map
}

export const availablePeriodsToUTC = (
  availablePeriods: Map<string, FieldTimeRange[]>,
  timezone: string
): AvailablePeriod[] => {
  const values = []
  for (const [date, periods] of availablePeriods) {
    for (const range of periods) {
      const start = momentTZ
        .tz(`${date} ${range.startTime.format('HH:mm:ss')}`, timezone)
        .utc()
        .toISOString()
      const end = momentTZ
        .tz(`${date} ${range.endTime.format('HH:mm:ss')}`, timezone)
        .utc()
        .toISOString()
      values.push({ start, end })
    }
  }
  return values
}
