import classNames from 'classnames'
import { formatISODate, newDateYMD, formatReadableDate } from 'shared-utils/date-utils'
import type { TDateRangeMap } from 'shared-types/calendar'
import type { TDayViewData } from './types'

export interface IDayViewContext {
  year: number
  month: number
  activeSelected: string[]
  focusedDate: string | null
  // Side-effect ref: tracks which day gets tabindex="0" (first non-disabled day)
  tabIndexSetRef: React.MutableRefObject<number>
  isDayDisabled: (date: Date, isSelected: boolean) => boolean
}

export interface IDayCellClassContext {
  range: boolean
  activeSelected: string[]
  rangeHovered: Date | null
  inRange: TDateRangeMap
  isExcluded: (date: Date) => boolean
}

export function getDayViewData(dayCounter: number, today: Date, ctx: IDayViewContext): TDayViewData {
  const currentDate = newDateYMD(ctx.year, ctx.month, dayCounter)
  const currentDateISO = formatISODate(currentDate)
  const isToday = currentDateISO === formatISODate(today)
  const isSelected = ctx.activeSelected.includes(currentDateISO)
  const isDisabledVal = ctx.isDayDisabled(currentDate, isSelected)

  let tabindex: string
  if (ctx.focusedDate) {
    tabindex = ctx.focusedDate === currentDateISO && !isDisabledVal ? '0' : '-1'
  } else if (!isDisabledVal && ctx.tabIndexSetRef.current === 0) {
    ctx.tabIndexSetRef.current = dayCounter
    tabindex = '0'
  } else {
    tabindex = ctx.tabIndexSetRef.current === dayCounter ? '0' : '-1'
  }

  return {
    currentDate,
    currentDateISO,
    isToday,
    isSelected,
    isDisabled: isDisabledVal,
    ariaLabel: formatReadableDate(currentDate),
    tabindex,
  }
}

export function getDayCellClasses(data: TDayViewData, ctx: IDayCellClassContext): string {
  const { currentDateISO, isToday, isSelected } = data
  const isRangeStart =
    ctx.range &&
    (ctx.activeSelected.length === 2 || ctx.rangeHovered !== null) &&
    currentDateISO === ctx.activeSelected[0]
  const isRangeEnd = ctx.range && ctx.activeSelected.length === 2 && currentDateISO === ctx.activeSelected[1]

  return classNames({
    'pkt-cal-today': isToday,
    'pkt-cal-selected': isSelected,
    'pkt-cal-in-range': ctx.inRange[currentDateISO],
    'pkt-cal-excluded': ctx.isExcluded(data.currentDate),
    'pkt-cal-in-range-first': isRangeStart,
    'pkt-cal-in-range-last': isRangeEnd,
    'pkt-cal-range-hover': ctx.rangeHovered !== null && currentDateISO === formatISODate(ctx.rangeHovered),
  })
}

export function getDayButtonClasses(data: TDayViewData, ctx: IDayCellClassContext): string {
  const { currentDateISO, isToday, isSelected, isDisabled: isDisabledVal } = data
  const isRangeStart =
    ctx.range &&
    (ctx.activeSelected.length === 2 || ctx.rangeHovered !== null) &&
    currentDateISO === ctx.activeSelected[0]
  const isRangeEnd = ctx.range && ctx.activeSelected.length === 2 && currentDateISO === ctx.activeSelected[1]

  return classNames({
    'pkt-calendar__date': true,
    'pkt-calendar__date--today': isToday,
    'pkt-calendar__date--selected': isSelected,
    'pkt-calendar__date--disabled': isDisabledVal,
    'pkt-calendar__date--in-range': ctx.inRange[currentDateISO],
    'pkt-calendar__date--in-range-hover':
      ctx.rangeHovered !== null && currentDateISO === formatISODate(ctx.rangeHovered),
    'pkt-calendar__date--range-start': isRangeStart,
    'pkt-calendar__date--range-end': isRangeEnd,
  })
}
