<script setup lang="ts">
type CalendarEvent = {
  id: string;
  title: string;
  start: string;
  end: string;
  contact: string;
  note: string;
};

type YearMonthItem = {
  monthIndex: number;
  label: string;
  count: number;
  first?: CalendarEvent;
};

type MonthCell = {
  key: string;
  day: number;
  inMonth: boolean;
  events: CalendarEvent[];
};

type MonthRow = {
  key: string;
  startKey: string;
  cells: MonthCell[];
};

type WeekDay = {
  key: string;
  label: string;
  day: number;
  events: CalendarEvent[];
};

defineProps<{
  contextPickerEnabled: boolean;
  hasContextScope: (scope: "calendar") => boolean;
  toggleContextScope: (scope: "calendar") => void;
  contextScopeLabel: (scope: "calendar") => string;
  setToday: () => void;
  calendarPeriodLabel: string;
  calendarZoomLevelIndex: number;
  onCalendarZoomSliderInput: (event: Event) => void;
  focusedCalendarEvent: CalendarEvent | null;
  formatDay: (iso: string) => string;
  formatTime: (iso: string) => string;
  setCalendarContentWrapRef: (element: HTMLDivElement | null) => void;
  shiftCalendar: (step: number) => void;
  setCalendarContentScrollRef: (element: HTMLDivElement | null) => void;
  onCalendarHierarchyWheel: (event: WheelEvent) => void;
  setCalendarSceneRef: (element: HTMLDivElement | null) => void;
  calendarViewportHeight: number;
  normalizedCalendarView: string;
  calendarSceneTransformStyle: Record<string, string>;
  onCalendarSceneMouseLeave: () => void;
  calendarView: string;
  yearMonths: YearMonthItem[];
  calendarCursorMonth: number;
  calendarHoveredMonthIndex: number | null;
  setCalendarHoveredMonthIndex: (value: number | null) => void;
  calendarZoomPrimeToken: string;
  calendarPrimeMonthToken: (monthIndex: number) => string;
  calendarPrimeStyle: (token: string) => Record<string, string>;
  zoomToMonth: (monthIndex: number) => void;
  openThreadFromCalendarItem: (event: CalendarEvent) => void;
  monthRows: MonthRow[];
  calendarHoveredWeekStartKey: string;
  setCalendarHoveredWeekStartKey: (value: string) => void;
  calendarPrimeWeekToken: (startKey: string) => string;
  selectedDateKey: string;
  monthCellHasFocusedEvent: (events: CalendarEvent[]) => boolean;
  calendarHoveredDayKey: string;
  setCalendarHoveredDayKey: (value: string) => void;
  pickDate: (key: string) => void;
  monthCellEvents: (events: CalendarEvent[]) => CalendarEvent[];
  isReviewHighlightedEvent: (eventId: string) => boolean;
  weekDays: WeekDay[];
  calendarPrimeDayToken: (dayKey: string) => string;
  selectedDayEvents: CalendarEvent[];
}>();
</script>

<template>
  <section
    class="relative flex h-full min-h-0 flex-col gap-3"
    :class="[
      contextPickerEnabled ? 'context-scope-block context-scope-block-active' : '',
      hasContextScope('calendar') ? 'context-scope-block-selected' : '',
    ]"
    @click="toggleContextScope('calendar')"
  >
    <span
      v-if="contextPickerEnabled"
      class="context-scope-label"
    >{{ contextScopeLabel('calendar') }}</span>
    <div class="grid grid-cols-[auto_1fr_auto] items-center gap-2">
      <div class="flex items-center gap-1">
        <button class="btn btn-xs" @click="setToday">Today</button>
      </div>

      <div class="text-center text-sm font-medium">
        {{ calendarPeriodLabel }}
      </div>

      <div class="justify-self-end calendar-zoom-inline" @click.stop>
        <input
          class="calendar-zoom-slider"
          type="range"
          min="0"
          max="3"
          step="1"
          :value="calendarZoomLevelIndex"
          aria-label="Calendar zoom level"
          @input="onCalendarZoomSliderInput"
        >
        <div class="calendar-zoom-marks" aria-hidden="true">
          <span
            v-for="index in 4"
            :key="`calendar-zoom-mark-${index}`"
            class="calendar-zoom-mark"
            :class="calendarZoomLevelIndex === index - 1 ? 'calendar-zoom-mark-active' : ''"
          />
        </div>
      </div>
    </div>

    <article
      v-if="focusedCalendarEvent"
      class="rounded-xl border border-success/50 bg-success/10 px-3 py-2"
    >
      <p class="text-xs font-semibold uppercase tracking-wide text-success/80">Review focus event</p>
      <p class="text-sm font-medium text-base-content">{{ focusedCalendarEvent.title }}</p>
      <p class="text-xs text-base-content/70">
        {{ formatDay(focusedCalendarEvent.start) }} · {{ formatTime(focusedCalendarEvent.start) }} - {{ formatTime(focusedCalendarEvent.end) }}
      </p>
      <p class="mt-1 text-xs text-base-content/80">{{ focusedCalendarEvent.note || "No note" }}</p>
    </article>

    <div :ref="setCalendarContentWrapRef" class="calendar-content-wrap min-h-0 flex-1">
      <button
        class="calendar-side-nav calendar-side-nav-left"
        type="button"
        title="Previous period"
        @click="shiftCalendar(-1)"
      >
        <span>←</span>
      </button>
      <button
        class="calendar-side-nav calendar-side-nav-right"
        type="button"
        title="Next period"
        @click="shiftCalendar(1)"
      >
        <span>→</span>
      </button>
      <div
        :ref="setCalendarContentScrollRef"
        class="calendar-content-scroll min-h-0 h-full overflow-y-auto pr-1"
        @wheel.prevent="onCalendarHierarchyWheel"
      >
        <div
          :ref="setCalendarSceneRef"
          :class="[
            'calendar-scene',
            normalizedCalendarView === 'day' ? 'cursor-zoom-out' : 'cursor-zoom-in',
          ]"
          :style="calendarSceneTransformStyle"
          @mouseleave="onCalendarSceneMouseLeave"
        >
          <div class="grid grid-cols-1 gap-2 sm:grid-cols-2 xl:grid-cols-3">
            <article
              v-for="item in yearMonths"
              :key="`year-month-${item.monthIndex}`"
              v-show="calendarView === 'year' || item.monthIndex === calendarCursorMonth"
              class="group relative rounded-xl border border-base-300 p-3 text-left transition calendar-hover-targetable"
              :class="[
                calendarView === 'year'
                  ? 'hover:border-primary/50 hover:bg-primary/5 cursor-zoom-in'
                  : 'cursor-default min-h-[26rem] bg-base-100 sm:col-span-2 xl:col-span-3',
                calendarHoveredMonthIndex === item.monthIndex ? 'calendar-hover-target' : '',
                calendarZoomPrimeToken === calendarPrimeMonthToken(item.monthIndex) ? 'calendar-zoom-prime-active' : '',
              ]"
              :style="{
                ...calendarPrimeStyle(calendarPrimeMonthToken(item.monthIndex)),
                ...(calendarView !== 'year' && item.monthIndex === calendarCursorMonth && calendarViewportHeight > 0
                  ? { minHeight: `${Math.max(420, calendarViewportHeight)}px` }
                  : {}),
              }"
              :data-calendar-month-index="item.monthIndex"
              @mouseenter="setCalendarHoveredMonthIndex(item.monthIndex)"
              @click="calendarView === 'year' ? zoomToMonth(item.monthIndex) : undefined"
            >
              <p class="font-medium">{{ item.label }}</p>
              <p class="text-xs text-base-content/60">{{ item.count }} events</p>
              <button
                v-if="calendarView === 'year' && item.first"
                class="mt-1 block w-full text-left text-xs text-base-content/70 hover:underline"
                @click.stop="openThreadFromCalendarItem(item.first)"
              >
                {{ formatDay(item.first.start) }} · {{ item.first.title }}
              </button>

              <div v-if="item.monthIndex === calendarCursorMonth" class="mt-3 calendar-depth-stack">
                <div
                  class="space-y-1 calendar-depth-layer"
                  :class="calendarView === 'month' || calendarView === 'agenda' ? 'calendar-depth-layer-active' : 'calendar-depth-layer-hidden'"
                >
                  <div class="grid grid-cols-7 gap-1 text-center text-xs font-semibold text-base-content/60">
                    <span>Sun</span>
                    <span>Mon</span>
                    <span>Tue</span>
                    <span>Wed</span>
                    <span>Thu</span>
                    <span>Fri</span>
                    <span>Sat</span>
                  </div>

                  <div class="space-y-1">
                    <div
                      v-for="row in monthRows"
                      :key="row.key"
                      class="group relative calendar-hover-targetable"
                      :class="[
                        calendarHoveredWeekStartKey === row.startKey ? 'calendar-hover-target' : '',
                        calendarZoomPrimeToken === calendarPrimeWeekToken(row.startKey) ? 'calendar-zoom-prime-active' : '',
                      ]"
                      :style="calendarPrimeStyle(calendarPrimeWeekToken(row.startKey))"
                      :data-calendar-week-start-key="row.startKey"
                      @mouseenter="setCalendarHoveredWeekStartKey(row.startKey)"
                    >
                      <div class="grid grid-cols-7 gap-1">
                        <button
                          v-for="cell in row.cells"
                          :key="cell.key"
                          class="group relative min-h-24 rounded-lg border p-1 text-left"
                          :class="[
                            cell.inMonth ? 'border-base-300 bg-base-100' : 'border-base-200 bg-base-200/40 text-base-content/40',
                            selectedDateKey === cell.key ? 'border-primary bg-primary/5' : '',
                            monthCellHasFocusedEvent(cell.events) ? 'border-success/60 bg-success/10' : '',
                          ]"
                          :data-calendar-day-key="cell.key"
                          @mouseenter="setCalendarHoveredDayKey(cell.key)"
                          @click="pickDate(cell.key)"
                        >
                          <p class="mb-1 text-xs font-semibold">{{ cell.day }}</p>
                          <button
                            v-for="event in monthCellEvents(cell.events)"
                            :key="event.id"
                            class="block w-full truncate rounded px-1 text-left text-[10px] text-base-content/70 transition hover:underline"
                            :class="isReviewHighlightedEvent(event.id) ? 'bg-success/20 text-success-content ring-1 ring-success/40' : ''"
                            @click.stop="openThreadFromCalendarItem(event)"
                          >
                            {{ formatTime(event.start) }} {{ event.title }}
                          </button>
                        </button>
                      </div>
                    </div>
                  </div>
                </div>

                <div
                  class="calendar-week-scroll overflow-x-auto pb-1 calendar-depth-layer"
                  :class="calendarView === 'week' ? 'calendar-depth-layer-active' : 'calendar-depth-layer-hidden'"
                >
                  <div class="calendar-week-grid">
                    <article
                      v-for="day in weekDays"
                      :key="day.key"
                      class="group relative flex min-h-[18rem] flex-col rounded-xl border border-base-300 bg-base-100 p-2.5 cursor-zoom-in calendar-hover-targetable"
                      :class="[
                        selectedDateKey === day.key ? 'border-primary bg-primary/5' : '',
                        calendarHoveredDayKey === day.key ? 'calendar-hover-target' : '',
                        calendarZoomPrimeToken === calendarPrimeDayToken(day.key) ? 'calendar-zoom-prime-active' : '',
                      ]"
                      :style="calendarPrimeStyle(calendarPrimeDayToken(day.key))"
                      :data-calendar-day-key="day.key"
                      @mouseenter="setCalendarHoveredDayKey(day.key)"
                      @click="pickDate(day.key)"
                    >
                      <div class="mb-2 flex items-start justify-between gap-2">
                        <p class="text-sm font-semibold leading-tight">{{ day.label }} {{ day.day }}</p>
                      </div>
                      <div class="space-y-1.5">
                        <button
                          v-for="event in day.events"
                          :key="event.id"
                          class="block w-full rounded-md px-2 py-1.5 text-left text-xs"
                          :class="isReviewHighlightedEvent(event.id) ? 'bg-success/20 ring-1 ring-success/45' : 'bg-base-200 hover:bg-base-300/80'"
                          @click.stop="openThreadFromCalendarItem(event)"
                        >
                          {{ formatTime(event.start) }} - {{ event.title }} ({{ event.contact }})
                        </button>
                        <p v-if="day.events.length === 0" class="pt-1 text-xs text-base-content/50">No events</p>
                      </div>
                    </article>
                  </div>
                </div>

                <div
                  class="space-y-2 calendar-depth-layer"
                  :class="calendarView === 'day' ? 'calendar-depth-layer-active' : 'calendar-depth-layer-hidden'"
                >
                  <button
                    v-for="event in selectedDayEvents"
                    :key="event.id"
                    class="block w-full rounded-xl border border-base-300 p-3 text-left transition hover:bg-base-200/60"
                    :class="isReviewHighlightedEvent(event.id) ? 'border-success/60 bg-success/10' : ''"
                    @click="openThreadFromCalendarItem(event)"
                  >
                    <p class="font-medium">{{ event.title }}</p>
                    <p class="text-xs text-base-content/60">{{ event.contact }}</p>
                    <p class="text-xs text-base-content/60">{{ formatTime(event.start) }} - {{ formatTime(event.end) }}</p>
                    <p class="mt-1 text-sm text-base-content/80">{{ event.note }}</p>
                  </button>
                  <p v-if="selectedDayEvents.length === 0" class="text-sm text-base-content/60">No events on this day.</p>
                </div>
              </div>
            </article>
          </div>
        </div>
      </div>
    </div>
  </section>
</template>

<style scoped>
.calendar-content-wrap {
  position: relative;
  padding-left: 40px;
  padding-right: 40px;
}

.calendar-content-scroll {
  height: 100%;
  overscroll-behavior: contain;
}

.calendar-scene {
  min-height: 100%;
  min-width: 100%;
  transform-origin: center center;
}

.calendar-scene.cursor-zoom-in,
.calendar-scene.cursor-zoom-in * {
  cursor: zoom-in;
}

.calendar-scene.cursor-zoom-out,
.calendar-scene.cursor-zoom-out * {
  cursor: zoom-out;
}

.calendar-week-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(165px, 1fr));
  gap: 8px;
  min-width: 1180px;
}

.calendar-depth-stack {
  position: relative;
  min-height: 100%;
}

.calendar-depth-layer {
  transition: opacity 260ms ease, transform 260ms ease;
}

.calendar-depth-layer-active {
  opacity: 1;
  transform: translateY(0);
  position: relative;
  z-index: 1;
  pointer-events: auto;
}

.calendar-depth-layer-hidden {
  opacity: 0;
  transform: translateY(10px);
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.calendar-side-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 4;
  width: 28px;
  height: 28px;
  border: 1px solid color-mix(in oklab, var(--color-base-content) 16%, transparent);
  border-radius: 999px;
  background: color-mix(in oklab, var(--color-base-100) 88%, transparent);
  color: color-mix(in oklab, var(--color-base-content) 86%, transparent);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background-color 120ms ease, border-color 120ms ease, transform 120ms ease;
}

.calendar-side-nav:hover {
  border-color: color-mix(in oklab, var(--color-primary) 50%, transparent);
  background: color-mix(in oklab, var(--color-primary) 14%, var(--color-base-100));
  transform: translateY(-50%) scale(1.03);
}

.calendar-side-nav-left {
  left: 4px;
}

.calendar-side-nav-right {
  right: 4px;
}

.calendar-hover-targetable {
  transform-origin: center center;
  transition: transform 320ms ease, box-shadow 320ms ease, outline-color 320ms ease;
}

.calendar-hover-target {
  outline: 2px solid color-mix(in oklab, var(--color-primary) 66%, transparent);
  outline-offset: 1px;
  box-shadow: 0 0 0 1px color-mix(in oklab, var(--color-primary) 32%, transparent) inset;
}

.calendar-zoom-prime-active {
  z-index: 2;
}

.calendar-zoom-inline {
  position: relative;
  display: flex;
  align-items: center;
  width: 128px;
  height: 22px;
  padding: 0 10px;
}

.calendar-zoom-slider {
  width: 100%;
  height: 18px;
  margin: 0;
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
}

.calendar-zoom-slider:focus-visible {
  outline: none;
}

.calendar-zoom-slider::-webkit-slider-runnable-track {
  height: 2px;
  border-radius: 999px;
  background: color-mix(in oklab, var(--color-base-content) 22%, transparent);
}

.calendar-zoom-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 10px;
  height: 10px;
  margin-top: -4px;
  border-radius: 999px;
  background: color-mix(in oklab, var(--color-base-content) 88%, transparent);
  border: 0;
}

.calendar-zoom-slider::-moz-range-track {
  height: 2px;
  border-radius: 999px;
  background: color-mix(in oklab, var(--color-base-content) 22%, transparent);
}

.calendar-zoom-slider::-moz-range-progress {
  height: 2px;
  border-radius: 999px;
  background: transparent;
}

.calendar-zoom-slider::-moz-range-thumb {
  width: 10px;
  height: 10px;
  border: 0;
  border-radius: 999px;
  background: color-mix(in oklab, var(--color-base-content) 88%, transparent);
}

.calendar-zoom-marks {
  position: absolute;
  inset: 0 10px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  pointer-events: none;
}

.calendar-zoom-mark {
  width: 4px;
  height: 4px;
  border-radius: 999px;
  background: color-mix(in oklab, var(--color-base-content) 35%, transparent);
}

.calendar-zoom-mark-active {
  background: color-mix(in oklab, var(--color-base-content) 85%, transparent);
}

@media (max-width: 960px) {
  .calendar-content-wrap {
    padding-left: 32px;
    padding-right: 32px;
  }

  .calendar-week-grid {
    grid-template-columns: repeat(7, minmax(150px, 1fr));
    min-width: 1060px;
  }

  .calendar-side-nav {
    width: 24px;
    height: 24px;
  }

  .calendar-zoom-inline {
    width: 108px;
  }
}
</style>
