<template>
  <div class="agenda-view">
    <div class="view-controls">
      <div class="view-navigation">
        <v-btn size="x-small" variant="text" icon="mdi-chevron-left" @click="previousPeriod" />
        <v-btn size="x-small" variant="tonal" @click="goToToday">Today</v-btn>
        <v-btn size="x-small" variant="text" icon="mdi-chevron-right" @click="nextPeriod" />
        <span class="current-period">{{ dateRangeLabel }}</span>
      </div>
      <v-spacer />
      <div class="view-selector">
        <v-btn
          v-for="span in AGENDA_VIEW_SPANS"
          :key="span"
          size="x-small"
          variant="text"
          @click="setSpan(span)"
          :color="selectedSpan === span ? 'primary' : undefined"
        >
          {{ span.toUpperCase() }}
        </v-btn>
      </div>
    </div>
    <v-list class="agenda-list">
      <template v-if="Object.keys(groupedEvents).length === 0">
        <v-list-item>
          <v-list-item-title class="text-center text-medium-emphasis">No events in this period</v-list-item-title>
        </v-list-item>
      </template>
      <template v-for="(dayEvents, date) in groupedEvents" :key="date">
        <v-list-subheader>{{ formatAgendaDate(date) }}</v-list-subheader>
        <v-list-item
          v-for="entity in dayEvents"
          :key="entity.identifier"
          @click="$emit('event-click', entity)"
        >
          <template #prepend>
            <v-icon :color="getEventColor(entity)">mdi-circle</v-icon>
          </template>
          <v-list-item-title>{{ entity.properties?.label || 'Untitled' }}</v-list-item-title>
          <v-list-item-subtitle>
            {{ getEventProperties(entity).timeless ? 'All day' : `${formatEventDateTime(getEventProperties(entity).startsOn)} - ${formatEventDateTime(getEventProperties(entity).endsOn)}` }}
          </v-list-item-subtitle>
        </v-list-item>
      </template>
    </v-list>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch } from 'vue';
import { AGENDA_VIEW_SPANS, spanToDays, type AgendaViewSpan } from '@/types/spans';
import type { EntityObject } from '@ChronoManager/models/entity';
import type { CollectionObject } from '@ChronoManager/models/collection';
import { EventObject } from '@ChronoManager/models/event';

type CalendarEntity = EntityObject;
type CalendarCollection = CollectionObject;

const props = defineProps<{
  events: CalendarEntity[];
  calendars: CalendarCollection[];
  currentDate?: Date;
  initialSpan?: AgendaViewSpan;
}>();

const selectedSpan = ref<AgendaViewSpan>(props.initialSpan ?? '1w');
const localDate = ref(new Date(props.currentDate ?? new Date()));

const emit = defineEmits<{
  'event-click': [event: CalendarEntity];
  'update:span': [span: AgendaViewSpan];
}>();

// Watch for external date changes (e.g., from mini calendar)
watch(() => props.currentDate, (newDate) => {
  if (newDate) {
    localDate.value = new Date(newDate);
  }
});

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

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

function getSpanDays(): number {
  return spanToDays(selectedSpan.value);
}

function previousPeriod() {
  const date = new Date(localDate.value);
  date.setDate(date.getDate() - getSpanDays());
  localDate.value = date;
}

function nextPeriod() {
  const date = new Date(localDate.value);
  date.setDate(date.getDate() + getSpanDays());
  localDate.value = date;
}

function goToToday() {
  localDate.value = new Date();
}

const dateRange = computed(() => {
  const start = new Date(localDate.value);
  start.setHours(0, 0, 0, 0);
  
  const end = new Date(start);
  end.setDate(end.getDate() + getSpanDays() - 1);
  end.setHours(23, 59, 59, 999);
  
  return { start, end };
});

const dateRangeLabel = computed(() => {
  const { start, end } = dateRange.value;
  const formatOptions: Intl.DateTimeFormatOptions = { month: 'short', day: 'numeric' };
  
  if (getSpanDays() === 1) {
    return start.toLocaleDateString('en-US', { month: 'long', day: 'numeric', year: 'numeric' });
  }
  
  if (start.getMonth() === end.getMonth()) {
    return `${start.toLocaleDateString('en-US', { month: 'short', day: 'numeric' })} - ${end.getDate()}, ${start.getFullYear()}`;
  }
  
  return `${start.toLocaleDateString('en-US', formatOptions)} - ${end.toLocaleDateString('en-US', formatOptions)}, ${end.getFullYear()}`;
});

const groupedEvents = computed(() => {
  const grouped: Record<string, CalendarEntity[]> = {};
  const { start, end } = dateRange.value;
  
  const filtered = props.events.filter((e): e is CalendarEntity => {
    const startsOn = getEventProperties(e).startsOn;
    if (typeof startsOn !== 'string') return false;
    const eventStart = new Date(startsOn);
    return eventStart >= start && eventStart <= end;
  });
  
  const sorted = filtered.sort((a, b) => 
    new Date(getEventProperties(a).startsOn || 0).getTime() - new Date(getEventProperties(b).startsOn || 0).getTime()
  );
  
  sorted.forEach(entity => {
    const dateKey = new Date(getEventProperties(entity).startsOn || 0).toDateString();
    if (!grouped[dateKey]) {
      grouped[dateKey] = [];
    }
    grouped[dateKey].push(entity);
  });
  
  return grouped;
});

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

function getEventProperties(entity: CalendarEntity): EventObject {
  return entity.properties as EventObject;
}

function formatTime(date: Date): string {
  return date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });
}

function formatEventDateTime(value: string | null): string {
  return value ? formatTime(new Date(value)) : '';
}

function formatAgendaDate(dateString: string): string {
  const date = new Date(dateString);
  return date.toLocaleDateString('en-US', { 
    weekday: 'long', 
    year: 'numeric', 
    month: 'long', 
    day: 'numeric' 
  });
}
</script>

<style scoped>
.agenda-view {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.view-controls {
  display: flex;
  align-items: center;
  padding: 4px 8px;
  border-bottom: 1px solid rgb(var(--v-border-color));
  background-color: rgb(var(--v-theme-surface));
  flex-shrink: 0;
}

.view-navigation {
  display: flex;
  align-items: center;
  gap: 4px;
}

.current-period {
  font-size: 14px;
  font-weight: 500;
  margin-left: 8px;
  white-space: nowrap;
}

.view-selector {
  display: flex;
  align-items: center;
  gap: 2px;
}

.agenda-list {
  flex: 1;
  overflow-y: auto;
  background-color: transparent;
}

.agenda-list :deep(.v-list-item) {
  margin: 4px 8px;
  border-radius: 4px;
  background-color: transparent;
}

.agenda-list :deep(.v-list-item:hover) {
  background-color: rgba(var(--v-theme-primary), 0.04);
}
</style>
