'use client'

import { useRouter } from 'next/navigation'
import { useEffect, useMemo, useRef, useState } from 'react'
import { Explain, useUiMode } from './UiModeContext'

export type HeaderCommandItem = {
  href?: string
  label: string
  description?: string
  section: string
  keywords?: string[]
  onSelect?: () => void | Promise<void>
}

function SearchIcon({ className = 'h-4 w-4' }: { className?: string }) {
  return (
    <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden>
      <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.9} d="m21 21-4.35-4.35" />
      <circle cx="11" cy="11" r="6.5" strokeWidth={1.9} />
    </svg>
  )
}

function matchItem(item: HeaderCommandItem, query: string) {
  const haystack = `${item.label} ${item.description || ''} ${item.section} ${(item.keywords || []).join(' ')}`.toLowerCase()
  return haystack.includes(query.toLowerCase())
}

export default function HeaderCommandPalette({
  open,
  onClose,
  items,
}: {
  open: boolean
  onClose: () => void
  items: HeaderCommandItem[]
}) {
  const router = useRouter()
  const { mode } = useUiMode()
  const inputRef = useRef<HTMLInputElement | null>(null)
  const itemRefs = useRef<Array<HTMLButtonElement | null>>([])
  const [query, setQuery] = useState('')
  const [activeIndex, setActiveIndex] = useState(0)

  const filteredItems = useMemo(() => {
    const matches = query.trim()
      ? items.filter((item) => matchItem(item, query))
      : items

    return [
      {
        href: `/search${query.trim() ? `?q=${encodeURIComponent(query.trim())}` : ''}`,
        label: query.trim() ? `Search for “${query.trim()}”` : 'Open full explorer search',
        description: query.trim()
          ? 'Jump to the full search surface with the current query.'
          : 'Open the full search page and browse the explorer index.',
        section: 'Search',
        keywords: ['query', 'find', 'lookup'],
      },
      ...matches,
    ]
  }, [items, query])

  useEffect(() => {
    if (!open) {
      setQuery('')
      setActiveIndex(0)
      return
    }

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        event.preventDefault()
        onClose()
      }
    }

    document.addEventListener('keydown', handleKeyDown)
    requestAnimationFrame(() => inputRef.current?.focus())
    return () => document.removeEventListener('keydown', handleKeyDown)
  }, [onClose, open])

  useEffect(() => {
    setActiveIndex(0)
  }, [query])

  useEffect(() => {
    if (!open) return
    itemRefs.current[activeIndex]?.scrollIntoView({ block: 'nearest' })
  }, [activeIndex, open])

  if (!open) return null

  const handleSelect = async (item: HeaderCommandItem) => {
    onClose()
    if (item.onSelect) {
      await item.onSelect()
      return
    }
    if (item.href) {
      router.push(item.href)
    }
  }

  return (
    <div className="fixed inset-0 z-[80] flex items-start justify-center bg-gray-950/45 px-4 py-20 backdrop-blur-sm">
      <div
        role="dialog"
        aria-modal="true"
        aria-label="Explorer command palette"
        className="w-full max-w-2xl overflow-hidden rounded-3xl border border-gray-200 bg-white shadow-[0_30px_100px_rgba(15,23,42,0.32)] dark:border-gray-700 dark:bg-gray-950"
      >
        <div className="border-b border-gray-200 px-5 py-4 dark:border-gray-800">
          <label htmlFor="header-command-search" className="sr-only">
            Search explorer destinations
          </label>
          <div className="flex items-center gap-3 rounded-2xl border border-gray-200 bg-gray-50 px-4 py-3 dark:border-gray-700 dark:bg-gray-900">
            <SearchIcon className="h-5 w-5 text-gray-500 dark:text-gray-400" />
            <input
              id="header-command-search"
              ref={inputRef}
              value={query}
              onChange={(event) => setQuery(event.target.value)}
              onKeyDown={(event) => {
                if (event.key === 'ArrowDown') {
                  event.preventDefault()
                  setActiveIndex((index) => Math.min(index + 1, filteredItems.length - 1))
                }
                if (event.key === 'ArrowUp') {
                  event.preventDefault()
                  setActiveIndex((index) => Math.max(index - 1, 0))
                }
                if (event.key === 'Enter') {
                  event.preventDefault()
                  const activeItem = filteredItems[activeIndex]
                  if (activeItem) void handleSelect(activeItem)
                }
              }}
              placeholder={mode === 'expert' ? 'Search tx / addr / block / tool' : 'Search pages, tools, tokens, and routes'}
              className="w-full border-0 bg-transparent text-sm text-gray-900 placeholder:text-gray-500 focus:outline-none dark:text-white dark:placeholder:text-gray-400"
            />
            <kbd className="rounded-lg border border-gray-200 px-2 py-1 text-[11px] font-medium uppercase tracking-wide text-gray-500 dark:border-gray-700 dark:text-gray-400">
              Esc
            </kbd>
          </div>
          <Explain>
            <p className="mt-3 text-xs leading-5 text-gray-500 dark:text-gray-400">
              Search destinations and run high-frequency header actions from one keyboard-first surface.
            </p>
          </Explain>
        </div>

        <div className="max-h-[60vh] overflow-y-auto p-3">
          <div className="grid gap-1.5">
            {filteredItems.map((item, index) => (
              <button
                key={`${item.section}-${item.label}-${item.href || item.label}`}
                ref={(node) => {
                  itemRefs.current[index] = node
                }}
                type="button"
                onMouseEnter={() => setActiveIndex(index)}
                onClick={() => void handleSelect(item)}
                className={[
                  'flex w-full items-start gap-3 rounded-2xl px-4 py-3 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500',
                  activeIndex === index
                    ? 'bg-primary-50 text-primary-900 dark:bg-primary-500/10 dark:text-primary-100'
                    : 'bg-white text-gray-800 hover:bg-gray-100 dark:bg-gray-950 dark:text-gray-100 dark:hover:bg-gray-900',
                ].join(' ')}
              >
                <span className="mt-0.5 inline-flex rounded-lg border border-gray-200 px-2 py-1 text-[11px] font-semibold uppercase tracking-wide text-gray-500 dark:border-gray-700 dark:text-gray-400">
                  {item.section}
                </span>
                <span className="min-w-0">
                  <span className="block font-semibold">{item.label}</span>
                  {mode === 'guided' && item.description ? (
                    <span className="mt-0.5 block text-xs leading-5 text-gray-500 dark:text-gray-400">
                      {item.description}
                    </span>
                  ) : null}
                </span>
              </button>
            ))}
          </div>
        </div>
        <div className="border-t border-gray-200 px-5 py-3 text-[11px] uppercase tracking-[0.16em] text-gray-500 dark:border-gray-800 dark:text-gray-400">
          {mode === 'expert' ? 'Keyboard-first ' : 'Use '}
          <kbd className="rounded border border-gray-200 px-1.5 py-0.5 font-medium dark:border-gray-700">/</kbd> or{' '}
          <kbd className="rounded border border-gray-200 px-1.5 py-0.5 font-medium dark:border-gray-700">Ctrl/Cmd + K</kbd>{' '}
          {mode === 'expert' ? 'to reopen.' : 'to reopen this palette.'}
        </div>
      </div>
      <button
        type="button"
        onClick={onClose}
        aria-label="Close command palette"
        className="fixed inset-0 -z-10 cursor-default"
      />
    </div>
  )
}
