<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { layoutMultiDayLanes, type MultiDaySegment } from '@/utils/multiDayLanes';
import { shiftLocalDays, startOfLocalDay } from '@/utils/date';
import { DAYS_VIEW_SPANS, spanToDays, type DaysViewSpan } from '@/types/spans';
import type { EntityObject } from '@ChronoManager/models/entity';
import type { CollectionObject } from '@ChronoManager/models/collection';
import { useChronoInstancesStore } from '@/stores/chronoInstancesStore';
import type { CalendarInstance } from '@/types/instance';
import ViewControls from './ViewControls.vue';
import { formatEpochTime, formatHour, formatWeekDay } from '@/utils/format';

const ALL_DAY_EVENT_HEIGHT = 24;

const props = defineProps<{
  currentDate: Date;
  calendars: CollectionObject[];
  initialSpan?: DaysViewSpan;
}>();

const instancesStore = useChronoInstancesStore();

const selectedSpan = ref<DaysViewSpan>(props.initialSpan ?? '7d');
const daysCount = computed(() => spanToDays(selectedSpan.value));

const emit = defineEmits<{
  'event-click': [event: EntityObject];
  'event-hover': [data: { event: MouseEvent; entity: EntityObject }];
  'event-hover-end': [];
  'date-click': [date: Date];
  'update:span': [span: DaysViewSpan];
  'update:current-date': [date: Date];
}>();

watch(() => props.initialSpan, (newSpan) => {
  if (newSpan && newSpan !== selectedSpan.value) {
    selectedSpan.value = newSpan;
  }
});

function setSpan(span: DaysViewSpan) {
  selectedSpan.value = span;
  emit('update:span', span);
}

const visibleDates = computed(() => {
  const dates: Date[] = [];
  const start = new Date(props.currentDate);
  
  for (let i = 0; i < daysCount.value; i++) {
    dates.push(new Date(start));
    start.setDate(start.getDate() + 1);
  }
  
  return dates;
});

// Compute all-day/multi-day event segments
const allDaySegments = computed(() => {
  if (visibleDates.value.length === 0) {
    return { segments: [], laneCount: 0 };
  }
  
  const rangeStart = startOfLocalDay(visibleDates.value[0]);
  const rangeEnd = startOfLocalDay(visibleDates.value[visibleDates.value.length - 1]);
  
  const getColumnIndex = (date: Date): number => {
    const targetDay = startOfLocalDay(date);
    return visibleDates.value.findIndex(d => startOfLocalDay(d).getTime() === targetDay.getTime());
  };
  
  const instances = instancesStore.instancesForRange({
    start: rangeStart.getTime(),
    end: shiftLocalDays(rangeEnd, 1).getTime(),
  });

  return layoutMultiDayLanes(instances, rangeStart, rangeEnd, daysCount.value, getColumnIndex);
});

function isToday(date: Date): boolean {
  const today = new Date();
  return date.toDateString() === today.toDateString();
}

function getTimedEvents(date: Date): CalendarInstance[] {
  return instancesStore.instancesForDay(date).filter(instance => !instance.timeless);
}

function getEventColor(instance: CalendarInstance): string {
  if (instance.color) return instance.color;
  const calendar = props.calendars.find(cal => cal.identifier === instance.entity.collection);
  return calendar?.properties?.color || '#1976D2';
}

function getAllDayEventStyle(segment: MultiDaySegment) {
  return {
    backgroundColor: getEventColor(segment.instance),
    left: `calc(${segment.startCol} / ${daysCount.value} * 100% + 4px)`,
    width: `calc(${segment.span} / ${daysCount.value} * 100% - 8px)`,
    top: `${segment.lane * ALL_DAY_EVENT_HEIGHT}px`,
  };
}

function getEventStyle(instance: CalendarInstance) {
  const startTime = new Date(instance.start);
  const start = startTime.getHours() * 60 + startTime.getMinutes();
  const duration = instance.duration / (1000 * 60);
  
  return {
    top: `${(start / 1440) * 100}%`,
    height: `${(duration / 1440) * 100}%`,
    backgroundColor: getEventColor(instance),
  };
}

function handleDayClick(event: MouseEvent, day: Date) {
  const target = event.currentTarget as HTMLElement;
  const rect = target.getBoundingClientRect();
  const clickY = event.clientY - rect.top;
  
  // Calculate the hour based on click position (60px per hour)
  const totalMinutes = Math.floor((clickY / 60) * 60);
  const hours = Math.floor(totalMinutes / 60);
  const minutes = Math.round((totalMinutes % 60) / 15) * 15; // Round to nearest 15 min
  
  // Create a new date with the clicked time
  const clickedDate = new Date(day);
  clickedDate.setHours(hours, minutes, 0, 0);
  
  emit('date-click', clickedDate);
}
</script>

<template>
  <div class="days-view">
    <ViewControls
      mode="days"
      :current-date="currentDate"
      :spans="DAYS_VIEW_SPANS"
      :selected-span="selectedSpan"
      @update:current-date="emit('update:current-date', $event)"
      @update:span="setSpan"
    />
    <div class="days-grid">
      <!-- Fixed Headers Row -->
      <div class="day-headers">
        <div class="time-header-spacer"></div>
        <div class="day-headers-row">
          <div v-for="day in visibleDates" :key="day.toISOString() + '-header'" class="day-header-cell" :class="{ 'single-day': daysCount === 1 }">
            <span class="day-name">{{ formatWeekDay(day) }}</span>
            <span class="day-number" :class="{ 'today': isToday(day) }">{{ day.getDate() }}</span>
          </div>
        </div>
      </div>
      
      <!-- All-Day Events Section -->
      <div v-if="allDaySegments.laneCount > 0" class="all-day-section">
        <div class="all-day-label">
          <span>All day</span>
        </div>
        <div class="all-day-events-container" :style="{ height: `${allDaySegments.laneCount * 24 + 4}px` }">
          <div class="all-day-columns">
            <div v-for="day in visibleDates" :key="day.toISOString() + '-allday'" class="all-day-column" :class="{ 'single-day': daysCount === 1 }"></div>
          </div>
          <div class="all-day-events-overlay">
            <div
              v-for="segment in allDaySegments.segments"
              :key="segment.instance.key"
              class="all-day-event"
              :class="{
                'is-start': segment.isStart,
                'is-end': segment.isEnd,
              }"
              :style="getAllDayEventStyle(segment)"
              @click="emit('event-click', segment.instance.entity)"
              @mouseenter="emit('event-hover', { event: $event, entity: segment.instance.entity })"
              @mouseleave="emit('event-hover-end')"
            >
              <span v-if="segment.isStart" class="event-label">{{ segment.instance.label || 'Untitled' }}</span>
            </div>
          </div>
        </div>
      </div>
      
      <!-- Scrollable Content -->
      <div class="days-content">
        <div class="time-column">
          <div v-for="hour in 24" :key="hour" class="time-slot">
            {{ formatHour(hour - 1) }}
          </div>
        </div>
        <div class="days-columns">
          <div v-for="day in visibleDates" :key="day.toISOString()" class="day-column" :class="{ 'single-day': daysCount === 1 }">
            <div class="day-events" @click="handleDayClick($event, day)">
              <div
                v-for="instance in getTimedEvents(day)"
                :key="instance.key"
                class="day-event"
                :style="getEventStyle(instance)"
                @click.stop="emit('event-click', instance.entity)"
                @mouseenter="emit('event-hover', { event: $event, entity: instance.entity })"
                @mouseleave="emit('event-hover-end')"
              >
                <template v-if="daysCount <= 3">
                  <div class="event-time">
                    {{ formatEpochTime(instance.start) }} - {{ formatEpochTime(instance.end) }}
                  </div>
                  <div class="event-title">{{ instance.label || 'Untitled' }}</div>
                </template>
                <template v-else>
                  <div class="event-title-compact">{{ instance.label || 'Untitled' }}</div>
                </template>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.days-view {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 600px;
}

.days-grid {
  display: flex;
  flex-direction: column;
  flex: 1;
  overflow: hidden;
  border: 1px solid rgb(var(--v-border-color));
  border-top: none;
}

/* Fixed Headers Row */
.day-headers {
  display: flex;
  flex-shrink: 0;
  border-bottom: 2px solid rgb(var(--v-border-color));
  background-color: rgb(var(--v-theme-surface-variant));
}

.time-header-spacer {
  width: 60px;
  min-width: 60px;
  flex-shrink: 0;
  border-right: 1px solid rgb(var(--v-border-color));
}

.day-headers-row {
  flex: 1;
  display: flex;
}

.day-header-cell {
  flex: 1;
  min-width: 80px;
  padding: 4px;
  text-align: center;
  border-right: 1px solid rgb(var(--v-border-color));
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
}

.day-header-cell:last-child {
  border-right: none;
}

.day-header-cell.single-day {
  min-width: 100%;
}

.day-name {
  font-size: 12px;
  text-transform: uppercase;
  opacity: 0.7;
  font-weight: 500;
}

.day-number {
  font-size: 12px;
  font-weight: 600;
}

.day-number.today {
  background-color: rgb(var(--v-theme-primary));
  color: rgb(var(--v-theme-on-primary));
  border-radius: 50%;
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 11px;
}

/* All-Day Events Section */
.all-day-section {
  display: flex;
  flex-shrink: 0;
  border-bottom: 1px solid rgb(var(--v-border-color));
  background-color: rgb(var(--v-theme-surface));
  min-height: 28px;
}

.all-day-label {
  width: 60px;
  min-width: 60px;
  flex-shrink: 0;
  border-right: 1px solid rgb(var(--v-border-color));
  background-color: rgb(var(--v-theme-surface-variant));
  display: flex;
  align-items: flex-start;
  justify-content: flex-end;
  padding: 4px 8px;
  font-size: 10px;
  opacity: 0.6;
  text-transform: uppercase;
}

.all-day-events-container {
  flex: 1;
  position: relative;
  min-height: 28px;
}

.all-day-columns {
  display: flex;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

.all-day-column {
  flex: 1;
  min-width: 80px;
  border-right: 1px solid rgb(var(--v-border-color), 0.3);
}

.all-day-column.single-day {
  min-width: 100%;
}

.all-day-column:last-child {
  border-right: none;
}

.all-day-events-overlay {
  position: absolute;
  top: 2px;
  left: 0;
  right: 0;
  bottom: 2px;
  pointer-events: none;
  z-index: 1;
}

.all-day-event {
  position: absolute;
  height: 20px;
  padding: 0 6px;
  font-size: 12px;
  color: white;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 500;
  display: flex;
  align-items: center;
  pointer-events: auto;
  box-sizing: border-box;
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.all-day-event:not(.is-start) {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
  padding-left: 4px;
}

.all-day-event:not(.is-end) {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

.all-day-event:hover {
  filter: brightness(1.1);
  z-index: 2;
}

.all-day-event .event-label {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Scrollable Content Area */
.days-content {
  display: flex;
  flex: 1;
  overflow-y: auto;
  overflow-x: hidden;
  min-height: 0; /* Allow flex child to shrink for scrolling */
}

.time-column {
  width: 60px;
  min-width: 60px;
  height: 1440px; /* 24 hours * 60px per hour */
  border-right: 1px solid rgb(var(--v-border-color));
  background-color: rgb(var(--v-theme-surface-variant));
  flex-shrink: 0;
}

.time-slot {
  height: 60px;
  padding: 4px 8px;
  font-size: 11px;
  opacity: 0.6;
  border-bottom: 1px solid rgb(var(--v-border-color), 0.5);
  text-align: right;
}

.days-columns {
  flex: 1;
  display: flex;
  min-height: 1440px; /* 24 hours * 60px per hour */
}

.day-column {
  flex: 1;
  min-width: 80px;
  border-right: 1px solid rgb(var(--v-border-color));
}

.day-column.single-day {
  min-width: 100%;
}

.day-column:last-child {
  border-right: none;
}

.day-events {
  position: relative;
  height: 1440px; /* 24 hours * 60px per hour */
  cursor: pointer;
}

.day-events:hover {
  background-color: rgba(var(--v-theme-primary), 0.02);
}

.day-event {
  position: absolute;
  left: 4px;
  right: 4px;
  padding: 6px 8px;
  border-radius: 4px;
  color: white;
  font-size: 12px;
  cursor: pointer;
  overflow: hidden;
  font-weight: 500;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
  transition: box-shadow 0.2s;
}

.day-event:hover {
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
  filter: brightness(1.1);
}

.event-time {
  font-weight: 600;
  margin-bottom: 2px;
  font-size: 11px;
}

.event-title {
  font-size: 13px;
  font-weight: 500;
}

.event-title-compact {
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
</style>
