<script setup lang="ts">
definePageMeta({ middleware: ['auth'] })

// Tier 2 Block C — once a user can be invited as editor/viewer onto other
// hosts' events, the dashboard has to surface that distinction. We split
// the list into "Your events" (the ones the signed-in user created) and
// "Shared with you" (every event they're a collaborator on but didn't
// create). The split is driven by host_id; the role pill on each card
// tells the collaborator what they can actually do.
interface EventSummary {
  id: string
  host_id: string
  name: string
  slug: string
  event_date: string
  status: string
  venue: string
  max_capacity: number
  your_role?: 'owner' | 'editor' | 'viewer'
}

interface EventsResponse {
  events: EventSummary[]
}

interface PendingInvite {
  event_id: string
  event_name: string
  role: 'owner' | 'editor' | 'viewer'
  inviter_name: string
  expires_at: string
  created_at: string
}

const auth = useAuth()

const events = ref<EventSummary[]>([])
const loadingEvents = ref(false)
const loadError = ref<string | null>(null)

// Pending invites for the signed-in user's email. Shown as a banner above
// the event list so a user who just verified their email + signed in can
// accept without re-clicking the invitation email link (which would have
// opened in a different tab and lost the original signup context).
const pendingInvites = ref<PendingInvite[]>([])
const acceptingInvite = ref<string | null>(null)
const inviteError = ref<string | null>(null)

async function loadEvents() {
  if (!auth.user.value) return
  loadingEvents.value = true
  loadError.value = null
  try {
    const res = await useApi<EventsResponse>('/events')
    events.value = res.events
  } catch (e: any) {
    loadError.value = e?.data?.error || e?.message || 'Failed to load events'
  } finally {
    loadingEvents.value = false
  }
}

async function loadPendingInvites() {
  if (!auth.user.value) return
  try {
    const res = await useApi<{ invites: PendingInvite[] }>('/me/invites')
    pendingInvites.value = res.invites || []
  } catch {
    // Non-fatal: the dashboard works fine without the banner.
    pendingInvites.value = []
  }
}

async function acceptInvite(eventID: string) {
  acceptingInvite.value = eventID
  inviteError.value = null
  try {
    await useApi(`/me/invites/${eventID}/accept`, { method: 'POST' })
    // Reload both lists — the new event should appear in "Shared with you".
    await Promise.all([loadEvents(), loadPendingInvites()])
  } catch (e: any) {
    inviteError.value = useErrMessage(e, 'Could not accept invitation')
  } finally {
    acceptingInvite.value = null
  }
}

function dismissInvite(eventID: string) {
  // Local-only dismissal — the invite stays valid on the server so the
  // user can still revisit it from the inviter's resend, or after
  // refreshing the page. Keeps the dashboard tidy if they aren't ready
  // to accept right now.
  pendingInvites.value = pendingInvites.value.filter((i) => i.event_id !== eventID)
}

watch(() => auth.user.value, () => {
  loadEvents()
  loadPendingInvites()
}, { immediate: true })

const myEvents = computed(() =>
  events.value.filter((e) => auth.user.value && e.host_id === auth.user.value.id),
)
const sharedEvents = computed(() =>
  events.value.filter((e) => !auth.user.value || e.host_id !== auth.user.value.id),
)

function fmtDate(iso: string) {
  try { return new Date(iso).toLocaleString() } catch { return iso }
}

function roleBadgeClass(role?: string) {
  switch (role) {
    case 'owner': return 'bg-brand-900/40 text-brand-300'
    case 'editor': return 'bg-amber-900/30 text-amber-300'
    case 'viewer': return 'bg-zinc-800 text-zinc-300'
    default: return 'bg-zinc-800 text-zinc-400'
  }
}
</script>

<template>
  <section>
    <ClientOnly>
      <div v-if="!auth.bootstrapped.value || !auth.user.value" class="text-sm text-zinc-500">
        Loading dashboard…
      </div>

      <div v-else>
        <div class="mb-6 flex items-center justify-between">
          <div>
            <h1 class="text-2xl font-semibold">Events</h1>
            <p class="text-sm text-zinc-400">
              Welcome back, {{ auth.user.value.name }}.
            </p>
          </div>
          <NuxtLink to="/dashboard/events/new" class="btn-primary">New event</NuxtLink>
        </div>

        <!-- Pending invites banner — the safety net for users who lost
             the original invite tab during the verify-email round-trip. -->
        <div v-if="pendingInvites.length > 0" class="mb-6 space-y-3">
          <p v-if="inviteError" class="text-sm text-red-400">{{ inviteError }}</p>
          <div
            v-for="invite in pendingInvites"
            :key="invite.event_id"
            class="flex items-center justify-between gap-3 rounded-lg border border-brand-700/60 bg-brand-500/[0.06] p-4"
          >
            <div class="min-w-0 flex-1">
              <p class="text-xs font-medium uppercase tracking-wider text-brand-400">Team invitation</p>
              <p class="mt-1 text-sm text-zinc-100">
                <strong>{{ invite.inviter_name || 'A teammate' }}</strong>
                invited you to
                <strong>{{ invite.event_name }}</strong>
                as <span class="capitalize text-brand-300">{{ invite.role }}</span>.
              </p>
            </div>
            <div class="flex shrink-0 items-center gap-2">
              <button
                type="button"
                class="text-xs text-zinc-400 hover:text-zinc-200"
                @click="dismissInvite(invite.event_id)"
              >Later</button>
              <button
                type="button"
                class="btn-primary text-sm"
                :disabled="acceptingInvite === invite.event_id"
                @click="acceptInvite(invite.event_id)"
              >
                {{ acceptingInvite === invite.event_id ? 'Accepting…' : 'Accept' }}
              </button>
            </div>
          </div>
        </div>

        <div v-if="loadingEvents" class="text-sm text-zinc-500">Loading…</div>
        <div v-else-if="loadError" class="card text-sm text-red-400">{{ loadError }}</div>
        <div v-else-if="events.length === 0 && pendingInvites.length === 0" class="card text-sm text-zinc-400">
          No events yet. Create one to get started, or wait for a teammate to invite you.
        </div>
        <div v-else class="space-y-8">
          <!-- Events the signed-in user created. -->
          <div>
            <header class="mb-3 flex items-baseline justify-between">
              <h2 class="text-sm font-medium uppercase tracking-wider text-zinc-400">
                Yours · {{ myEvents.length }}
              </h2>
            </header>
            <div v-if="myEvents.length === 0" class="card text-sm text-zinc-500">
              You haven't created an event yet.
              <NuxtLink to="/dashboard/events/new" class="ml-1 text-brand-400 hover:text-brand-300">Start one</NuxtLink>.
            </div>
            <div v-else class="grid gap-4 md:grid-cols-2">
              <NuxtLink
                v-for="ev in myEvents"
                :key="ev.id"
                :to="`/dashboard/events/${ev.id}`"
                class="card transition hover:border-brand-700 hover:bg-zinc-900/80"
              >
                <div class="mb-1 flex items-center justify-between">
                  <h3 class="font-semibold text-zinc-50">{{ ev.name }}</h3>
                  <span class="text-xs uppercase tracking-wide text-zinc-500">{{ ev.status }}</span>
                </div>
                <p class="text-sm text-zinc-400">{{ ev.venue || '—' }}</p>
                <p class="mt-2 text-xs text-zinc-500">{{ fmtDate(ev.event_date) }}</p>
              </NuxtLink>
            </div>
          </div>

          <!-- Events the user was invited to. -->
          <div v-if="sharedEvents.length > 0">
            <header class="mb-3 flex items-baseline justify-between">
              <h2 class="text-sm font-medium uppercase tracking-wider text-zinc-400">
                Shared with you · {{ sharedEvents.length }}
              </h2>
            </header>
            <div class="grid gap-4 md:grid-cols-2">
              <NuxtLink
                v-for="ev in sharedEvents"
                :key="ev.id"
                :to="`/dashboard/events/${ev.id}`"
                class="card transition hover:border-brand-700 hover:bg-zinc-900/80"
              >
                <div class="mb-1 flex items-center justify-between gap-2">
                  <h3 class="truncate font-semibold text-zinc-50">{{ ev.name }}</h3>
                  <span
                    class="rounded-full px-2 py-0.5 text-[10px] font-medium uppercase tracking-wide"
                    :class="roleBadgeClass(ev.your_role)"
                  >{{ ev.your_role || 'member' }}</span>
                </div>
                <p class="text-sm text-zinc-400">{{ ev.venue || '—' }}</p>
                <p class="mt-2 text-xs text-zinc-500">{{ fmtDate(ev.event_date) }}</p>
              </NuxtLink>
            </div>
          </div>
        </div>
      </div>

      <template #fallback>
        <div class="text-sm text-zinc-500">Loading dashboard…</div>
      </template>
    </ClientOnly>
  </section>
</template>
