<script lang="ts" setup>
import { router } from '@inertiajs/vue3'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'

interface PaletteItem {
  title: string
  icon: string
  href: string
  section: string
}

interface Props {
  items: PaletteItem[]
}

const props = defineProps<Props>()
const isOpen = ref<boolean>(false)
const searchQuery = ref<string>('')
const selectedIndex = ref<number>(0)

const filteredItems = computed<PaletteItem[]>(() => {
  if (!searchQuery.value) return props.items
  const q = searchQuery.value.toLowerCase()
  return props.items.filter(item =>
    item.title.toLowerCase().includes(q) || item.section.toLowerCase().includes(q)
  )
})

watch(searchQuery, () => { selectedIndex.value = 0 })

function open(): void {
  isOpen.value = true
  searchQuery.value = ''
  selectedIndex.value = 0
}

function close(): void {
  isOpen.value = false
}

function navigate(item: PaletteItem): void {
  close()
  router.visit(item.href)
}

function handleKeydown(e: KeyboardEvent): void {
  if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
    e.preventDefault()
    isOpen.value ? close() : open()
    return
  }
  if (!isOpen.value) return

  if (e.key === 'ArrowDown') {
    e.preventDefault()
    selectedIndex.value = Math.min(selectedIndex.value + 1, filteredItems.value.length - 1)
  } else if (e.key === 'ArrowUp') {
    e.preventDefault()
    selectedIndex.value = Math.max(selectedIndex.value - 1, 0)
  } else if (e.key === 'Enter' && filteredItems.value[selectedIndex.value]) {
    e.preventDefault()
    navigate(filteredItems.value[selectedIndex.value])
  }
}

onMounted(() => document.addEventListener('keydown', handleKeydown))
onUnmounted(() => document.removeEventListener('keydown', handleKeydown))

defineExpose({ open })
</script>

<template>
  <VDialog
    v-model="isOpen"
    max-width="560"
    content-class="command-palette-dialog"
    transition="dialog-top-transition"
  >
    <VCard>
      <div class="d-flex align-center pa-4 pb-0">
        <VIcon icon="tabler-search" size="20" class="me-3 text-medium-emphasis" />
        <input
          v-model="searchQuery"
          placeholder="Search pages..."
          class="command-palette-input flex-grow-1"
          autofocus
        />
        <VChip size="x-small" variant="outlined" @click="close">
          ESC
        </VChip>
      </div>

      <VDivider class="mt-4" />

      <VList v-if="filteredItems.length > 0" class="pa-2" density="compact" max-height="400" style="overflow-y: auto;">
        <VListItem
          v-for="(item, i) in filteredItems"
          :key="item.href"
          :active="i === selectedIndex"
          color="primary"
          rounded
          @click="navigate(item)"
          @mouseenter="selectedIndex = i"
        >
          <template #prepend>
            <VIcon :icon="item.icon" size="18" />
          </template>
          <VListItemTitle class="text-body-2">{{ item.title }}</VListItemTitle>
          <template #append>
            <VChip size="x-small" variant="text" class="text-caption text-medium-emphasis">
              {{ item.section }}
            </VChip>
          </template>
        </VListItem>
      </VList>

      <div v-else class="pa-8 text-center">
        <div class="text-body-2 text-medium-emphasis">No results found</div>
      </div>
    </VCard>
  </VDialog>
</template>

<style lang="scss" scoped>
.command-palette-input {
  background: none;
  border: none;
  outline: none;
  font-size: 1rem;
  color: inherit;
  width: 100%;

  &::placeholder {
    color: rgba(var(--v-theme-on-surface), 0.4);
  }
}
</style>
