<script>
  let { items = [], onNavigate = () => {}, onOpenExternal = () => {} } = $props();

  let open = $state(false);
  let query = $state("");
  let selectedIndex = $state(0);
  let inputEl = $state(null);

  function fuzzyMatch(text, q) {
    if (!q) return true;
    const lower = text.toLowerCase();
    const ql = q.toLowerCase();
    let qi = 0;
    for (let i = 0; i < lower.length && qi < ql.length; i++) {
      if (lower[i] === ql[qi]) qi++;
    }
    return qi === ql.length;
  }

  let filtered = $derived(
    items.filter(i => fuzzyMatch(i.label + " " + (i.section || ""), query))
  );

  function handleKeydown(e) {
    if ((e.metaKey || e.ctrlKey) && e.key === "k") {
      e.preventDefault();
      open = !open;
      if (open) {
        query = "";
        selectedIndex = 0;
      }
    }
    if (!open) return;
    if (e.key === "ArrowDown") {
      e.preventDefault();
      selectedIndex = Math.min(selectedIndex + 1, filtered.length - 1);
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      selectedIndex = Math.max(selectedIndex - 1, 0);
    } else if (e.key === "Enter" && filtered[selectedIndex]) {
      e.preventDefault();
      select(filtered[selectedIndex]);
    } else if (e.key === "Escape") {
      e.preventDefault();
      open = false;
    }
  }

  function select(item) {
    open = false;
    if (item.external || item.remoteHref) {
      window.open(item.remoteHref || item.href, "_blank", "noopener");
    } else if (item.id) {
      onNavigate(item.id);
    }
  }

  function sectionClass(section) {
    if (section === "main") return "text-sky-500";
    if (section === "media") return "text-violet-500";
    if (section === "tools") return "text-amber-500";
    return "text-surface-400";
  }
</script>

<svelte:window onkeydown={handleKeydown} />

{#if open}
  <!-- Overlay -->
  <button class="fixed inset-0 bg-black/40 z-[100] backdrop-blur-sm" onclick={() => open = false}></button>

  <!-- Palette -->
  <div class="fixed top-[15%] left-1/2 -translate-x-1/2 z-[101] w-[520px] max-w-[90vw]" role="dialog" aria-modal="true">
    <div class="bg-white dark:bg-surface-800 rounded-2xl border border-surface-200 dark:border-surface-700 shadow-2xl overflow-hidden">
      <!-- Search -->
      <div class="flex items-center px-4 border-b border-surface-200 dark:border-surface-700">
        <svg class="w-4 h-4 text-surface-400 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /></svg>
        <input
          bind:this={inputEl}
          type="text"
          placeholder="Search services, pages, actions..."
          bind:value={query}
          class="w-full bg-transparent border-none outline-none px-3 py-4 text-sm text-surface-800 dark:text-surface-200 placeholder-surface-400"
          autofocus
        />
        <kbd class="text-[10px] font-mono px-1.5 py-0.5 rounded bg-surface-100 dark:bg-surface-700 text-surface-400">esc</kbd>
      </div>

      <!-- Results -->
      <div class="max-h-[360px] overflow-y-auto p-2">
        {#if filtered.length === 0}
          <div class="py-8 text-center text-sm text-surface-400">No results found</div>
        {:else}
          {#each filtered as item, i}
            <button
              class="w-full text-left px-3 py-2.5 rounded-xl text-sm flex items-center gap-3 transition-all duration-100
                {i === selectedIndex
                  ? 'bg-primary-50 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 shadow-sm'
                  : 'text-surface-600 dark:text-surface-300 hover:bg-surface-100 dark:hover:bg-surface-700'}
              "
              onmouseenter={() => selectedIndex = i}
              onclick={() => select(item)}
            >
              <span class="w-6 h-6 rounded-lg flex items-center justify-center text-xs font-bold uppercase {sectionClass(item.section)}">
                {item.section ? item.section[0] : "?"}
              </span>
              <div class="flex-1 min-w-0">
                <div class="font-medium truncate">{item.label}</div>
                {#if item.description}
                  <div class="text-[11px] text-surface-400 truncate">{item.description}</div>
                {/if}
              </div>
              {#if item.external || item.remoteHref}
                <svg class="w-3 h-3 text-surface-400 shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" /></svg>
              {/if}
            </button>
          {/each}
        {/if}
      </div>

      <!-- Footer hint -->
      <div class="flex items-center gap-4 px-4 py-2.5 border-t border-surface-200 dark:border-surface-700 bg-surface-50 dark:bg-surface-800/50">
        <div class="flex items-center gap-1.5 text-[10px] text-surface-400">
          <kbd class="font-mono px-1 py-0.5 rounded bg-surface-200 dark:bg-surface-600 text-surface-500">↑↓</kbd>
          <span>Navigate</span>
        </div>
        <div class="flex items-center gap-1.5 text-[10px] text-surface-400">
          <kbd class="font-mono px-1 py-0.5 rounded bg-surface-200 dark:bg-surface-600 text-surface-500">↵</kbd>
          <span>Open</span>
        </div>
        <div class="flex items-center gap-1.5 text-[10px] text-surface-400">
          <kbd class="font-mono px-1 py-0.5 rounded bg-surface-200 dark:bg-surface-600 text-surface-500">esc</kbd>
          <span>Close</span>
        </div>
      </div>
    </div>
  </div>
{/if}
