<template>
  <div class="event-list">
    <section
      v-for="section in groupedSections"
      :key="section.key"
      :aria-label="section.label"
      class="event-section"
    >
      <SectionHeader :label="section.label" :emphasized="section.emphasized" />
      <div role="list">
        <template v-for="group in section.dateGroups" :key="group.dateKey">
          <DateSubheader v-if="group.showSubheader" :label="group.label" />
          <div v-for="event in group.events" :key="event.eventToken" role="listitem">
            <EventCard
              :event-token="event.eventToken"
              :title="event.title"
              :relative-time="formatRelativeTime(event.dateTime)"
              :is-past="section.key === 'past'"
              :event-role="getRole(event)"
              :time-display-mode="section.key === 'past' ? 'relative' : 'clock'"
              :date-time="event.dateTime"
              @delete="requestDelete"
            />
          </div>
        </template>
      </div>
    </section>
    <ConfirmDialog
      :open="!!pendingDeleteToken"
      :title="deleteDialogTitle"
      :message="deleteDialogMessage"
      confirm-label="Remove"
      cancel-label="Cancel"
      @confirm="confirmDelete"
      @cancel="cancelDelete"
    />
  </div>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { useEventStorage, isValidStoredEvent } from '../composables/useEventStorage'
import { useEventGrouping } from '../composables/useEventGrouping'
import { formatRelativeTime } from '../composables/useRelativeTime'
import { api } from '../api/client'
import EventCard from './EventCard.vue'
import SectionHeader from './SectionHeader.vue'
import DateSubheader from './DateSubheader.vue'
import ConfirmDialog from './ConfirmDialog.vue'
import type { StoredEvent } from '../composables/useEventStorage'

const { getStoredEvents, getRsvp, getOrganizerToken, removeEvent } = useEventStorage()

const pendingDeleteToken = ref<string | null>(null)
const deleteError = ref('')

const pendingDeleteRole = computed(() => {
  if (!pendingDeleteToken.value) return null
  const event = getStoredEvents().find((e) => e.eventToken === pendingDeleteToken.value)
  return event ? getRole(event) : null
})

const deleteDialogTitle = computed(() => {
  return pendingDeleteRole.value === 'organizer' ? 'Cancel event?' : 'Remove event?'
})

const deleteDialogMessage = computed(() => {
  if (!pendingDeleteToken.value) return ''
  if (pendingDeleteRole.value === 'organizer') {
    return 'This will permanently cancel the event for all attendees.'
  }
  const rsvp = getRsvp(pendingDeleteToken.value)
  if (rsvp) {
    return 'This event will be removed from your list and your attendance will be cancelled.'
  }
  return 'This event will be removed from your list.'
})

function requestDelete(eventToken: string) {
  deleteError.value = ''
  const role = getRole(getStoredEvents().find((e) => e.eventToken === eventToken)!)
  if (role === 'watcher') {
    removeEvent(eventToken)
    return
  }
  pendingDeleteToken.value = eventToken
}

async function confirmDelete() {
  if (!pendingDeleteToken.value) return

  const eventToken = pendingDeleteToken.value
  const organizerToken = getOrganizerToken(eventToken)

  if (organizerToken) {
    try {
      const { response } = await api.PATCH('/events/{eventToken}', {
        params: {
          path: { eventToken },
          query: { organizerToken },
        },
        body: { cancelled: true },
      })

      if (response.status !== 204 && response.status !== 409 && response.status !== 404) {
        deleteError.value = 'Could not cancel event. Please try again.'
        return
      }
    } catch {
      deleteError.value = 'Could not cancel event. Please try again.'
      return
    }

    removeEvent(eventToken)
    pendingDeleteToken.value = null
    return
  }

  const rsvp = getRsvp(eventToken)

  if (rsvp) {
    try {
      const { response } = await api.DELETE('/events/{eventToken}/rsvps/{rsvpToken}', {
        params: {
          path: {
            eventToken: eventToken,
            rsvpToken: rsvp.rsvpToken,
          },
        },
      })

      if (response.status !== 204 && response.status !== 404) {
        deleteError.value = 'Could not cancel attendance. Please try again.'
        pendingDeleteToken.value = null
        return
      }
    } catch {
      deleteError.value = 'Could not cancel attendance. Please try again.'
      pendingDeleteToken.value = null
      return
    }
  }

  removeEvent(eventToken)
  pendingDeleteToken.value = null
}

function cancelDelete() {
  pendingDeleteToken.value = null
}

function getRole(event: StoredEvent): 'organizer' | 'attendee' | 'watcher' {
  if (event.organizerToken) return 'organizer'
  if (event.rsvpToken) return 'attendee'
  return 'watcher'
}

const groupedSections = computed(() => {
  const valid = getStoredEvents().filter(isValidStoredEvent)
  return useEventGrouping(valid)
})
</script>

<style scoped>
.event-list {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-md);
}

.event-section [role="list"] {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-sm);
}
</style>
