// frontend/src/components/ui/HeaderSearch.jsx
// Global search bar for the top header.
// Debounces 500ms → GET /api/search?q= → floating results panel.

import { useState, useEffect, useRef, useCallback } from 'react'
import { useNavigate } from 'react-router-dom'
import api from '@/lib/api'

import IcoDevices   from '@/assets/side-menu-icons/devices.svg?react'
import IcoCustomers from '@/assets/side-menu-icons/customers.svg?react'
import IcoProducts  from '@/assets/side-menu-icons/products.svg?react'
import IcoMelodies  from '@/assets/side-menu-icons/melodies.svg?react'

// App Users has no sidebar SVG file — keep inline
function IcoUsers() {
  return (
    <svg width="16" height="16" viewBox="0 0 16 16" fill="none"
      stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"
      aria-hidden="true" focusable="false"
    >
      <circle cx="6" cy="5" r="2.5" />
      <path d="M2 13c0-2.2 1.8-4 4-4" />
      <circle cx="12" cy="7" r="2" />
      <path d="M9.5 13c0-1.65 1.12-3 2.5-3s2.5 1.35 2.5 3" />
    </svg>
  )
}

// ─── Type config ──────────────────────────────────────────────────────────────

const TYPE_META = {
  device:   { label: 'Devices',   accent: 'var(--color-info)',    Icon: IcoDevices   },
  user:     { label: 'Users',     accent: 'var(--color-success)', Icon: IcoUsers     },
  customer: { label: 'Customers', accent: 'var(--color-primary)', Icon: IcoCustomers },
  product:  { label: 'Products',  accent: 'var(--color-warning)', Icon: IcoProducts  },
  melody:   { label: 'Melodies',  accent: '#f0c040',              Icon: IcoMelodies  },
}

// ─── Search / spinner icons ───────────────────────────────────────────────────

function SearchIcon() {
  return (
    <svg width="13" height="13" viewBox="0 0 13 13" fill="none"
      stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round"
      aria-hidden="true" focusable="false"
    >
      <circle cx="5.5" cy="5.5" r="4" />
      <path d="M8.5 8.5L11 11" />
    </svg>
  )
}

function SpinnerIcon() {
  return (
    <svg width="13" height="13" viewBox="0 0 13 13" fill="none"
      stroke="currentColor" strokeWidth="1.7" strokeLinecap="round"
      aria-hidden="true" focusable="false"
      style={{ animation: 'spin 0.7s linear infinite' }}
    >
      <circle cx="6.5" cy="6.5" r="4" strokeOpacity="0.25" />
      <path d="M6.5 2.5a4 4 0 0 1 4 4" />
    </svg>
  )
}

// ─── Result item ──────────────────────────────────────────────────────────────

function ResultItem({ result, isActive, onMouseEnter, onMouseLeave, onClick }) {
  const meta = TYPE_META[result.type] || { label: result.type, accent: 'var(--color-text-muted)', Icon: null }
  const { Icon, accent } = meta

  return (
    <button
      type="button"
      className={`gs-result-item${isActive ? ' gs-result-item--active' : ''}`}
      style={{ '--gs-accent': accent }}
      onMouseEnter={onMouseEnter}
      onMouseLeave={onMouseLeave}
      onClick={onClick}
      tabIndex={-1}
    >
      <span
        className="gs-result-icon"
        style={{ color: accent, backgroundColor: `color-mix(in srgb, ${accent} 12%, transparent)` }}
      >
        {Icon && <Icon width="14" height="14" aria-hidden="true" focusable="false" style={{ flexShrink: 0 }} />}
      </span>

      <span className="gs-result-body">
        <span className="gs-result-label">{result.label}</span>
        {result.sublabel && (
          <span className="gs-result-sublabel">{result.sublabel}</span>
        )}
      </span>
    </button>
  )
}

// ─── Main component ───────────────────────────────────────────────────────────

export default function HeaderSearch({ placeholder = 'Search…' }) {
  const [query, setQuery] = useState('')
  const [results, setResults] = useState([])
  const [loading, setLoading] = useState(false)
  const [open, setOpen] = useState(false)
  const [activeIdx, setActiveIdx] = useState(-1)

  const navigate = useNavigate()
  const wrapRef = useRef(null)
  const inputRef = useRef(null)
  const debounceRef = useRef(null)
  const requestIdRef = useRef(0)

  useEffect(() => {
    clearTimeout(debounceRef.current)
    const q = query.trim()
    if (q.length < 2) {
      setResults([])
      setLoading(false)
      setOpen(false)
      setActiveIdx(-1)
      return
    }
    setLoading(true)
    const reqId = ++requestIdRef.current
    debounceRef.current = setTimeout(async () => {
      try {
        const data = await api.get(`/search?q=${encodeURIComponent(q)}`)
        if (reqId !== requestIdRef.current) return
        setResults(data.results || [])
        setOpen(true)
        setActiveIdx(-1)
      } catch {
        if (reqId === requestIdRef.current) setResults([])
      } finally {
        if (reqId === requestIdRef.current) setLoading(false)
      }
    }, 500)
    return () => clearTimeout(debounceRef.current)
  }, [query])

  useEffect(() => {
    if (!open) return
    const handler = (e) => {
      if (!wrapRef.current?.contains(e.target)) {
        setOpen(false)
        setActiveIdx(-1)
      }
    }
    document.addEventListener('mousedown', handler)
    return () => document.removeEventListener('mousedown', handler)
  }, [open])

  const navigateTo = useCallback((url) => {
    setOpen(false)
    setQuery('')
    setResults([])
    setActiveIdx(-1)
    navigate(url)
  }, [navigate])

  const handleKeyDown = (e) => {
    if (e.key === 'Escape') {
      setOpen(false)
      setQuery('')
      setActiveIdx(-1)
      return
    }
    if (!open || !results.length) return
    if (e.key === 'ArrowDown') {
      e.preventDefault()
      setActiveIdx((i) => Math.min(i + 1, results.length - 1))
    } else if (e.key === 'ArrowUp') {
      e.preventDefault()
      setActiveIdx((i) => Math.max(i - 1, -1))
    } else if (e.key === 'Enter') {
      e.preventDefault()
      if (activeIdx >= 0 && results[activeIdx]) navigateTo(results[activeIdx].url)
    }
  }

  const grouped = results.reduce((acc, r, i) => {
    if (!acc[r.type]) acc[r.type] = []
    acc[r.type].push({ ...r, _idx: i })
    return acc
  }, {})

  const isEmpty = open && !loading && results.length === 0 && query.trim().length >= 2

  return (
    <div className="v2-topbar-search" ref={wrapRef}>
      <span className="v2-topbar-search-icon">
        {loading ? <SpinnerIcon /> : <SearchIcon />}
      </span>
      <input
        ref={inputRef}
        type="search"
        className="v2-topbar-search-input"
        value={query}
        onChange={(e) => setQuery(e.target.value)}
        onKeyDown={handleKeyDown}
        onFocus={() => { if (results.length > 0) setOpen(true) }}
        placeholder={placeholder}
        aria-label={placeholder}
        autoComplete="off"
        spellCheck={false}
      />

      {(open || isEmpty) && (
        <div className="gs-dropdown" role="listbox">
          {isEmpty ? (
            <div className="gs-empty">
              <span className="gs-empty-icon"><SearchIcon /></span>
              <span>No results for <em>&ldquo;{query.trim()}&rdquo;</em></span>
            </div>
          ) : (
            Object.entries(grouped).map(([type, items], groupIdx) => {
              const meta = TYPE_META[type] || { label: type, accent: 'var(--color-text-muted)' }
              return (
                <div key={type} className="gs-group">
                  {groupIdx > 0 && <div className="gs-divider" />}
                  <div className="gs-group-header" style={{ color: meta.accent }}>
                    {meta.label}
                    <span className="gs-group-count">{items.length}</span>
                  </div>
                  {items.map((r) => (
                    <ResultItem
                      key={`${r.type}-${r.id}`}
                      result={r}
                      isActive={r._idx === activeIdx}
                      onMouseEnter={() => setActiveIdx(r._idx)}
                      onMouseLeave={() => setActiveIdx(-1)}
                      onClick={() => navigateTo(r.url)}
                    />
                  ))}
                </div>
              )
            })
          )}
        </div>
      )}
    </div>
  )
}
