import {
  Button as AriaButton,
  Calendar as AriaCalendar,
  CalendarGridHeader as AriaCalendarGridHeader,
  CalendarCell,
  CalendarGrid,
  CalendarGridBody,
  CalendarHeaderCell,
  Heading,
} from 'react-aria-components';

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

import { ChevronLeftIcon, ChevronRightIcon } from '@/components/icons';

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

const cellStyles = tv({
  base: 'flex h-[30px] w-[30px] cursor-default items-center justify-center rounded-full text-xs outline-none',
  variants: {
    isSelected: {
      true: 'bg-primary font-bold text-white',
      false: '',
    },
    isDisabled: {
      true: 'cursor-default text-kc-gray-be',
    },
    isUnavailable: {
      true: 'cursor-default text-kc-gray-be line-through',
    },
    isOutsideMonth: {
      true: 'text-kc-gray-be',
    },
    isSunday: {
      true: 'text-[#e48686]',
    },
    isSaturday: {
      true: 'text-[#7b8cc8]',
    },
    isToday: {
      true: 'font-bold text-primary',
    },
    isHovered: {
      true: 'bg-primary-tertiary01',
    },
    isFocusVisible: {
      true: 'ring-2 ring-offset-2 ring-primary',
    },
  },
  compoundVariants: [
    {
      isSelected: true,
      isSunday: true,
      className: 'text-white',
    },
    {
      isSelected: true,
      isSaturday: true,
      className: 'text-white',
    },
    {
      isSelected: true,
      isToday: true,
      className: 'text-white',
    },
    {
      isSelected: true,
      isHovered: true,
      className: 'bg-primary',
    },
  ],
});

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

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

  return (
    <AriaCalendar
      aria-label="날짜 선택"
      value={value !== undefined ? dateToCalendarDate(value ?? null) : undefined}
      defaultValue={defaultValue !== undefined ? dateToCalendarDate(defaultValue ?? null) : undefined}
      onChange={(val) => onChange?.(calendarDateToDate(val))}
      maxValue={maxValue !== undefined ? dateToCalendarDate(maxValue) : undefined}
      minValue={minValue !== undefined ? dateToCalendarDate(minValue) : undefined}
      isDisabled={isDisabled}
      firstDayOfWeek="sun"
      className={className}
    >
      <CalendarHeader />
      <CalendarGrid className="border-spacing-0">
        <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,
                  isDisabled: isCellDisabled,
                  isUnavailable,
                  isOutsideMonth,
                  isHovered,
                  isFocusVisible,
                }) =>
                  cellStyles({
                    isSelected,
                    isDisabled: isCellDisabled,
                    isUnavailable,
                    isOutsideMonth,
                    isSunday: !isSelected && !isDisabled && !isOutsideMonth ? isSunday : false,
                    isSaturday: !isSelected && !isDisabled && !isOutsideMonth ? isSaturday : false,
                    isToday: !isSelected ? isToday : false,
                    isHovered: !isSelected ? isHovered : false,
                    isFocusVisible,
                  })
                }
              />
            );
          }}
        </CalendarGridBody>
      </CalendarGrid>
    </AriaCalendar>
  );
}

const navButton = tv({
  base: 'flex h-7 w-7 items-center justify-center rounded-sm border-none bg-transparent outline-none',
  variants: {
    isDisabled: {
      true: 'cursor-default text-kc-gray-be',
      false: 'cursor-pointer text-kc-black-34 hover:bg-kc-gray-eb',
    },
    isFocusVisible: {
      true: 'ring-2 ring-offset-2 ring-primary',
    },
  },
  defaultVariants: {
    isDisabled: false,
  },
});

export function CalendarHeader() {
  return (
    <header className="flex items-center gap-1 pb-3">
      <AriaButton slot="previous" className={(renderProps) => navButton(renderProps)}>
        <ChevronLeftIcon className="h-4 w-4" />
      </AriaButton>
      <Heading className="mx-2 flex-1 text-center text-sm font-semibold text-kc-black-34" />
      <AriaButton slot="next" className={(renderProps) => navButton(renderProps)}>
        <ChevronRightIcon className="h-4 w-4" />
      </AriaButton>
    </header>
  );
}

export function CalendarGridHeader() {
  return (
    <AriaCalendarGridHeader>
      {(day) => (
        <CalendarHeaderCell className="h-[30px] w-[30px] text-xs font-semibold text-kc-gray-99 first:text-[#e48686] last:text-[#7b8cc8]">
          {day}
        </CalendarHeaderCell>
      )}
    </AriaCalendarGridHeader>
  );
}
