<template>
  <UContainer class="py-6">
    <div class="mx-auto max-w-7xl space-y-4">
      <div class="flex flex-col gap-2 lg:flex-row lg:items-end lg:justify-between">
        <div class="space-y-1">
          <UBadge label="Bookings" color="primary" variant="soft" size="sm" class="rounded-full" />
          <h1 class="text-2xl font-bold tracking-tight text-highlighted">
            Booking list
          </h1>
          <p class="text-sm text-muted">
            {{ auth.isSuperAdmin.value ? 'All submitted bookings across every PIC.' : 'Bookings assigned to you as PIC.' }}
          </p>
        </div>

        <UBadge
          :label="auth.isSuperAdmin.value ? 'Super Admin View' : 'Staff View'"
          :color="auth.isSuperAdmin.value ? 'primary' : 'neutral'"
          variant="soft"
          size="sm"
          class="rounded-full"
        />
      </div>

      <UAlert
        title="Inventory counting rule"
        :description="inventoryDescription"
        color="info"
        icon="i-lucide-info"
        variant="soft"
        :ui="{ root: 'py-3', title: 'text-sm font-medium', description: 'text-xs sm:text-sm' }"
      />

      <div v-if="auth.isSuperAdmin.value" class="grid gap-4 xl:grid-cols-[minmax(0,1.2fr)_18rem]">
        <UCard class="border border-default bg-default shadow-sm" :ui="{ header: 'px-4 py-3', body: 'px-4 py-3' }">
          <template #header>
            <div class="space-y-1">
              <h2 class="text-base font-semibold text-highlighted">
                Capacity settings
              </h2>
              <p class="text-xs text-muted sm:text-sm">
                Configure the event capacity used to calculate sold and left inventory.
              </p>
            </div>
          </template>

          <UForm :state="capacityForm" class="space-y-3" @submit="saveCapacity">
            <div class="flex flex-col gap-3 sm:flex-row sm:items-end">
              <UFormField name="totalSeats" label="Total Seats" class="flex-1">
                <UInput
                  v-model="capacityForm.totalSeats"
                  type="number"
                  inputmode="numeric"
                  min="0"
                  size="md"
                  class="w-full"
                  placeholder="Leave blank for no seat limit"
                />
              </UFormField>

              <UButton
                type="submit"
                label="Save Capacity"
                icon="i-lucide-save"
                size="md"
                :loading="savingCapacity"
                class="justify-center sm:min-w-32"
              />
            </div>

            <div class="flex items-center justify-between gap-3 border-t border-default pt-3">
              <p class="text-xs text-muted sm:text-sm">
                Last updated {{ settings.updatedAt ? formatDateTime(settings.updatedAt) : 'Not set yet' }}
              </p>
            </div>
          </UForm>
        </UCard>

        <UCard class="border border-default bg-default shadow-sm" :ui="{ header: 'px-4 py-3', body: 'px-4 py-3' }">
          <template #header>
            <div class="space-y-1">
              <h2 class="text-base font-semibold text-highlighted">
                Pending reservations
              </h2>
              <p class="text-xs text-muted sm:text-sm">
                Pending bookings are not counted as sold until the PIC confirms them.
              </p>
            </div>
          </template>

          <div class="grid gap-4 sm:grid-cols-2">
            <div class="rounded-lg border border-default bg-muted/20 p-3">
              <p class="text-xs uppercase tracking-wide text-muted">
                Pending bookings
              </p>
              <p class="mt-1 text-xl font-semibold text-highlighted">
                {{ pendingCount }}
              </p>
            </div>

            <div class="rounded-lg border border-default bg-muted/20 p-3">
              <p class="text-xs uppercase tracking-wide text-muted">
                Pending seats
              </p>
              <p class="mt-1 text-xl font-semibold text-highlighted">
                {{ summary.pendingSeats }}
              </p>
            </div>
          </div>
        </UCard>
      </div>

      <div class="grid gap-3 sm:grid-cols-2 xl:grid-cols-3">
        <UCard
          v-for="item in inventoryCards"
          :key="item.label"
          class="border border-default bg-default shadow-sm"
          :ui="{ body: 'px-4 py-3' }"
        >
          <div class="space-y-0.5">
            <p class="text-[11px] font-medium uppercase tracking-wide text-muted">
              {{ item.label }}
            </p>
            <p class="text-2xl font-semibold leading-none text-highlighted">
              {{ item.value }}
            </p>
          </div>
        </UCard>
      </div>

      <div class="grid gap-3 md:grid-cols-3">
        <UCard class="border border-default bg-default shadow-sm" :ui="{ body: 'px-4 py-3' }">
          <div class="space-y-0.5">
            <p class="text-[11px] font-medium uppercase tracking-wide text-muted">
              Total Seats
            </p>
            <p class="text-2xl font-semibold leading-none text-highlighted">
              {{ formatInventoryNumber(summary.totalSeats) }}
            </p>
          </div>
        </UCard>

        <UCard class="border border-default bg-default shadow-sm" :ui="{ body: 'px-4 py-3' }">
          <div class="space-y-0.5">
            <p class="text-[11px] font-medium uppercase tracking-wide text-muted">
              Total bookings
            </p>
            <p class="text-2xl font-semibold leading-none text-highlighted">
              {{ bookings.length }}
            </p>
          </div>
        </UCard>

        <UCard class="border border-default bg-default shadow-sm" :ui="{ body: 'px-4 py-3' }">
          <div class="space-y-0.5">
            <p class="text-[11px] font-medium uppercase tracking-wide text-muted">
              Booking status
            </p>
            <p class="text-sm font-medium text-default">
              {{ confirmedCount }} confirmed, {{ pendingCount }} pending
            </p>
          </div>
        </UCard>
      </div>

      <UCard
        class="border border-default bg-default shadow-sm"
        :ui="{ header: 'px-4 py-3', body: 'p-0 sm:p-0' }"
      >
        <template #header>
          <div class="flex flex-col gap-2 lg:flex-row lg:items-center lg:justify-between">
            <div class="flex flex-col gap-2 sm:flex-row sm:items-center">
              <UInput
                v-model="searchQuery"
                size="md"
                class="w-full sm:w-72"
                placeholder="Search guest, phone, PIC, or ticket"
              />

              <UButton
                label="Refresh"
                color="neutral"
                variant="outline"
                icon="i-lucide-refresh-cw"
                size="md"
                :loading="loadingBookings"
                @click="refreshBookings"
              />
            </div>
          </div>
        </template>

        <div class="overflow-x-auto">
          <UTable
            :data="filteredBookings"
            :columns="columns"
            :loading="loadingBookings"
            :empty="searchQuery.trim() ? 'No matching bookings found.' : 'No bookings available yet.'"
            sticky="header"
            caption="Bookings"
            class="min-w-[980px]"
          >
            <template #customerName-cell="{ row }">
              <div class="min-w-0 space-y-0.5 py-0.5">
                <div class="text-sm font-semibold leading-tight text-highlighted">
                  {{ row.original.customerName }}
                </div>
                <div class="text-xs text-muted">
                  {{ row.original.customerPhone }}
                </div>
              </div>
            </template>

            <template #quantity-cell="{ row }">
              <div class="space-y-0.5 py-0.5">
                <div class="text-sm font-medium text-default">
                  {{ ticketLabel(row.original.ticketType) }}
                </div>
              </div>
            </template>

            <template #seatCount-cell="{ row }">
              <div class="space-y-0.5 py-0.5">
                <div class="text-sm font-medium text-default">
                  {{ row.original.seatCount }} seats
                </div>
                <div class="text-xs text-muted">
                  {{ formatBookingCurrency(row.original.totalPrice) }}
                </div>
              </div>
            </template>

            <template #personInChargeName-cell="{ row }">
              <div class="min-w-0 space-y-0.5 py-0.5">
                <div class="text-sm font-medium text-default">
                  {{ row.original.personInChargeName }}
                </div>
                <div class="text-xs text-muted">
                  {{ row.original.personInChargePhoneNumber }}
                </div>
              </div>
            </template>

            <template #status-cell="{ row }">
              <div class="space-y-1 py-0.5">
                <UBadge
                  :label="getBookingStatusLabel(row.original.status)"
                  :color="row.original.status === 'confirmed' ? 'success' : 'warning'"
                  variant="soft"
                  size="sm"
                />
                <div class="text-xs text-muted">
                  {{ row.original.status === 'confirmed' ? `Confirmed ${formatDateTime(row.original.confirmedAt)}` : 'Awaiting PIC confirmation' }}
                </div>
              </div>
            </template>

            <template #createdAt-cell="{ row }">
              <span class="text-xs text-muted">
                {{ formatDateTime(row.original.createdAt) }}
              </span>
            </template>

            <template #actions-cell="{ row }">
              <div class="flex flex-wrap justify-end gap-1.5 py-0.5">
                <UButton
                  :to="confirmationPath(row.original)"
                  label="Open"
                  color="neutral"
                  variant="outline"
                  icon="i-lucide-external-link"
                  size="sm"
                />
                <UButton
                  :to="receiptPath(row.original)"
                  label="Receipt"
                  color="neutral"
                  variant="outline"
                  icon="i-lucide-receipt"
                  size="sm"
                />
              </div>
            </template>
          </UTable>
        </div>
      </UCard>
    </div>
  </UContainer>
</template>

<script lang="ts" setup>
import type { BookingCapacitySettings, BookingInventorySummary, PublicBooking, TicketType } from '~~/shared/booking'

import {
  formatBookingCurrency,
  getBookingStatusLabel,
  getTicketCatalogItem
} from '~~/shared/booking'

import { getErrorMessage } from '../../utils/errors'
import { formatDateTime } from '../../utils/formatters'

definePageMeta({
  middleware: 'auth'
})

const toast = useToast()
const apiClient = useApiClient()
const auth = useAuth()

const bookings = ref<PublicBooking[]>([])
const loadingBookings = ref(false)
const savingCapacity = ref(false)
const searchQuery = ref('')
const settings = reactive<BookingCapacitySettings>({
  totalSeats: null,
  updatedAt: null
})
const summary = reactive<BookingInventorySummary>({
  totalSeats: null,
  soldSeats: 0,
  pendingSeats: 0,
  leftSeats: null
})
const capacityForm = reactive({
  totalSeats: ''
})

const columns = [
  { accessorKey: 'customerName', header: 'Guest' },
  { accessorKey: 'quantity', header: 'Booking' },
  { accessorKey: 'seatCount', header: 'Seats / Total' },
  { accessorKey: 'personInChargeName', header: 'PIC' },
  { id: 'status', header: 'Status' },
  { accessorKey: 'createdAt', header: 'Submitted' },
  { id: 'actions', header: 'Actions' }
]

const inventoryDescription = computed(() => {
  return 'Every booking is converted into seats immediately, so sold and remaining capacity are tracked only in seats.'
})

const inventoryCards = computed(() => {
  return [
    {
      label: 'Seats Sold',
      value: String(summary.soldSeats)
    },
    {
      label: 'Pending Seats',
      value: String(summary.pendingSeats)
    },
    {
      label: 'Seats Left',
      value: formatInventoryNumber(summary.leftSeats)
    }
  ]
})

const filteredBookings = computed(() => {
  const keyword = searchQuery.value.trim().toLowerCase()

  if (!keyword) {
    return bookings.value
  }

  return bookings.value.filter((booking) => {
    return [
      booking.customerName,
      booking.customerPhone,
      booking.personInChargeName,
      booking.personInChargePhoneNumber,
      booking.ticketType,
      booking.status
    ].some((value) => value.toLowerCase().includes(keyword))
  })
})

const pendingCount = computed(() => {
  return bookings.value.filter((booking) => booking.status === 'pending').length
})

const confirmedCount = computed(() => {
  return bookings.value.filter((booking) => booking.status === 'confirmed').length
})

await refreshBookings()

function ticketLabel(ticketType: TicketType) {
  return getTicketCatalogItem(ticketType)?.label || ticketType.toUpperCase()
}

function confirmationPath(booking: PublicBooking) {
  return `/confirmation/${booking.confirmationToken}`
}

function receiptPath(booking: PublicBooking) {
  return `/receipt/${booking.receiptToken}`
}

function formatInventoryNumber(value: number | null) {
  return value === null ? 'Not set' : String(value)
}

function normalizeCapacityValue(value: string | number | null | undefined) {
  if (typeof value === 'number') {
    return Number.isFinite(value) ? String(value) : null
  }

  const normalized = String(value || '').trim()
  return normalized || null
}

function syncCapacityForm(nextSettings: BookingCapacitySettings) {
  capacityForm.totalSeats = nextSettings.totalSeats === null ? '' : String(nextSettings.totalSeats)
}

function applySettings(nextSettings: BookingCapacitySettings) {
  settings.totalSeats = nextSettings.totalSeats
  settings.updatedAt = nextSettings.updatedAt
  syncCapacityForm(nextSettings)
}

function applySummary(nextSummary: BookingInventorySummary) {
  summary.totalSeats = nextSummary.totalSeats
  summary.soldSeats = nextSummary.soldSeats
  summary.pendingSeats = nextSummary.pendingSeats
  summary.leftSeats = nextSummary.leftSeats
}

async function refreshBookings() {
  if (loadingBookings.value) {
    return
  }

  loadingBookings.value = true

  try {
    const response = await apiClient<{
      bookings: PublicBooking[]
      settings: BookingCapacitySettings
      summary: BookingInventorySummary
    }>('/api/bookings')

    bookings.value = response.bookings
    applySettings(response.settings)
    applySummary(response.summary)
  } catch (error: any) {
    toast.add({
      title: 'Unable to load bookings',
      description: getErrorMessage(error, 'The booking list could not be loaded.'),
      color: 'error',
      icon: 'i-lucide-circle-alert'
    })
  } finally {
    loadingBookings.value = false
  }
}

async function saveCapacity(event: Event) {
  event.preventDefault()

  if (!auth.isSuperAdmin.value || savingCapacity.value) {
    return
  }

  savingCapacity.value = true

  try {
    const response = await apiClient<{ settings: BookingCapacitySettings }>('/api/bookings/capacity', {
      method: 'PATCH',
      body: {
        totalSeats: normalizeCapacityValue(capacityForm.totalSeats)
      }
    })

    applySettings(response.settings)
    await refreshBookings()

    toast.add({
      title: 'Capacity updated',
      description: 'The booking inventory limits have been saved.',
      color: 'success',
      icon: 'i-lucide-check-circle-2'
    })
  } catch (error: any) {
    toast.add({
      title: 'Capacity update failed',
      description: getErrorMessage(error, 'Unable to save the booking inventory limits.'),
      color: 'error',
      icon: 'i-lucide-circle-alert'
    })
  } finally {
    savingCapacity.value = false
  }
}
</script>
