'use client'

import { useState, useEffect, useMemo, useRef, useCallback } from 'react'
import { motion, AnimatePresence } from 'motion/react'
import {
  Search,
  ChevronLeft,
  ChevronRight,
  X,
  CornerDownRight,
  Folder,
  HelpCircle,
  Command,
  FileText,
  Sparkles,
  Loader2,
} from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useNotebooks } from '@/context/notebooks-context'
import { useLanguage } from '@/lib/i18n'
import type { Note } from '@/lib/types'

interface SearchMatch {
  id: string
  noteId: string
  noteTitle: string
  path: string
  type: 'document' | 'heading' | 'paragraph' | 'list'
  headingLevel?: number
  text: string
  matchedText: string
  lineIndex: number
}

interface SearchModalProps {
  isOpen: boolean
  onClose: () => void
}

/** Strip HTML tags and decode basic entities for plain-text matching */
function stripHtml(html: string): string {
  return html
    .replace(/<[^>]+>/g, ' ')
    .replace(/&amp;/g, '&')
    .replace(/&lt;/g, '<')
    .replace(/&gt;/g, '>')
    .replace(/&quot;/g, '"')
    .replace(/&#39;/g, "'")
    .replace(/&nbsp;/g, ' ')
    .replace(/\s{2,}/g, ' ')
    .trim()
}

/** Safe RegExp escape */
function escapeRegExp(s: string) {
  return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
}

export function SearchModal({ isOpen, onClose }: SearchModalProps) {
  const router = useRouter()
  const { notebooks } = useNotebooks()
  const { t } = useLanguage()

  const [query, setQuery] = useState('')
  const [useRegex, setUseRegex] = useState(false)
  const [caseSensitive, setCaseSensitive] = useState(false)
  const [searchInTrash, setSearchInTrash] = useState(false)
  const [savedQueries, setSavedQueries] = useState<string[]>([])
  const [results, setResults] = useState<Note[]>([])
  const [isLoading, setIsLoading] = useState(false)
  const [overview, setOverview] = useState<string | null>(null)
  const [overviewLoading, setOverviewLoading] = useState(false)
  const [selectedIndex, setSelectedIndex] = useState(0)

  const inputRef = useRef<HTMLInputElement>(null)
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)

  // Load saved queries from localStorage
  useEffect(() => {
    try {
      const stored = localStorage.getItem('momento-search-saved')
      if (stored) setSavedQueries(JSON.parse(stored))
    } catch {}
  }, [])

  // Focus input when opened
  useEffect(() => {
    if (isOpen) {
      setTimeout(() => inputRef.current?.focus(), 50)
      setQuery('')
      setResults([])
      setSelectedIndex(0)
    }
  }, [isOpen])

  // Rebuild notebook path helper
  const getNotebookPath = useCallback(
    (notebookId: string | null | undefined): string => {
      if (!notebookId) return ''
      const segments: string[] = []
      let current = notebooks.find(n => n.id === notebookId)
      while (current) {
        segments.unshift(current.name)
        const parentId = current.parentId
        current = parentId ? notebooks.find(n => n.id === parentId) : undefined
      }
      return segments.join(' / ')
    },
    [notebooks]
  )

  // Fetch notes from API with debounce
  useEffect(() => {
    if (debounceRef.current) clearTimeout(debounceRef.current)

    if (!query.trim()) {
      setResults([])
      setIsLoading(false)
      return
    }

    setIsLoading(true)
    debounceRef.current = setTimeout(async () => {
      try {
        const params = new URLSearchParams({
          search: query.trim(),
          limit: '40',
          ...(searchInTrash ? {} : {}),
        })
        const res = await fetch(`/api/notes?${params}`)
        if (!res.ok) throw new Error('search failed')
        const data = await res.json()
        setResults(data.data ?? [])
      } catch {
        setResults([])
      } finally {
        setIsLoading(false)
      }
    }, 280)

    return () => {
      if (debounceRef.current) clearTimeout(debounceRef.current)
    }
  }, [query, searchInTrash])

  // Fetch AI overview after results load
  useEffect(() => {
    if (!query.trim() || results.length === 0) {
      setOverview(null)
      return
    }
    setOverviewLoading(true)
    const timer = setTimeout(async () => {
      try {
        const topResults = results.slice(0, 5).map(r => ({
          title: r.title || 'Sans titre',
          snippet: r.content?.replace(/<[^>]+>/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 400) || '',
        }))
        const res = await fetch('/api/ai/search-overview', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ query: query.trim(), results: topResults }),
        })
        const data = await res.json()
        setOverview(data.hasRelevantInfo ? data.answer : null)
      } catch {
        setOverview(null)
      } finally {
        setOverviewLoading(false)
      }
    }, 500)

    return () => clearTimeout(timer)
  }, [query, results])

  // Reset selected index when results change
  useEffect(() => {
    setSelectedIndex(0)
  }, [results, query])

  // Build SearchMatch list from results for the left panel
  const filteredMatches = useMemo((): SearchMatch[] => {
    if (!query.trim() || results.length === 0) return []

    const searchRegex = (() => {
      try {
        // BUG FIX: caseSensitive → 'g' (respect casse), insensitive → 'gi'
        const flag = caseSensitive ? 'g' : 'gi'
        const pattern = useRegex ? query : escapeRegExp(query)
        return new RegExp(pattern, flag)
      } catch {
        return null
      }
    })()

    if (!searchRegex) return []

    const matches: SearchMatch[] = []

    results.forEach(note => {
      const notebookPath = getNotebookPath(note.notebookId)
      const fullPath = notebookPath
        ? `${notebookPath} / ${note.title ?? 'Sans titre'}`
        : (note.title ?? 'Sans titre')

      // 1. Title match
      if (note.title && searchRegex.test(note.title)) {
        matches.push({
          id: `${note.id}-title`,
          noteId: note.id,
          noteTitle: note.title ?? 'Sans titre',
          path: fullPath,
          type: 'document',
          text: note.title ?? '',
          matchedText: note.title ?? '',
          lineIndex: -1,
        })
      }

      // 2. Content match — strip HTML, split by lines
      if (note.content) {
        const plainContent = stripHtml(note.content)
        const lines = plainContent.split(/\n|(?<=\.)\s+(?=[A-Z])/)
        lines.forEach((line, index) => {
          const trimmed = line.trim()
          if (!trimmed || trimmed.length < 10) return

          // Reset lastIndex for global regex
          searchRegex.lastIndex = 0
          if (!searchRegex.test(trimmed)) return

          let type: 'heading' | 'paragraph' | 'list' = 'paragraph'
          let headingLevel: number | undefined
          let displayVal = trimmed.slice(0, 120)

          if (/^#{1,6}\s/.test(trimmed)) {
            type = 'heading'
            const m = trimmed.match(/^(#{1,6})\s+(.+)$/)
            if (m) { headingLevel = m[1].length; displayVal = m[2] }
          } else if (/^[-*+]\s+/.test(trimmed) || /^\d+\.\s+/.test(trimmed)) {
            type = 'list'
            displayVal = trimmed.replace(/^[-*+\d.]+\s+/, '').slice(0, 120)
          }

          matches.push({
            id: `${note.id}-line-${index}`,
            noteId: note.id,
            noteTitle: note.title ?? 'Sans titre',
            path: fullPath,
            type,
            headingLevel,
            text: trimmed,
            matchedText: displayVal,
            lineIndex: index,
          })
        })
      }
    })

    return matches.slice(0, 200) // cap pour les perf
  }, [results, query, useRegex, caseSensitive, getNotebookPath])

  // Active match for preview panel
  const activeMatch = filteredMatches[selectedIndex]

  // Count distinct notes in results
  const docMatchesCount = useMemo(() => {
    return new Set(filteredMatches.map(m => m.noteId)).size
  }, [filteredMatches])

  // Preview panel: highlighted context around the matched line
  const highlightedPreview = useMemo(() => {
    if (!activeMatch) return null
    const currentNote = results.find(n => n.id === activeMatch.noteId)
    if (!currentNote) return null
    if (!query.trim()) return <p className="text-xs text-concrete p-2">{stripHtml(currentNote.content).slice(0, 500)}</p>

    try {
      // Fixed flag for preview highlights
      const flag = caseSensitive ? 'g' : 'gi'
      const searchPattern = useRegex ? query : escapeRegExp(query)
      const highlightRegex = new RegExp(`(${searchPattern})`, flag)

      const plainContent = stripHtml(currentNote.content)
      const lines = plainContent.split(/\n|(?<=\.)\s+(?=[A-Z])/).filter(l => l.trim())

      const targetIndex = activeMatch.lineIndex >= 0 ? activeMatch.lineIndex : 0
      const startLine = Math.max(0, targetIndex - 2)
      const endLine = Math.min(lines.length - 1, targetIndex + 6)

      return (
        <div className="space-y-0.5 my-1">
          {startLine > 0 && (
            <div className="text-[10px] text-concrete/40 italic pl-10 py-0.5">…</div>
          )}
          {lines.slice(startLine, endLine + 1).map((line, idx) => {
            const absoluteIdx = startLine + idx
            const isMatchLine = absoluteIdx === targetIndex
            highlightRegex.lastIndex = 0
            const hasMatch = highlightRegex.test(line)
            highlightRegex.lastIndex = 0
            const segments = line.split(highlightRegex)

            return (
              <div
                key={absoluteIdx}
                className={`py-1 px-2 rounded-lg text-xs leading-relaxed flex items-start gap-3 transition-colors ${
                  isMatchLine
                    ? 'bg-blueprint/5 border-l-2 border-blueprint pl-2 dark:bg-blueprint/10'
                    : 'opacity-70'
                }`}
              >
                <span className="font-mono text-[9px] text-concrete/40 text-right w-6 select-none mt-0.5 shrink-0">
                  {absoluteIdx + 1}
                </span>
                <span className="font-sans text-ink dark:text-dark-ink break-words min-w-0">
                  {hasMatch
                    ? segments.map((seg, sIdx) => {
                        highlightRegex.lastIndex = 0
                        const isMatch = highlightRegex.test(seg)
                        return isMatch ? (
                          <mark
                            key={sIdx}
                            className="bg-blueprint/20 text-ink dark:text-white dark:bg-blueprint/30 rounded px-0.5 border-b border-blueprint font-semibold"
                          >
                            {seg}
                          </mark>
                        ) : (
                          seg
                        )
                      })
                    : line}
                </span>
              </div>
            )
          })}
          {endLine < lines.length - 1 && (
            <div className="text-[10px] text-concrete/40 italic pl-10 py-0.5">…</div>
          )}
        </div>
      )
    } catch {
      return <p className="text-xs text-concrete p-2">{stripHtml(currentNote.content).slice(0, 600)}</p>
    }
  }, [activeMatch, results, query, useRegex, caseSensitive])

  // Row highlight renderer
  const renderHighlightedRow = (text: string) => {
    if (!query.trim()) return <span className="truncate">{text}</span>
    try {
      // Fixed: caseSensitive → 'g', insensitive → 'gi'
      const flag = caseSensitive ? 'g' : 'gi'
      const pattern = useRegex ? query : escapeRegExp(query)
      const regex = new RegExp(`(${pattern})`, flag)
      const segments = text.split(regex)
      return (
        <span className="truncate">
          {segments.map((seg, i) => {
            regex.lastIndex = 0
            return regex.test(seg) ? (
              <mark key={i} className="bg-blueprint/25 text-ink dark:text-white dark:bg-blueprint/40 px-0.5 rounded font-bold">
                {seg}
              </mark>
            ) : (
              seg
            )
          })}
        </span>
      )
    } catch {
      return <span className="truncate">{text}</span>
    }
  }

  // Keyboard navigation + focus trap
  const modalRef = useRef<HTMLDivElement>(null)
  useEffect(() => {
    if (!isOpen) return
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') { e.preventDefault(); onClose() }
      else if (e.key === 'Tab' && modalRef.current) {
        const focusable = modalRef.current.querySelectorAll<HTMLElement>('button, a, input, [tabindex]:not([tabindex="-1"])')
        if (focusable.length === 0) return
        const first = focusable[0]
        const last = focusable[focusable.length - 1]
        if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus() }
        else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus() }
      }
      else if (e.key === 'ArrowDown') { e.preventDefault(); setSelectedIndex(p => Math.min(p + 1, filteredMatches.length - 1)) }
      else if (e.key === 'ArrowUp') { e.preventDefault(); setSelectedIndex(p => Math.max(p - 1, 0)) }
      else if (e.key === 'Enter') {
        e.preventDefault()
        if (filteredMatches[selectedIndex]) {
          router.push(`/home?openNote=${filteredMatches[selectedIndex].noteId}`)
          onClose()
        }
      }
    }
    window.addEventListener('keydown', handleKeyDown)
    return () => window.removeEventListener('keydown', handleKeyDown)
  }, [isOpen, selectedIndex, filteredMatches, onClose, router])

  // Save/remove query from localStorage
  const handleSaveQuery = () => {
    if (!query.trim()) return
    setSavedQueries(prev => {
      const next = prev.includes(query.trim()) ? prev : [...prev.slice(-9), query.trim()]
      try { localStorage.setItem('momento-search-saved', JSON.stringify(next)) } catch {}
      return next
    })
  }
  const handleRemoveQuery = () => {
    setSavedQueries(prev => {
      const next = prev.filter(q => q !== query.trim())
      try { localStorage.setItem('momento-search-saved', JSON.stringify(next)) } catch {}
      return next
    })
  }

  if (!isOpen) return null

  return (
    <div
      ref={modalRef}
      className="fixed inset-0 bg-black/40 dark:bg-black/60 backdrop-blur-sm flex items-center justify-center z-[200] p-4 sm:p-6 select-none"
      role="dialog"
      aria-modal="true"
      aria-label={t('searchModal.ariaLabel')}
      onClick={(e) => { if (e.target === e.currentTarget) onClose() }}
    >
      <motion.div
        initial={{ opacity: 0, scale: 0.98, y: 8 }}
        animate={{ opacity: 1, scale: 1, y: 0 }}
        exit={{ opacity: 0, scale: 0.98, y: 8 }}
        transition={{ duration: 0.15 }}
        className="w-full max-w-[860px] h-[580px] sm:h-[640px] rounded-2xl bg-white dark:bg-[#121212] border border-border dark:border-zinc-800 shadow-2xl flex flex-col overflow-hidden"
      >
        {/* Search bar */}
        <div className="p-4 border-b border-border/60 dark:border-zinc-800 bg-paper/50 dark:bg-[#161616] flex flex-col gap-3 shrink-0">
          <div className="flex items-center gap-2.5 relative">
            <Search size={17} className="text-concrete absolute left-3 top-1/2 -translate-y-1/2 shrink-0" />
            <input
              ref={inputRef}
              type="text"
              value={query}
              onChange={e => setQuery(e.target.value)}
              placeholder={t('searchModal.placeholder')}
              className="w-full text-sm pl-10 pr-28 py-2.5 rounded-xl border border-border/70 dark:border-zinc-800 bg-white/85 dark:bg-[#1C1C1C] text-ink dark:text-dark-ink placeholder-concrete/50 outline-none focus:border-blueprint transition-colors"
            />
            <div className="absolute right-3 top-1/2 -translate-y-1/2 flex items-center gap-1">
              <button
                onClick={() => setCaseSensitive(c => !c)}
                title={t('searchModal.caseSensitive')}
                className={`px-1.5 py-1 text-[9.5px] font-bold rounded-md transition-colors select-none ${
                  caseSensitive ? 'text-blueprint bg-blueprint/8' : 'text-concrete hover:bg-black/5 dark:hover:bg-white/5'
                }`}
              >
                Aa
              </button>
              <button
                onClick={() => setUseRegex(r => !r)}
                title={t('searchModal.regexMode')}
                className={`px-1.5 py-1 text-[9.5px] font-bold rounded-md transition-colors select-none ${
                  useRegex ? 'text-blueprint bg-blueprint/8' : 'text-concrete hover:bg-black/5 dark:hover:bg-white/5'
                }`}
              >
                .*
              </button>
              <button onClick={onClose} className="p-1 hover:bg-black/5 dark:hover:bg-white/10 rounded-md text-concrete transition-all">
                <X size={14} />
              </button>
            </div>
          </div>

          {/* Saved queries */}
          {savedQueries.length > 0 && (
            <div className="flex items-center gap-2 text-[10px] text-concrete">
              <span className="uppercase text-[9px] font-bold">{t('searchModal.favorites')}</span>
              <div className="flex flex-wrap gap-1.5">
                {savedQueries.map(sq => (
                  <button
                    key={sq}
                    onClick={() => setQuery(sq)}
                    className={`px-2 py-0.5 rounded-md border text-[9.5px] font-medium transition-all hover:border-blueprint ${
                      query === sq
                        ? 'bg-blueprint/10 border-blueprint text-blueprint'
                        : 'bg-white dark:bg-zinc-800 border-border/40 text-concrete'
                    }`}
                  >
                    {sq}
                  </button>
                ))}
              </div>
            </div>
          )}
        </div>

        {/* Status bar */}
        <div className="px-4 py-2 bg-[#F8F7F4] dark:bg-[#141414] border-b border-border/40 dark:border-zinc-800 flex items-center justify-between shrink-0">
          <div className="flex items-center gap-3">
            <div className="flex items-center gap-0.5 border border-border/40 dark:border-zinc-800 bg-white dark:bg-zinc-900 rounded-lg p-0.5">
              <button
                disabled={filteredMatches.length === 0}
                onClick={() => setSelectedIndex(p => Math.max(0, p - 1))}
                className="p-1 hover:bg-black/5 dark:hover:bg-white/5 rounded text-concrete disabled:opacity-40 transition-colors"
              >
                <ChevronLeft size={12} />
              </button>
              <span className="text-[9.5px] font-bold font-mono px-1.5 text-concrete">
                {filteredMatches.length > 0 ? `${selectedIndex + 1}/${filteredMatches.length}` : '—'}
              </span>
              <button
                disabled={filteredMatches.length === 0}
                onClick={() => setSelectedIndex(p => Math.min(filteredMatches.length - 1, p + 1))}
                className="p-1 hover:bg-black/5 dark:hover:bg-white/5 rounded text-concrete disabled:opacity-40 transition-colors"
              >
                <ChevronRight size={12} />
              </button>
            </div>
            <span className="text-[11px] font-medium text-concrete">
              {isLoading
                ? t('searchModal.searching')
                : filteredMatches.length > 0
                  ? `${filteredMatches.length} occurrence${filteredMatches.length > 1 ? 's' : ''} dans ${docMatchesCount} note${docMatchesCount > 1 ? 's' : ''}`
                  : query.trim()
                    ? t('searchModal.noResults')
                    : t('searchModal.typeToSearch')}
            </span>
          </div>
          <div className="flex items-center gap-4">
            {query.trim() && (
              <button
                onClick={savedQueries.includes(query.trim()) ? handleRemoveQuery : handleSaveQuery}
                className="text-[10px] font-bold uppercase tracking-wider text-blueprint border-b border-dashed border-blueprint hover:border-solid"
              >
                {savedQueries.includes(query.trim()) ? 'Retirer favori' : 'Sauvegarder'}
              </button>
            )}
            <label className="flex items-center gap-1.5 cursor-pointer text-[10.5px] font-medium text-concrete">
              <input
                type="checkbox"
                checked={searchInTrash}
                onChange={e => setSearchInTrash(e.target.checked)}
                className="rounded border-border/60 text-blueprint focus:ring-blueprint w-3 h-3"
              />
              <span>{t('searchModal.trashIncluded')}</span>
            </label>
          </div>
        </div>

        {/* Dual panel */}
        <div className="flex-1 flex overflow-hidden">
          {/* Left — results list */}
          <div className="w-[45%] h-full border-r border-border/40 dark:border-zinc-800 flex flex-col bg-[#FAF9F5]/30 dark:bg-[#121212]/30 overflow-hidden">
            <div className="flex-1 overflow-y-auto p-2 space-y-1">
              {/* AI Overview */}
              {(overviewLoading || overview) && (
                <div className="mb-2 rounded-xl border border-brand-accent/20 bg-brand-accent/[0.03] p-3" dir="auto">
                  <div className="flex items-center gap-1.5 mb-1.5">
                    <Sparkles size={12} className="text-brand-accent" />
                    <span className="text-[9px] font-bold uppercase tracking-widest text-brand-accent">
                      {overviewLoading ? t('searchModal.aiAnalysis') : t('searchModal.aiResponse')}
                    </span>
                  </div>
                  {overviewLoading ? (
                    <div className="flex items-center gap-2">
                      <Loader2 size={12} className="animate-spin text-brand-accent" />
                      <span className="text-[11px] text-muted-foreground">{t('searchModal.resultsSummary')}</span>
                    </div>
                  ) : (
                    <p className="text-[12px] leading-relaxed text-foreground/80">{overview}</p>
                  )}
                </div>
              )}
              {filteredMatches.map((m, idx) => {
                const isSelected = idx === selectedIndex
                return (
                  <div
                    key={m.id}
                    onClick={() => setSelectedIndex(idx)}
                    onDoubleClick={() => {
                      router.push(`/home?openNote=${m.noteId}`)
                      onClose()
                    }}
                    className={`p-2.5 rounded-xl cursor-pointer text-left select-none relative flex flex-col gap-1 border transition-all ${
                      isSelected
                        ? 'bg-white dark:bg-zinc-800 shadow-sm border-blueprint/25'
                        : 'border-transparent hover:bg-black/[0.02] dark:hover:bg-white/[0.02]'
                    }`}
                  >
                    {isSelected && (
                      <div className="absolute left-0 top-1/2 -translate-y-1/2 w-1 h-3.5 bg-blueprint rounded-r-full" />
                    )}
                    <div className="flex items-center gap-1.5 min-w-0">
                      {m.type === 'document' && <FileText size={12} className="text-sky-500 shrink-0" />}
                      {m.type === 'heading' && (
                        <span className="text-[8px] font-extrabold uppercase bg-indigo-50 dark:bg-indigo-950/40 text-indigo-500 border border-indigo-200 dark:border-indigo-900 px-1 rounded-sm shrink-0 font-mono">
                          H{m.headingLevel ?? ''}
                        </span>
                      )}
                      {m.type === 'list' && (
                        <span className="text-[8px] font-extrabold uppercase bg-emerald-50 dark:bg-emerald-950/40 text-emerald-600 border border-emerald-200 dark:border-emerald-900 px-1 rounded-sm shrink-0 font-mono">
                          LIST
                        </span>
                      )}
                      {m.type === 'paragraph' && (
                        <span className="text-[8px] font-extrabold uppercase bg-zinc-100 dark:bg-zinc-800 text-concrete border border-border/20 px-1 rounded-sm shrink-0 font-mono">
                          TXT
                        </span>
                      )}
                      <span className={`font-semibold truncate text-xs ${isSelected ? 'text-ink dark:text-dark-ink' : 'text-muted-foreground'}`}>
                        {m.noteTitle}
                      </span>
                    </div>
                    <div className="text-[11px] text-concrete truncate pl-5 font-sans leading-tight">
                      {renderHighlightedRow(m.matchedText)}
                    </div>
                    <div className="text-[8.5px] font-mono tracking-widest uppercase text-concrete/45 truncate pl-5 mt-0.5">
                      {m.path}
                    </div>
                  </div>
                )
              })}

              {!isLoading && filteredMatches.length === 0 && (
                <div className="h-full flex flex-col items-center justify-center text-center p-6 text-concrete pt-24 space-y-2">
                  <Search size={20} className="opacity-30 animate-pulse" />
                  <p className="text-[11px] font-medium italic opacity-70">
                    {query.trim() ? t('searchModal.noMatch') : t('searchModal.typeForResults')}
                  </p>
                </div>
              )}

              {isLoading && (
                <div className="h-full flex items-center justify-center text-concrete pt-24">
                  <div className="w-4 h-4 border-2 border-blueprint/30 border-t-blueprint rounded-full animate-spin" />
                </div>
              )}
            </div>
          </div>

          {/* Right — preview panel */}
          <div className="flex-1 h-full bg-[#FCFCFA]/80 dark:bg-[#151515] flex flex-col overflow-hidden">
            {activeMatch ? (
              <div className="flex-1 flex flex-col p-5 overflow-hidden">
                <div className="space-y-3 overflow-hidden flex flex-col flex-1">
                  <div className="flex items-center gap-1.5 p-2 bg-black/[0.02] dark:bg-white/[0.02] border border-border/40 rounded-xl">
                    <Folder size={11} className="text-concrete shrink-0" />
                    <span className="text-[9.5px] font-mono tracking-widest text-concrete font-medium uppercase truncate">
                      {activeMatch.path}
                    </span>
                  </div>

                  <div className="border-b border-border/40 dark:border-zinc-800 pb-2">
                    <h4 className="text-[13px] font-serif font-bold text-ink dark:text-dark-ink">
                      {activeMatch.noteTitle}
                    </h4>
                    <p className="text-[8px] uppercase tracking-wider text-concrete font-bold mt-0.5">
                      {t('searchModal.documentPreview')}
                    </p>
                  </div>

                  <div className="flex-1 overflow-y-auto bg-white dark:bg-[#121212] border border-border/30 dark:border-zinc-800 rounded-xl p-3.5 shadow-inner min-h-0">
                    {highlightedPreview}
                  </div>
                </div>

                <div className="pt-4 border-t border-border/40 dark:border-zinc-800 flex items-center justify-between shrink-0 mt-3">
                  <button
                    onClick={() => {
                      router.push(`/home?openNote=${activeMatch.noteId}`)
                      onClose()
                    }}
                    className="px-5 py-2.5 bg-ink text-white dark:bg-white dark:text-black hover:opacity-90 text-xs font-semibold rounded-xl flex items-center gap-2 transition-all shadow-sm"
                  >
                    <CornerDownRight size={13} />
                    <span>{t('searchModal.openInEditor')}</span>
                  </button>
                  <span className="text-[10px] text-concrete font-bold font-mono bg-paper dark:bg-white/5 border border-border/30 px-2 py-1 rounded">
                    ID: {activeMatch.noteId.slice(0, 8)}…
                  </span>
                </div>
              </div>
            ) : (
              <div className="flex-1 flex flex-col items-center justify-center text-center p-6 text-concrete space-y-3">
                <HelpCircle size={24} className="opacity-25" />
                <div className="space-y-1">
                  <p className="text-[11.5px] font-bold">{t('searchModal.documentPreview')}</p>
                  <p className="text-[10px] italic opacity-60">
                    {t('searchModal.selectResultToPreview')}
                  </p>
                </div>
              </div>
            )}
          </div>
        </div>

        {/* Footer keyboard hints */}
        <div className="p-3 bg-[#FAF9F5] dark:bg-[#0E0E0E] border-t border-border/50 dark:border-zinc-800 flex items-center justify-between shrink-0">
          <div className="flex items-center gap-5 text-[9.5px] font-bold text-concrete/70">
            <span className="flex items-center gap-1.5">
              <kbd className="bg-slate-200 dark:bg-zinc-800 px-1 py-0.5 rounded text-ink dark:text-white text-[9px]">↑↓</kbd>
              {t('searchModal.hintNavigate')}
            </span>
            <span className="flex items-center gap-1.5">
              <kbd className="bg-slate-200 dark:bg-zinc-800 px-1 py-0.5 rounded text-ink dark:text-white text-[9px]">Entrée</kbd>
              {t('searchModal.hintOpen')}
            </span>
            <span className="flex items-center gap-1.5">
              <kbd className="bg-slate-200 dark:bg-zinc-800 px-1 py-0.5 rounded text-ink dark:text-white text-[9px]">Échap</kbd>
              {t('searchModal.hintClose')}
            </span>
          </div>
          <div className="flex items-center gap-1.5 text-[9px] font-bold uppercase tracking-wider text-concrete/50">
            <Command size={10} />
            <span>{t('searchModal.title')}</span>
          </div>
        </div>
      </motion.div>
    </div>
  )
}
