import moment from 'moment'
import * as React from 'react'
import { type DateRange } from 'react-day-picker'

import Button from '../Button/Button'
import styles from './_datePicker.module.scss'

export type RangeButtonType =
  | 'last7Days'
  | 'next7Days'
  | 'thisWeekToDate'
  | 'thisWeek'
  | 'lastWeek'
  | 'nextWeek'
  | 'lastMonth'
  | 'thisMonth'
  | 'thisMonthToDate'
  | 'nextMonth'
  | 'thisQuarter'
  | 'thisQuarterToDate'
  | 'lastQuarter'
  | 'nextQuarter'
  | 'thisYear'
  | 'thisYearToDate'
  | 'lastYear'
  | 'nextYear'

export type SingleButtonType = 'today' | 'yesterday' | 'tomorrow'

export const trimWhitespace = (str: string): string => {
  return str.trim()
}

/**
 * Checks if the given string is either empty or contains only whitespace characters.
 *
 * @param {string} str - The string to check.
 * @returns {boolean} - Returns true if the string is empty or contains only whitespace, otherwise false.
 */
export const isEmptyOrWhitespace = (str: string): boolean => {
  return !str || trimWhitespace(str).length === 0
}

/**
 * Returns a date range object (`from` and `to` dates) based on the specified button type.
 *
 * @param {RangeButtonType} buttonType - The type of action button representing a specific date range.
 * @returns {DateRange} - An object containing `from` and `to` dates for the specified button type.
 */
export const getDateRangeForButtonType = (
  buttonType: RangeButtonType,
): DateRange => {
  const today = moment().startOf('day')
  let fromDate: Date
  let toDate: Date

  switch (buttonType) {
    case 'last7Days':
      fromDate = today.clone().subtract(7, 'days').toDate()
      toDate = today.clone().subtract(1, 'day').toDate()
      break
    case 'next7Days':
      fromDate = today.clone().add(1, 'day').toDate()
      toDate = today.clone().add(7, 'days').toDate()
      break
    case 'thisWeekToDate': {
      const sunday = today.clone().startOf('week')
      fromDate = sunday.toDate()
      toDate = today.toDate()
      break
    }
    case 'thisWeek': {
      const sunday = today.clone().startOf('week')
      const saturday = today.clone().endOf('week')
      fromDate = sunday.toDate()
      toDate = saturday.toDate()
      break
    }
    case 'lastWeek': {
      const lastWeekSunday = today.clone().subtract(1, 'week').startOf('week')
      const lastWeekSaturday = today.clone().subtract(1, 'week').endOf('week')
      fromDate = lastWeekSunday.toDate()
      toDate = lastWeekSaturday.toDate()
      break
    }
    case 'nextWeek': {
      const nextWeekSunday = today.clone().add(1, 'week').startOf('week')
      const nextWeekSaturday = today.clone().add(1, 'week').endOf('week')
      fromDate = nextWeekSunday.toDate()
      toDate = nextWeekSaturday.toDate()
      break
    }
    case 'thisMonth':
      fromDate = today.clone().startOf('month').toDate()
      toDate = today.clone().endOf('month').toDate()
      break
    case 'lastMonth':
      fromDate = today.clone().subtract(1, 'month').startOf('month').toDate()
      toDate = today.clone().subtract(1, 'month').endOf('month').toDate()
      break
    case 'thisMonthToDate':
      fromDate = today.clone().startOf('month').toDate()
      toDate = today.toDate()
      break
    case 'nextMonth':
      fromDate = today.clone().add(1, 'month').startOf('month').toDate()
      toDate = today.clone().add(1, 'month').endOf('month').toDate()
      break
    case 'thisQuarter':
      fromDate = today.clone().startOf('quarter').toDate()
      toDate = today.clone().endOf('quarter').toDate()
      break
    case 'thisQuarterToDate':
      fromDate = today.clone().startOf('quarter').toDate()
      toDate = today.toDate()
      break
    case 'lastQuarter':
      fromDate = today
        .clone()
        .subtract(1, 'quarter')
        .startOf('quarter')
        .toDate()
      toDate = today.clone().subtract(1, 'quarter').endOf('quarter').toDate()
      break
    case 'nextQuarter':
      fromDate = today.clone().add(1, 'quarter').startOf('quarter').toDate()
      toDate = today
        .clone()
        .add(1, 'quarter')
        .endOf('quarter')
        .startOf('day')
        .toDate()
      break
    case 'thisYearToDate':
      fromDate = today.clone().startOf('year').toDate()
      toDate = today.toDate()
      break
    case 'thisYear':
      fromDate = today.clone().startOf('year').toDate()
      toDate = today.clone().endOf('year').startOf('day').toDate()
      break
    case 'lastYear':
      fromDate = today.clone().subtract(1, 'year').startOf('year').toDate()
      toDate = today
        .clone()
        .subtract(1, 'year')
        .endOf('year')
        .startOf('day')
        .toDate()
      break
    case 'nextYear':
      fromDate = today.clone().add(1, 'year').startOf('year').toDate()
      toDate = today
        .clone()
        .add(1, 'year')
        .endOf('year')
        .startOf('day')
        .toDate()
      break
    default:
      fromDate = today.toDate()
      toDate = today.toDate()
  }

  return {
    from: fromDate,
    to: toDate,
  }
}

/**
 * Validates whether a given string is a valid date in the format MM/DD/YYYY.
 *
 * @param {string} dateString - The date string to validate.
 * @returns {boolean} - Returns true if the string is empty, contains only whitespace, or is a valid date in the specified format. Otherwise, returns false.
 */
export const isValidDateString = (dateString: string): boolean => {
  if (isEmptyOrWhitespace(dateString)) {
    return true
  }

  const trimmedDate = trimWhitespace(dateString)
  return moment(trimmedDate, 'MM/DD/YYYY', true).isValid()
}

/**
 * Parses a date range string in the format "MM/DD/YYYY - MM/DD/YYYY" into a DateRange object.
 *
 * @param {string} dateRangeString - The date range string to parse.
 * @returns {DateRange | null} - Returns a DateRange object with `from` and `to` dates if valid, otherwise null.
 */
export const parseDateRangeString = (
  dateRangeString: string,
): DateRange | null => {
  if (isEmptyOrWhitespace(dateRangeString)) {
    return null
  }

  const trimmedRange = trimWhitespace(dateRangeString)

  const dates = trimmedRange
    .split(/\s*-\s*/)
    .map((part) => trimWhitespace(part))

  if (dates.length !== 2) {
    return null
  }

  const fromDate = moment(dates[0], 'MM/DD/YYYY', true)
  const toDate = moment(dates[1], 'MM/DD/YYYY', true)

  if (!fromDate.isValid() || !toDate.isValid()) {
    return null
  }

  if (fromDate.isAfter(toDate)) {
    return {
      from: toDate.toDate(),
      to: fromDate.toDate(),
    }
  }

  return {
    from: fromDate.toDate(),
    to: toDate.toDate(),
  }
}
export const isDateRangeValidWithRestrictions = (
  dateRange: DateRange,
  dateRestrictions?: {
    beforeDate?: Date
    afterDate?: Date
  },
): boolean => {
  if (!dateRange.from || !dateRange.to) {
    return false
  }

  if (
    !dateRestrictions ||
    (!dateRestrictions.beforeDate && !dateRestrictions.afterDate)
  ) {
    return true
  }

  const fromDate = moment(dateRange.from).startOf('day')
  const toDate = moment(dateRange.to).startOf('day')

  if (dateRestrictions.beforeDate) {
    const beforeDate = moment(dateRestrictions.beforeDate).startOf('day')
    if (fromDate.isBefore(beforeDate) || toDate.isBefore(beforeDate)) {
      return false
    }
  }

  if (dateRestrictions.afterDate) {
    const afterDate = moment(dateRestrictions.afterDate).startOf('day')
    if (fromDate.isAfter(afterDate) || toDate.isAfter(afterDate)) {
      return false
    }
  }

  return true
}
/**
 * Adjusts a date range to comply with specified date restrictions.
 * If the date range falls outside the restrictions, it will be adjusted to the nearest valid dates.
 *
 * @param {DateRange} dateRange - The date range to be adjusted, containing `from` and `to` dates.
 * @param {Object} [dateRestrictions] - Optional restrictions for the date range.
 * @param {Date} [dateRestrictions.beforeDate] - The date before which the range cannot start.
 * @param {Date} [dateRestrictions.afterDate] - The date after which the range cannot end.
 * @returns {DateRange} - The adjusted date range that complies with the restrictions.
 */
export const adjustDateRangeWithRestrictions = (
  dateRange: DateRange,
  dateRestrictions?: {
    beforeDate?: Date
    afterDate?: Date
  },
): DateRange => {
  // Case 1: No restrictions or no dates
  if (!dateRange.from || !dateRange.to) {
    return dateRange
  }

  if (
    !dateRestrictions ||
    (!dateRestrictions.beforeDate && !dateRestrictions.afterDate)
  ) {
    return dateRange
  }

  const fromDate = moment(dateRange.from).startOf('day')
  const toDate = moment(dateRange.to).startOf('day')
  let adjustedFromDate = fromDate.clone()
  let adjustedToDate = toDate.clone()

  // Case 2: Check if entire range is in restricted area
  if (dateRestrictions.beforeDate) {
    const beforeDate = moment(dateRestrictions.beforeDate).startOf('day')
    if (fromDate.isBefore(beforeDate) && toDate.isBefore(beforeDate)) {
      return { from: undefined, to: undefined }
    }
  }

  if (dateRestrictions.afterDate) {
    const afterDate = moment(dateRestrictions.afterDate).startOf('day')
    if (fromDate.isAfter(afterDate) && toDate.isAfter(afterDate)) {
      return { from: undefined, to: undefined }
    }
  }

  // Case 3 & 4: Adjust dates to stay within restrictions
  if (dateRestrictions.beforeDate) {
    const beforeDate = moment(dateRestrictions.beforeDate).startOf('day')
    if (fromDate.isBefore(beforeDate)) {
      adjustedFromDate = beforeDate.clone()
    }
    if (toDate.isBefore(beforeDate)) {
      adjustedToDate = beforeDate.clone()
    }
  }

  if (dateRestrictions.afterDate) {
    const afterDate = moment(dateRestrictions.afterDate).startOf('day')
    if (fromDate.isAfter(afterDate)) {
      adjustedFromDate = afterDate.clone()
    }
    if (toDate.isAfter(afterDate)) {
      adjustedToDate = afterDate.clone()
    }
  }

  // If after adjustments, the range is invalid (from after to), return undefined
  if (adjustedFromDate.isAfter(adjustedToDate)) {
    return { from: undefined, to: undefined }
  }

  // Return the adjusted range
  return {
    from: adjustedFromDate.toDate(),
    to: adjustedToDate.toDate(),
  }
}

/**
 * Returns a date based on the specified single date button type.
 *
 * @param {SingleButtonType} buttonType - The type of action button representing a specific date
 * @returns {Date} - The date for the specified button type
 */
export const getDateForButtonType = (buttonType: SingleButtonType): Date => {
  switch (buttonType) {
    case 'today':
      return moment().startOf('day').toDate()
    case 'yesterday':
      return moment().subtract(1, 'day').startOf('day').toDate()
    case 'tomorrow':
      return moment().add(1, 'day').startOf('day').toDate()
  }
}

/**
 * Checks if a single date is valid considering restrictions like not showing past dates
 * and specific before/after date restrictions.
 *
 * @param {Date} date - The date to validate.
 * @param {boolean} showPastDates - Whether past dates are allowed.
 * @param {object} [dateRestrictions] - Optional restrictions for the date.
 * @param {Date} [dateRestrictions.beforeDate] - The date before which the input date is invalid.
 * @param {Date} [dateRestrictions.afterDate] - The date after which the input date is invalid.
 * @returns {boolean} - True if the date is valid within the restrictions, false otherwise.
 */
export const isSingleDateValidWithRestrictions = (
  date: Date,
  dateRestrictions?: {
    beforeDate?: Date
    afterDate?: Date
  },
): boolean => {
  const day = moment(date).startOf('day')
  if (
    dateRestrictions?.beforeDate &&
    day.isBefore(moment(dateRestrictions.beforeDate).startOf('day'))
  ) {
    return false
  }
  if (
    dateRestrictions?.afterDate &&
    day.isAfter(moment(dateRestrictions.afterDate).startOf('day'))
  ) {
    return false
  }
  return true
}

export type ButtonConfig = {
  show: boolean
  onClick: () => void
  label: string
  groupName: string
}

// Utility: Returns true if any date in the range is valid under the given restrictions; otherwise, returns false. Used to determine button visibility.
function isAnyDateInRangeValid(
  dateRange: DateRange,
  dateRestrictions?: { beforeDate?: Date; afterDate?: Date },
): boolean {
  if (!dateRange.from || !dateRange.to) return false
  const from = moment(dateRange.from).startOf('day')
  const to = moment(dateRange.to).startOf('day')
  const days = to.diff(from, 'days')
  for (let i = 0; i <= days; i++) {
    const d = from.clone().add(i, 'days').toDate()
    if (isSingleDateValidWithRestrictions(d, dateRestrictions)) {
      return true
    }
  }
  return false
}

// Utility: Returns true if the date range contains any restricted dates; otherwise, returns false. Used to hide buttons when their ranges contain restricted dates.
function doesDateRangeContainRestrictedDates(
  dateRange: DateRange,
  dateRestrictions?: { beforeDate?: Date; afterDate?: Date },
): boolean {
  if (!dateRange.from || !dateRange.to || !dateRestrictions) return false

  const from = moment(dateRange.from).startOf('day')
  const to = moment(dateRange.to).startOf('day')
  const days = to.diff(from, 'days')

  for (let i = 0; i <= days; i++) {
    const d = from.clone().add(i, 'days').toDate()
    if (!isSingleDateValidWithRestrictions(d, dateRestrictions)) {
      return true
    }
  }
  return false
}

export const getSingleDateButtonConfigs = ({
  showTodaySelector,
  showYesterdaySelector,
  showTomorrowSelector,
  selectToday,
  selectYesterday,
  selectTomorrow,
  dateRestrictions,
}: {
  showTodaySelector?: boolean
  showYesterdaySelector?: boolean
  showTomorrowSelector?: boolean
  selectToday: () => void
  selectYesterday: () => void
  selectTomorrow: () => void
  dateRestrictions?: { beforeDate?: Date; afterDate?: Date }
}): ButtonConfig[] => {
  return [
    {
      show:
        (showTodaySelector ?? true) &&
        isSingleDateValidWithRestrictions(
          getDateForButtonType('today'),
          dateRestrictions,
        ),
      onClick: selectToday,
      label: 'today',
      groupName: 'today',
    },
    {
      show:
        (showYesterdaySelector ?? true) &&
        isSingleDateValidWithRestrictions(
          getDateForButtonType('yesterday'),
          dateRestrictions,
        ),
      onClick: selectYesterday,
      label: 'yesterday',
      groupName: 'yesterday',
    },
    {
      show:
        (showTomorrowSelector ?? true) &&
        isSingleDateValidWithRestrictions(
          getDateForButtonType('tomorrow'),
          dateRestrictions,
        ),
      onClick: selectTomorrow,
      label: 'tomorrow',
      groupName: 'tomorrow',
    },
  ]
}

export const getRangeDateButtonConfigs = ({
  last7Days,
  next7Days,
  thisWeekToDate,
  thisWeek,
  lastWeek,
  nextWeek,
  thisMonth,
  lastMonth,
  thisMonthToDate,
  nextMonth,
  thisQuarter,
  thisQuarterToDate,
  lastQuarter,
  nextQuarter,
  thisYear,
  thisYearToDate,
  lastYear,
  nextYear,
  selectLast7Days,
  selectNext7Days,
  selectThisWeekToDate,
  selectThisWeek,
  selectLastWeek,
  selectNextWeek,
  selectThisMonth,
  selectLastMonth,
  selectThisMonthToDate,
  selectNextMonth,
  selectThisQuarter,
  selectThisQuarterToDate,
  selectLastQuarter,
  selectNextQuarter,
  selectThisYear,
  selectThisYearToDate,
  selectLastYear,
  selectNextYear,
  dateRestrictions,
}: {
  last7Days?: boolean
  next7Days?: boolean
  thisWeekToDate?: boolean
  thisWeek?: boolean
  lastWeek?: boolean
  nextWeek?: boolean
  thisMonth?: boolean
  lastMonth?: boolean
  thisMonthToDate?: boolean
  nextMonth?: boolean
  thisQuarter?: boolean
  thisQuarterToDate?: boolean
  lastQuarter?: boolean
  nextQuarter?: boolean
  thisYear?: boolean
  thisYearToDate?: boolean
  lastYear?: boolean
  nextYear?: boolean
  selectLast7Days: () => void
  selectNext7Days: () => void
  selectThisWeekToDate: () => void
  selectThisWeek: () => void
  selectLastWeek: () => void
  selectNextWeek: () => void
  selectThisMonth: () => void
  selectLastMonth: () => void
  selectThisMonthToDate: () => void
  selectNextMonth: () => void
  selectThisQuarter: () => void
  selectThisQuarterToDate: () => void
  selectLastQuarter: () => void
  selectNextQuarter: () => void
  selectThisYear: () => void
  selectThisYearToDate: () => void
  selectLastYear: () => void
  selectNextYear: () => void
  dateRestrictions?: { beforeDate?: Date; afterDate?: Date }
}): ButtonConfig[] => {
  return [
    {
      show:
        (last7Days ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('last7Days'),
          dateRestrictions,
        ),
      onClick: selectLast7Days,
      label: 'last7Days',
      groupName: 'days',
    },
    {
      show:
        (next7Days ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('next7Days'),
          dateRestrictions,
        ),
      onClick: selectNext7Days,
      label: 'next7Days',
      groupName: 'days',
    },
    {
      show:
        (thisWeekToDate ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('thisWeekToDate'),
          dateRestrictions,
        ),
      onClick: selectThisWeekToDate,
      label: 'thisWeekToDate',
      groupName: 'weeks',
    },
    {
      show:
        (thisWeek ?? true) &&
        !doesDateRangeContainRestrictedDates(
          getDateRangeForButtonType('thisWeek'),
          dateRestrictions,
        ),
      onClick: selectThisWeek,
      label: 'thisWeek',
      groupName: 'weeks',
    },
    {
      show:
        (lastWeek ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('lastWeek'),
          dateRestrictions,
        ),
      onClick: selectLastWeek,
      label: 'lastWeek',
      groupName: 'weeks',
    },
    {
      show:
        (nextWeek ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('nextWeek'),
          dateRestrictions,
        ),
      onClick: selectNextWeek,
      label: 'nextWeek',
      groupName: 'weeks',
    },
    {
      show:
        (thisMonthToDate ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('thisMonthToDate'),
          dateRestrictions,
        ),
      onClick: selectThisMonthToDate,
      label: 'thisMonthToDate',
      groupName: 'months',
    },
    {
      show:
        (thisMonth ?? true) &&
        !doesDateRangeContainRestrictedDates(
          getDateRangeForButtonType('thisMonth'),
          dateRestrictions,
        ),
      onClick: selectThisMonth,
      label: 'thisMonth',
      groupName: 'months',
    },
    {
      show:
        (lastMonth ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('lastMonth'),
          dateRestrictions,
        ),
      onClick: selectLastMonth,
      label: 'lastMonth',
      groupName: 'months',
    },
    {
      show:
        (nextMonth ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('nextMonth'),
          dateRestrictions,
        ),
      onClick: selectNextMonth,
      label: 'nextMonth',
      groupName: 'months',
    },
    {
      show:
        (thisQuarterToDate ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('thisQuarterToDate'),
          dateRestrictions,
        ),
      onClick: selectThisQuarterToDate,
      label: 'thisQuarterToDate',
      groupName: 'quarters',
    },
    {
      show:
        (thisQuarter ?? true) &&
        !doesDateRangeContainRestrictedDates(
          getDateRangeForButtonType('thisQuarter'),
          dateRestrictions,
        ),
      onClick: selectThisQuarter,
      label: 'thisQuarter',
      groupName: 'quarters',
    },
    {
      show:
        (lastQuarter ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('lastQuarter'),
          dateRestrictions,
        ),
      onClick: selectLastQuarter,
      label: 'lastQuarter',
      groupName: 'quarters',
    },
    {
      show:
        (nextQuarter ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('nextQuarter'),
          dateRestrictions,
        ),
      onClick: selectNextQuarter,
      label: 'nextQuarter',
      groupName: 'quarters',
    },
    {
      show:
        (thisYearToDate ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('thisYearToDate'),
          dateRestrictions,
        ),
      onClick: selectThisYearToDate,
      label: 'thisYearToDate',
      groupName: 'years',
    },
    {
      show:
        (thisYear ?? true) &&
        !doesDateRangeContainRestrictedDates(
          getDateRangeForButtonType('thisYear'),
          dateRestrictions,
        ),
      onClick: selectThisYear,
      label: 'thisYear',
      groupName: 'years',
    },
    {
      show:
        (lastYear ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('lastYear'),
          dateRestrictions,
        ),
      onClick: selectLastYear,
      label: 'lastYear',
      groupName: 'years',
    },
    {
      show:
        (nextYear ?? true) &&
        isAnyDateInRangeValid(
          getDateRangeForButtonType('nextYear'),
          dateRestrictions,
        ),
      onClick: selectNextYear,
      label: 'nextYear',
      groupName: 'years',
    },
  ]
}

export type MainButtonType = 'day' | 'week' | 'month' | 'quarter' | 'year'

export const renderButtons = (
  buttonConfigs: ButtonConfig[],
  selectedBtnType: SingleButtonType | RangeButtonType | null,
  c: (key: string) => string,
  type: 'single' | 'range',
  selectedGroup: string | null,
  onGroupSelect: (group: string | null) => void,
  reset: boolean,
  handleReset: () => void,
) => {
  const mainButtons: { type: MainButtonType; group: string }[] = [
    { type: 'day', group: 'days' },
    { type: 'week', group: 'weeks' },
    { type: 'month', group: 'months' },
    { type: 'quarter', group: 'quarters' },
    { type: 'year', group: 'years' },
  ]

  const renderBackButton = () => (
    <Button
      className={styles.actionButton}
      onClick={() => onGroupSelect(null)}
      icon='caretLeft'
    />
  )

  const renderResetButton = () => (
    <div className={styles.resetButtonContainer}>
      <div className={styles.resetButtonDivider}></div>
      <Button className={styles.actionButton} onClick={handleReset}>
        {c('reset')}
      </Button>
    </div>
  )

  const hasAvailableButtonsInGroup = (group: string): boolean => {
    return buttonConfigs.some(
      ({ show, groupName }) => show && groupName === group,
    )
  }

  const renderMainButtons = () => (
    <>
      {mainButtons
        .filter(({ group }) => hasAvailableButtonsInGroup(group))
        .map(({ type, group }) => (
          <Button
            key={type}
            className={`${styles.actionButton} ${selectedGroup === group ? styles.selectedAction : ''}`}
            onClick={() => onGroupSelect(group)}
          >
            {c(type)}
          </Button>
        ))}
      {reset ? renderResetButton() : null}
    </>
  )

  const renderGroupButtons = () => (
    <>
      {buttonConfigs
        .filter(({ show, groupName }) => show && groupName === selectedGroup)
        .map(({ onClick, label }) => (
          <Button
            key={label}
            className={`${styles.actionButton} ${selectedBtnType === label ? styles.selectedAction : ''}`}
            onClick={onClick}
          >
            {c(label)}
          </Button>
        ))}
    </>
  )

  const renderSingleDateButtons = () => (
    <>
      {buttonConfigs
        .filter(({ show }) => show)
        .map(({ onClick, label }) => (
          <Button
            key={label}
            className={`${styles.actionButton} ${selectedBtnType === label ? styles.selectedAction : ''}`}
            onClick={onClick}
          >
            {c(label)}
          </Button>
        ))}
      {reset ? renderResetButton() : null}
    </>
  )

  return (
    <div className={styles.actionButtonsContainer}>
      {type === 'range' && selectedGroup ? (
        <div className={styles.caretButton}>{renderBackButton()}</div>
      ) : (
        <></>
      )}
      <div
        className={`${styles.actionButtons} ${
          type === 'range'
            ? styles.actionButtonsInRange
            : styles.actionButtonsInSingle
        }`}
      >
        {type === 'single'
          ? renderSingleDateButtons()
          : selectedGroup
            ? renderGroupButtons()
            : renderMainButtons()}
      </div>
    </div>
  )
}

interface RenderActionButtonsParams {
  type: 'single' | 'range'
  actionButtons: any
  selectedBtnType: RangeButtonType | SingleButtonType | null
  c: (key: string) => string
  selectedGroup: string | null
  setSelectedGroup: (group: string | null) => void
  handlers: any
  reset: boolean
  handleReset: () => void
  dateRestrictions?: { beforeDate?: Date; afterDate?: Date }
}

export function renderActionButtons({
  type,
  actionButtons,
  selectedBtnType,
  c,
  selectedGroup,
  setSelectedGroup,
  handlers,
  reset,
  handleReset,
  dateRestrictions,
}: RenderActionButtonsParams) {
  if (type === 'single') {
    return renderButtons(
      getSingleDateButtonConfigs({
        showTodaySelector: actionButtons.today,
        showYesterdaySelector: actionButtons.yesterday,
        showTomorrowSelector: actionButtons.tomorrow,
        selectToday: handlers.selectToday!,
        selectYesterday: handlers.selectYesterday!,
        selectTomorrow: handlers.selectTomorrow!,
        dateRestrictions,
      }),
      selectedBtnType,
      c,
      type,
      selectedGroup,
      setSelectedGroup,
      reset,
      handleReset,
    )
  } else {
    return renderButtons(
      getRangeDateButtonConfigs({
        last7Days: actionButtons.last7Days,
        next7Days: actionButtons.next7Days,
        thisWeekToDate: actionButtons.thisWeekToDate,
        thisWeek: actionButtons.thisWeek,
        lastWeek: actionButtons.lastWeek,
        nextWeek: actionButtons.nextWeek,
        thisMonth: actionButtons.thisMonth,
        lastMonth: actionButtons.lastMonth,
        thisMonthToDate: actionButtons.thisMonthToDate,
        nextMonth: actionButtons.nextMonth,
        thisQuarter: actionButtons.thisQuarter,
        thisQuarterToDate: actionButtons.thisQuarterToDate,
        lastQuarter: actionButtons.lastQuarter,
        nextQuarter: actionButtons.nextQuarter,
        thisYear: actionButtons.thisYear,
        thisYearToDate: actionButtons.thisYearToDate,
        lastYear: actionButtons.lastYear,
        nextYear: actionButtons.nextYear,
        selectLast7Days: handlers.selectLast7Days!,
        selectNext7Days: handlers.selectNext7Days!,
        selectThisWeekToDate: handlers.selectThisWeekToDate!,
        selectThisWeek: handlers.selectThisWeek!,
        selectLastWeek: handlers.selectLastWeek!,
        selectNextWeek: handlers.selectNextWeek!,
        selectThisMonth: handlers.selectThisMonth!,
        selectLastMonth: handlers.selectLastMonth!,
        selectThisMonthToDate: handlers.selectThisMonthToDate!,
        selectNextMonth: handlers.selectNextMonth!,
        selectThisQuarter: handlers.selectThisQuarter!,
        selectThisQuarterToDate: handlers.selectThisQuarterToDate!,
        selectLastQuarter: handlers.selectLastQuarter!,
        selectNextQuarter: handlers.selectNextQuarter!,
        selectThisYear: handlers.selectThisYear!,
        selectThisYearToDate: handlers.selectThisYearToDate!,
        selectLastYear: handlers.selectLastYear!,
        selectNextYear: handlers.selectNextYear!,
        dateRestrictions,
      }),
      selectedBtnType,
      c,
      type,
      selectedGroup,
      setSelectedGroup,
      reset,
      handleReset,
    )
  }
}

// To check if the default date passed is valid or not with the restrictions
export const getSelectedDate = (
  selectedDate: Date | undefined,
  dateRestrictions?: {
    beforeDate?: Date
    afterDate?: Date
  },
) => {
  if (dateRestrictions && selectedDate) {
    return isSingleDateValidWithRestrictions(selectedDate, dateRestrictions)
      ? selectedDate
      : undefined
  }
  return selectedDate
}

// To check if the default date range passed is valid or not with the restrictions
export const getSelectedDateRange = (
  selectedDateRange: DateRange | undefined,
  dateRestrictions?: {
    beforeDate?: Date
    afterDate?: Date
  },
) => {
  if (dateRestrictions && selectedDateRange) {
    return adjustDateRangeWithRestrictions(selectedDateRange, dateRestrictions)
  }
  return selectedDateRange
}
