<script setup>
import { CalendarDate, getLocalTimeZone, today } from "@internationalized/date";
import { reactiveOmit, useNavigatorLanguage, useVModel } from "@vueuse/core";
import { CalendarRoot, useDateFormatter, useForwardPropsEmits } from "reka-ui";
import { toDate } from "reka-ui/date";
import { computed, watch } from "vue";
import { useI18n } from "vue-i18n";
import { cn } from "../../../utils/cn";
import { buttonVariants } from "../button";
import { CalendarCell, CalendarCellTrigger, CalendarGrid, CalendarGridBody, CalendarGridHead, CalendarGridRow, CalendarHeadCell, CalendarHeader, CalendarHeading, CalendarNextButton, CalendarPrevButton } from ".";
defineOptions({ name: "UiCalendar" });
const props = defineProps({
  defaultValue: { type: Object, required: false },
  defaultPlaceholder: { type: Object, required: false },
  placeholder: { type: Object, required: false },
  pagedNavigation: { type: Boolean, required: false },
  preventDeselect: { type: Boolean, required: false },
  weekStartsOn: { type: Number, required: false },
  weekdayFormat: { type: String, required: false },
  calendarLabel: { type: String, required: false },
  fixedWeeks: { type: Boolean, required: false },
  maxValue: { type: Object, required: false },
  minValue: { type: Object, required: false },
  locale: { type: String, required: false },
  numberOfMonths: { type: Number, required: false },
  disabled: { type: Boolean, required: false },
  readonly: { type: Boolean, required: false },
  initialFocus: { type: Boolean, required: false },
  isDateDisabled: { type: Function, required: false },
  isDateUnavailable: { type: Function, required: false },
  dir: { type: String, required: false },
  nextPage: { type: Function, required: false },
  prevPage: { type: Function, required: false },
  modelValue: { type: null, required: false, default: void 0 },
  multiple: { type: Boolean, required: false },
  disableDaysOutsideCurrentView: { type: Boolean, required: false },
  asChild: { type: Boolean, required: false },
  as: { type: null, required: false },
  class: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
  layout: { type: String, required: false, default: void 0 }
});
const emits = defineEmits(["update:modelValue", "update:placeholder"]);
const delegatedProps = reactiveOmit(props, "class", "layout", "placeholder");
const placeholder = useVModel(props, "placeholder", emits, {
  passive: true,
  defaultValue: props.defaultPlaceholder ?? today(getLocalTimeZone())
});
const navLocale = useNavigatorLanguage();
const { locale: i18nLocale } = useI18n({ useScope: "global", inheritLocale: true });
const locale = computed(() => props.locale ?? i18nLocale.value ?? navLocale.language.value ?? "en");
const formatter = useDateFormatter(locale.value);
watch(locale, (next) => {
  formatter.setLocale(next);
});
const forwarded = useForwardPropsEmits(delegatedProps, emits);
const weekStartsOn = computed(() => {
  const lang = navLocale.language.value;
  if (!navLocale.isSupported || !lang) return void 0;
  const intl = new Intl.Locale(lang);
  if ("getWeekInfo" in intl && typeof intl.getWeekInfo === "function") {
    return intl.getWeekInfo().firstDay;
  }
  return void 0;
});
const yearGridStart = computed(() => Math.floor(placeholder.value.year / 12) * 12);
function isPickerDateDisabled(date) {
  const fn = props.isDateDisabled;
  if (typeof fn !== "function") return false;
  return fn(date);
}
</script>

<template>
  <CalendarRoot
    v-slot="{ grid, weekDays, date }"
    v-bind="forwarded"
    v-model:placeholder="placeholder"
    data-slot="calendar"
    :week-starts-on="weekStartsOn"
    fixed-weeks
    :locale="locale"
    :class="cn('p-3', props.class)"
  >
    <CalendarHeader :class="layout === 'year' ? 'pt-2 pb-2' : 'pt-0'">
      <nav class="w-full flex items-center gap-1 absolute top-1/2 -translate-y-1/2 transform-gpu inset-x-0 justify-between z-10">
        <CalendarPrevButton
          :prev-page="layout === 'year' ? (d) => d.subtract({ years: 12 }) : layout === 'month' ? (d) => d.subtract({ years: 1 }) : void 0"
        >
          <slot name="calendar-prev-icon" />
        </CalendarPrevButton>
        <CalendarNextButton
          :next-page="layout === 'year' ? (d) => d.add({ years: 12 }) : layout === 'month' ? (d) => d.add({ years: 1 }) : void 0"
        >
          <slot name="calendar-next-icon" />
        </CalendarNextButton>
      </nav>

      <slot
        name="calendar-heading"
        :date="date"
      >
        <template v-if="layout === 'month'">
          <span
            class="text-sm font-medium"
            style="text-autospace: normal"
          >
            {{ formatter.custom(toDate(date), { year: "numeric" }) }}
          </span>
        </template>
        <template v-else-if="layout === 'year'" />
        <template v-else>
          <CalendarHeading />
        </template>
      </slot>
    </CalendarHeader>

    <!-- Month picker grid (month-only / month-and-year) -->
    <div
      v-if="layout === 'month'"
      class="grid grid-cols-4 gap-1 mt-4 w-full"
    >
      <button
        v-for="m in 12"
        :key="m"
        type="button"
        :disabled="isPickerDateDisabled(new CalendarDate(placeholder.year, m, 1))"
        :class="cn(
  buttonVariants({ variant: 'ghost' }),
  'h-9 w-full rounded-md font-normal',
  modelValue && !Array.isArray(modelValue) && modelValue.year === placeholder.year && modelValue.month === m ? 'bg-[color-mix(in_srgb,var(--primary)_20%,white)] text-(--primary)' : '',
  isPickerDateDisabled(new CalendarDate(placeholder.year, m, 1)) ? 'text-zinc-500 opacity-50 cursor-default' : 'cursor-pointer'
)"
        @click="emits('update:modelValue', new CalendarDate(placeholder.year, m, 1))"
      >
        {{ formatter.custom(toDate(new CalendarDate(placeholder.year, m, 1)), { month: "short" }) }}
      </button>
    </div>

    <!-- Year picker grid -->
    <div
      v-else-if="layout === 'year'"
      class="grid grid-cols-4 gap-1 mt-4 w-full"
    >
      <button
        v-for="i in 12"
        :key="i"
        type="button"
        :disabled="isPickerDateDisabled(new CalendarDate(yearGridStart + i - 1, 1, 1))"
        :class="cn(
  buttonVariants({ variant: 'ghost' }),
  'h-9 w-full rounded-md font-normal',
  modelValue && !Array.isArray(modelValue) && modelValue.year === yearGridStart + i - 1 ? 'bg-[color-mix(in_srgb,var(--primary)_20%,white)] text-(--primary)' : '',
  isPickerDateDisabled(new CalendarDate(yearGridStart + i - 1, 1, 1)) ? 'text-zinc-500 opacity-50 cursor-default' : 'cursor-pointer'
)"
        @click="emits('update:modelValue', new CalendarDate(yearGridStart + i - 1, 1, 1))"
      >
        {{ yearGridStart + i - 1 }}
      </button>
    </div>

    <!-- Default: day grid -->
    <div
      v-else
      class="flex flex-col gap-y-4 mt-4 sm:flex-row sm:gap-x-4 sm:gap-y-0"
    >
      <CalendarGrid
        v-for="month in grid"
        :key="month.value.toString()"
      >
        <CalendarGridHead>
          <CalendarGridRow>
            <CalendarHeadCell
              v-for="day in weekDays"
              :key="day"
            >
              {{ day }}
            </CalendarHeadCell>
          </CalendarGridRow>
        </CalendarGridHead>
        <CalendarGridBody>
          <CalendarGridRow
            v-for="(weekDates, index) in month.rows"
            :key="`weekDate-${index}`"
            class="mt-2 w-full"
          >
            <CalendarCell
              v-for="weekDate in weekDates"
              :key="weekDate.toString()"
              :date="weekDate"
            >
              <CalendarCellTrigger
                :day="weekDate"
                :month="month.value"
              />
            </CalendarCell>
          </CalendarGridRow>
        </CalendarGridBody>
      </CalendarGrid>
    </div>
  </CalendarRoot>
</template>
