<script setup>
import { computed, onMounted, onUnmounted, ref, watch, nextTick } from 'vue'
import { useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { Search, Folder, ListTodo, TicketCheck, Bot, CornerDownLeft } from 'lucide-vue-next'
import { call } from '../api'
import { useAppStore } from '../store'

const store = useAppStore()
const router = useRouter()
const { t } = useI18n()
const q = ref('')
const hits = ref([])
const sel = ref(0)
const busy = ref(false)
const searched = ref(false)
const input = ref(null)
const listEl = ref(null)
let timer = null

const kindMeta = {
  project: { icon: Folder, label: 'kindProject' },
  todo: { icon: ListTodo, label: 'kindTodo' },
  ticket: { icon: TicketCheck, label: 'kindTicket' },
  conversation: { icon: Bot, label: 'kindConversation' }
}
const groups = computed(() => {
  const by = {}
  const g = []
  for (const h of hits.value) {
    if (!by[h.kind]) { by[h.kind] = { kind: h.kind, items: [] }; g.push(by[h.kind]) }
    by[h.kind].items.push(h)
  }
  return g
})

watch(q, () => {
  clearTimeout(timer)
  timer = setTimeout(search, 180)
})
async function search() {
  const s = q.value.trim()
  if (!s) { hits.value = []; sel.value = 0; searched.value = false; return }
  busy.value = true
  try {
    hits.value = await call('GlobalSearch', s) || []
    sel.value = 0
    searched.value = true
  } catch { hits.value = [] }
  busy.value = false
}
function close() { store.paletteOpen = false }
function go(h) {
  close()
  if (h.kind === 'project') router.push(`/project/${h.id}`)
  else if (h.kind === 'todo') router.push('/todos')
  else if (h.kind === 'ticket') router.push('/tickets')
  else router.push({ path: '/ai', query: { conversation: h.id } })
}
function onKey(e) {
  if (e.key === 'Escape') { e.preventDefault(); close() }
  else if (e.key === 'ArrowDown') { e.preventDefault(); move(1) }
  else if (e.key === 'ArrowUp') { e.preventDefault(); move(-1) }
  else if (e.key === 'Enter' && hits.value[sel.value]) { e.preventDefault(); go(hits.value[sel.value]) }
}
function move(d) {
  if (!hits.value.length) return
  sel.value = (sel.value + d + hits.value.length) % hits.value.length
  nextTick(() => listEl.value?.querySelector('.cp-item.active')?.scrollIntoView({ block: 'nearest' }))
}
const flatIndex = h => hits.value.indexOf(h)
onMounted(() => {
  addEventListener('keydown', onKey)
  nextTick(() => input.value?.focus())
})
onUnmounted(() => { removeEventListener('keydown', onKey); clearTimeout(timer) })
</script>

<template>
  <div class="cp-overlay" @click.self="close">
    <section class="cp-panel popover-glass">
      <label class="cp-input">
        <Search />
        <input ref="input" v-model="q" :placeholder="t('searchPlaceholder')" spellcheck="false" />
        <kbd>Esc</kbd>
      </label>
      <div v-if="groups.length" ref="listEl" class="cp-list">
        <div v-for="g in groups" :key="g.kind" class="cp-group">
          <small>{{ t(kindMeta[g.kind].label) }}</small>
          <button v-for="h in g.items" :key="g.kind + h.id" class="cp-item" :class="{ active: flatIndex(h) === sel }"
            @mouseenter="sel = flatIndex(h)" @click="go(h)">
            <component :is="kindMeta[g.kind].icon" />
            <span class="cp-title">{{ h.title || '—' }}</span>
            <span v-if="h.sub" class="cp-sub">{{ h.sub }}</span>
            <CornerDownLeft v-if="flatIndex(h) === sel" class="cp-enter" />
          </button>
        </div>
      </div>
      <p v-else-if="searched && !busy" class="cp-empty">{{ t('searchEmpty') }}</p>
      <p v-else class="cp-empty muted">{{ t('searchHint') }}</p>
    </section>
  </div>
</template>
