<script setup lang="ts">
import type { SetupContext } from 'vue'
import type { CalendarEvent } from '../CalendarTypes'
import { formatDate } from '@bagelink/vue'
import { ref, computed, onMounted, onUnmounted, useSlots } from 'vue'

interface AgendaViewEvent extends CalendarEvent {
	dayLabel: string
	isToday: boolean
	height: number
}

const props = defineProps<{
	events: CalendarEvent[]
	startDate: Date
}>()

const emit = defineEmits<{
	(e: 'eventClick', event: CalendarEvent): void
	(e: 'dateChange', date: Date): void
	(e: 'openPopover', event: CalendarEvent, position?: { top: number, left: number }): void
}>()

const slots: SetupContext['slots'] = useSlots()

// UI references
const containerRef = ref<HTMLElement | null>(null)
const currentDate = ref<Date | null>(null)

// Process events for agenda view
const processedEvents = computed(() => {
	const events: AgendaViewEvent[] = []
	const today = new Date().toDateString()

	// Sort events by start time
	const sortedEvents = [...props.events].sort(
		(a, b) => new Date(a.start_time).getTime() - new Date(b.start_time).getTime()
	)

	// Group events by date
	const eventsByDate = sortedEvents.reduce((acc, event) => {
		const date = new Date(event.start_time).toDateString()
		if (!acc[date]) acc[date] = []
		acc[date].push(event)
		return acc
	}, {} as { [key: string]: CalendarEvent[] })

	// Process each date's events
	Object.entries(eventsByDate).forEach(([dateStr, dateEvents]) => {
		const date = new Date(dateStr)
		const isToday = date.toDateString() === today

		dateEvents.forEach((event) => {
			const duration = (new Date(event.end_time).getTime() - new Date(event.start_time).getTime()) / (1000 * 60)
			// Limit height: 60px per 30 minutes, max 200px
			const height = Math.min(duration / 30 * 60, 200)

			events.push({
				...event,
				dayLabel: date.toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric' }),
				isToday,
				height
			})
		})
	})

	return events
})

// Handle scroll to determine visible date
function handleScroll() {
	if (!containerRef.value) return

	const container = containerRef.value
	const eventElements = container.querySelectorAll('.event')
	let mostVisibleEvent: Element | null = null
	let maxVisibility = 0

	// Find the event that's most visible in the viewport
	eventElements.forEach((element) => {
		const rect = element.getBoundingClientRect()
		const containerRect = container.getBoundingClientRect()

		// Calculate how much of the element is visible
		const visibleTop = Math.max(rect.top, containerRect.top)
		const visibleBottom = Math.min(rect.bottom, containerRect.bottom)
		const visibleHeight = Math.max(0, visibleBottom - visibleTop)
		const visibility = visibleHeight / rect.height

		if (visibility > maxVisibility) {
			maxVisibility = visibility
			mostVisibleEvent = element
		}
	})

	// Update current date if a new date is most visible
	if (mostVisibleEvent) {
		const element = mostVisibleEvent as HTMLElement
		const dateStr = element.dataset.date || element.getAttribute('data-date')
		if (dateStr) {
			const date = new Date(dateStr)
			if (!currentDate.value || date.toDateString() !== currentDate.value.toDateString()) {
				currentDate.value = date
				emit('dateChange', date)
			}
		}
	}
}

// Update event handling to emit the openPopover event
function handleEventSelection(event: CalendarEvent, domEvent?: MouseEvent) {
	if (!slots.eventContent) {
		emit('eventClick', event)
		return
	}

	// Calculate position from DOM event if available
	if (domEvent) {
		const rect = (domEvent.currentTarget as HTMLElement).getBoundingClientRect()
		const position = {
			top: rect.top + window.scrollY + (rect.height / 2),
			left: rect.left + window.scrollX + rect.width + 10
		}
		emit('openPopover', event, position)
	} else {
		emit('openPopover', event)
	}
}

// Lifecycle hooks
onMounted(() => {
	if (containerRef.value) {
		containerRef.value.addEventListener('scroll', handleScroll)
	}
})

onUnmounted(() => {
	if (containerRef.value) {
		containerRef.value.removeEventListener('scroll', handleScroll)
	}
})
</script>

<template>
	<div class="agenda-view">
		<div class="agenda-header">
			<div class="time-column">
				Time
			</div>
			<div class="event-column">
				Event
			</div>
		</div>
		<div ref="containerRef" class="agenda-content">
			<div
				v-for="event in processedEvents"
				:key="event.id"
				class="event"
				:style="{
					height: `${event.height}px`,
					backgroundColor: event.color || 'var(--bgl-primary)',
				}"
				:data-date="event.start_time"
				@click.stop="handleEventSelection(event, $event)"
			>
				<div class="event-content">
					<div class="event-time">
						{{ formatDate(event.start_time, { fmt: 'HH:mm' }) }}
					</div>
					<div class="event-details">
						<div class="event-title">
							{{ event.title }}
						</div>
						<div class="event-day" :class="{ today: event.isToday }">
							{{ event.dayLabel }}
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

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

.agenda-header {
  display: flex;
  padding: 0.5rem;
  border-bottom: 1px solid var(--border-color);
}

.time-column {
  width: 100px;
  flex-shrink: 0;
}

.event-column {
  flex-grow: 1;
}

.agenda-content {
  flex-grow: 1;
  overflow-y: auto;
  padding: 1rem;
}

.event {
  margin-bottom: 1rem;
  border-radius: 4px;
  overflow: hidden;
  cursor: pointer;
  transition: all 0.2s ease;
}

.event:hover {
  transform: scale(1.01);
}

.event-content {
  display: flex;
  height: 100%;
  color: white;
}

.event-time {
  width: 100px;
  flex-shrink: 0;
  padding: 0.5rem;
  display: flex;
  align-items: center;
  font-size: 0.9rem;
}

.event-details {
  flex-grow: 1;
  padding: 0.5rem;
  border-left: 1px solid rgba(255, 255, 255, 0.2);
}

.event-title {
  font-size: 1rem;
  margin-bottom: 0.25rem;
}

.event-day {
  font-size: 0.8rem;
  opacity: 0.8;
}

.event-day.today {
  color: var(--bgl-primary);
  opacity: 1;
}

@media (max-width: 768px) {
  .agenda-header {
    padding: 0.5rem;
  }

  .time-column {
    width: 80px;
  }

  .event-content {
    font-size: 0.9rem;
  }

  .event-time {
    width: 80px;
    font-size: 0.8rem;
  }

  .event-title {
    font-size: 0.9rem;
  }

  .event-day {
    font-size: 0.7rem;
  }
}
</style>
