import {
  RangeCalendar as AriaRangeCalendar,
  CalendarCell,
  CalendarGrid,
  CalendarGridBody,
  type DateValue,
} from 'react-aria-components';

import { getLocalTimeZone, today } from '@internationalized/date';
import { tv } from 'tailwind-variants';

import { CalendarGridHeader, CalendarHeader } from './Calendar';
import { calendarDateToDate, dateToCalendarDate } from './utils';

const rangeCell = tv({
  base: 'flex h-full w-full items-center justify-center rounded-full text-xs',
  variants: {
    selectionState: {
      none: '',
      middle: '',
      cap: 'bg-primary font-bold text-white',
    },
    isDisabled: {
      true: 'text-kc-gray-be',
    },
    isOutsideMonth: {
      true: 'text-kc-gray-be',
    },
    isSunday: {
      true: 'text-[#e48686]',
    },
    isSaturday: {
      true: 'text-[#7b8cc8]',
    },
    isToday: {
      true: 'font-bold text-primary',
    },
    isHovered: {
      true: '',
    },
    isFocusVisible: {
      true: 'ring-2 ring-offset-2 ring-primary',
    },
  },
  compoundVariants: [
    {
      selectionState: 'cap',
      isSunday: true,
      className: 'text-white',
    },
    {
      selectionState: 'cap',
      isSaturday: true,
      className: 'text-white',
    },
    {
      selectionState: 'cap',
      isToday: true,
      className: 'text-white',
    },
    {
      selectionState: 'none',
      isHovered: true,
      className: 'bg-primary-tertiary01 rounded-full',
    },
    {
      selectionState: 'middle',
      isHovered: true,
      className: 'bg-primary-tertiary01',
    },
  ],
});

export interface RangeCalendarProps {
  value?: { start: Date; end: Date } | null;
  defaultValue?: { start: Date; end: Date } | null;
  onChange?: (value: { start: Date; end: Date } | null) => void;
  maxValue?: Date | null;
  minValue?: Date | null;
  isDisabled?: boolean;
  className?: string;
}

export function RangeCalendar({
  value,
  defaultValue,
  onChange,
  maxValue,
  minValue,
  isDisabled,
  className,
}: RangeCalendarProps) {
  const todayDate = today(getLocalTimeZone());

  const ariaValue =
    value !== undefined
      ? value
        ? { start: dateToCalendarDate(value.start)!, end: dateToCalendarDate(value.end)! }
        : null
      : undefined;

  const ariaDefaultValue =
    defaultValue !== undefined
      ? defaultValue
        ? { start: dateToCalendarDate(defaultValue.start)!, end: dateToCalendarDate(defaultValue.end)! }
        : null
      : undefined;

  return (
    <AriaRangeCalendar<DateValue>
      aria-label="날짜 범위 선택"
      value={ariaValue}
      defaultValue={ariaDefaultValue}
      onChange={(range) => {
        if (!range) {
          onChange?.(null);
        } else {
          onChange?.({
            start: calendarDateToDate(range.start)!,
            end: calendarDateToDate(range.end)!,
          });
        }
      }}
      maxValue={maxValue !== undefined ? dateToCalendarDate(maxValue) : undefined}
      minValue={minValue !== undefined ? dateToCalendarDate(minValue) : undefined}
      isDisabled={isDisabled}
      firstDayOfWeek="sun"
      className={className}
    >
      <CalendarHeader />
      <CalendarGrid className="border-spacing-0 [&_td]:px-0 [&_td]:py-px">
        <CalendarGridHeader />
        <CalendarGridBody>
          {(date) => {
            const dayOfWeek = date.toDate('UTC').getDay();
            const isSunday = dayOfWeek === 0;
            const isSaturday = dayOfWeek === 6;
            const isToday = date.compare(todayDate) === 0;

            return (
              <CalendarCell
                date={date}
                className={({ isSelected, isSelectionStart, isSelectionEnd }) => {
                  const classes = ['group h-[30px] w-[30px] cursor-default text-sm outline-none'];
                  if (isSelected) {
                    classes.push('bg-primary/10');
                    if (isSelectionStart) classes.push('rounded-s-full');
                    if (isSelectionEnd) classes.push('rounded-e-full');
                  }
                  return classes.join(' ');
                }}
              >
                {({
                  formattedDate,
                  isSelected,
                  isSelectionStart,
                  isSelectionEnd,
                  isDisabled: isCellDisabled,
                  isOutsideMonth,
                  isHovered,
                  isFocusVisible,
                }) => {
                  const selectionState =
                    isSelected && (isSelectionStart || isSelectionEnd)
                      ? ('cap' as const)
                      : isSelected
                        ? ('middle' as const)
                        : ('none' as const);
                  const showDayColor = selectionState !== 'cap' && !isCellDisabled && !isOutsideMonth;

                  return (
                    <span
                      className={rangeCell({
                        selectionState,
                        isDisabled: isCellDisabled,
                        isOutsideMonth,
                        isSunday: showDayColor ? isSunday : false,
                        isSaturday: showDayColor ? isSaturday : false,
                        isToday: selectionState !== 'cap' ? isToday : false,
                        isHovered: !isSelected ? isHovered : false,
                        isFocusVisible,
                      })}
                    >
                      {formattedDate}
                    </span>
                  );
                }}
              </CalendarCell>
            );
          }}
        </CalendarGridBody>
      </CalendarGrid>
    </AriaRangeCalendar>
  );
}
