'use client'

/**
 * MarkdownSlashCommands
 * Detects "/" typed in a textarea and shows a floating command palette.
 * Supports keyboard navigation (↑↓ Enter Esc) and replaces the "/cmd" text
 * with the appropriate markdown syntax.
 */

import { useEffect, useRef, useState, useCallback } from 'react'
import { createPortal } from 'react-dom'
import {
  Heading1, Heading2, Heading3, List, ListOrdered,
  CheckSquare, Quote, Code, Minus, Bold, Italic,
  Pilcrow, Link as LinkIcon,
} from 'lucide-react'
import { cn } from '@/lib/utils'
import { useLanguage } from '@/lib/i18n'

type SlashCmd = {
  title: string
  desc: string
  icon: typeof Heading1
  keywords: string[]
  insert: string
  cursorOffset?: number // chars from end where cursor lands
}

const COMMANDS: SlashCmd[] = [
  { title: 'Texte', desc: 'Paragraphe normal', icon: Pilcrow, keywords: ['text', 'texte', 'p'], insert: '' },
  { title: 'Titre 1', desc: 'Grand titre de section', icon: Heading1, keywords: ['h1', '1', 'heading', 'titre'], insert: '# ' },
  { title: 'Titre 2', desc: 'Titre de niveau 2', icon: Heading2, keywords: ['h2', '2', 'titre'], insert: '## ' },
  { title: 'Titre 3', desc: 'Titre de niveau 3', icon: Heading3, keywords: ['h3', '3', 'titre'], insert: '### ' },
  { title: 'Liste à puces', desc: 'Liste non ordonnée', icon: List, keywords: ['list', 'liste', 'ul', 'bullet', '-'], insert: '- ' },
  { title: 'Liste numérotée', desc: 'Liste ordonnée', icon: ListOrdered, keywords: ['ol', 'numbered', 'numéro', '1.'], insert: '1. ' },
  { title: 'Tâche (to-do)', desc: 'Case à cocher', icon: CheckSquare, keywords: ['todo', 'tache', 'task', 'checkbox', '[]'], insert: '- [ ] ' },
  { title: 'Citation', desc: 'Bloc de citation', icon: Quote, keywords: ['quote', 'citation', 'blockquote', '>'], insert: '> ' },
  { title: 'Bloc de code', desc: 'Snippet de code', icon: Code, keywords: ['code', 'block', '```'], insert: '```\n', cursorOffset: 4 },
  { title: 'Séparateur', desc: 'Ligne horizontale', icon: Minus, keywords: ['hr', 'divider', 'separator', '---'], insert: '---\n' },
  { title: 'Gras', desc: '**texte en gras**', icon: Bold, keywords: ['bold', 'gras', '**'], insert: '****', cursorOffset: 2 },
  { title: 'Italique', desc: '*texte en italique*', icon: Italic, keywords: ['italic', 'italique', '*'], insert: '**', cursorOffset: 1 },
  { title: 'Lien', desc: '[texte](url)', icon: LinkIcon, keywords: ['link', 'lien', 'url'], insert: '[]()', cursorOffset: 3 },
]

interface MarkdownSlashCommandsProps {
  textareaRef: React.RefObject<HTMLTextAreaElement>
  value: string
  onChange: (value: string) => void
}

export function MarkdownSlashCommands({ textareaRef, value, onChange }: MarkdownSlashCommandsProps) {
  const { t } = useLanguage()
  const [open, setOpen] = useState(false)
  const [query, setQuery] = useState('')
  const [selectedIndex, setSelectedIndex] = useState(0)
  const [coords, setCoords] = useState({ top: 0, left: 0 })
  const slashPosRef = useRef<number>(-1)
  const menuRef = useRef<HTMLDivElement>(null)

  const filtered = COMMANDS.filter(cmd => {
    if (!query) return true
    const q = query.toLowerCase()
    return cmd.keywords.some(k => k.includes(q)) || cmd.title.toLowerCase().includes(q)
  })

  const close = useCallback(() => {
    setOpen(false)
    setQuery('')
    setSelectedIndex(0)
    slashPosRef.current = -1
  }, [])

  const getCaretCoords = useCallback(() => {
    const el = textareaRef.current
    if (!el) return { top: 0, left: 0 }
    const rect = el.getBoundingClientRect()
    // Approximate caret position using a mirror div
    const mirror = document.createElement('div')
    const style = window.getComputedStyle(el)
    ;['font', 'fontSize', 'fontFamily', 'fontWeight', 'lineHeight',
      'paddingTop', 'paddingLeft', 'paddingRight', 'borderTop', 'borderLeft',
      'whiteSpace', 'wordWrap', 'overflowWrap'].forEach(p => {
      (mirror.style as any)[p] = (style as any)[p]
    })
    mirror.style.position = 'absolute'
    mirror.style.visibility = 'hidden'
    mirror.style.width = `${el.offsetWidth}px`
    mirror.style.top = '0'
    mirror.style.left = '0'
    document.body.appendChild(mirror)
    const textBefore = el.value.substring(0, el.selectionStart ?? 0)
    mirror.textContent = textBefore
    const span = document.createElement('span')
    span.textContent = '|'
    mirror.appendChild(span)
    const spanRect = span.getBoundingClientRect()
    document.body.removeChild(mirror)
    return {
      top: rect.top + el.scrollTop + spanRect.top - mirror.getBoundingClientRect().top + span.offsetHeight + 8,
      left: Math.min(rect.left + spanRect.left - mirror.getBoundingClientRect().left, rect.right - 240),
    }
  }, [textareaRef])

  const applyCommand = useCallback((cmd: SlashCmd) => {
    const el = textareaRef.current
    if (!el || slashPosRef.current < 0) { close(); return }

    const cursorPos = el.selectionStart ?? 0
    const before = value.substring(0, slashPosRef.current)
    const after = value.substring(cursorPos)

    if (cmd.insert === '') {
      // "Text" — just remove the slash
      const newVal = before + after
      onChange(newVal)
      setTimeout(() => {
        el.focus()
        const pos = slashPosRef.current
        el.setSelectionRange(pos, pos)
      }, 0)
    } else {
      const newVal = before + cmd.insert + after
      onChange(newVal)
      setTimeout(() => {
        el.focus()
        const offset = cmd.cursorOffset ?? 0
        const pos = slashPosRef.current + cmd.insert.length - offset
        el.setSelectionRange(pos, pos)
      }, 0)
    }
    close()
  }, [value, onChange, close, textareaRef])

  // Monitor textarea input
  useEffect(() => {
    const el = textareaRef.current
    if (!el) return

    const handleInput = () => {
      const pos = el.selectionStart ?? 0
      const text = el.value
      // Look for "/" at start of word
      const lineStart = text.lastIndexOf('\n', pos - 1) + 1
      const lineText = text.substring(lineStart, pos)
      const slashMatch = lineText.match(/\/(\S*)$/)

      if (slashMatch) {
        slashPosRef.current = pos - slashMatch[0].length
        setQuery(slashMatch[1])
        setSelectedIndex(0)
        setOpen(true)
        const c = getCaretCoords()
        setCoords(c)
      } else {
        if (open) close()
      }
    }

    el.addEventListener('input', handleInput)
    return () => el.removeEventListener('input', handleInput)
  }, [textareaRef, open, close, getCaretCoords])

  // Keyboard navigation
  useEffect(() => {
    if (!open) return
    const handleKey = (e: KeyboardEvent) => {
      if (e.key === 'ArrowDown') { e.preventDefault(); setSelectedIndex(i => (i + 1) % filtered.length) }
      else if (e.key === 'ArrowUp') { e.preventDefault(); setSelectedIndex(i => (i - 1 + filtered.length) % filtered.length) }
      else if (e.key === 'Enter') { e.preventDefault(); if (filtered[selectedIndex]) applyCommand(filtered[selectedIndex]) }
      else if (e.key === 'Escape') { e.preventDefault(); close() }
    }
    document.addEventListener('keydown', handleKey, true)
    return () => document.removeEventListener('keydown', handleKey, true)
  }, [open, filtered, selectedIndex, applyCommand, close])

  // Close on outside click
  useEffect(() => {
    if (!open) return
    const handleClick = (e: MouseEvent) => {
      if (menuRef.current && !menuRef.current.contains(e.target as Node)) close()
    }
    document.addEventListener('mousedown', handleClick)
    return () => document.removeEventListener('mousedown', handleClick)
  }, [open, close])

  if (!open || filtered.length === 0) return null
  if (typeof document === 'undefined') return null

  return createPortal(
    <div
      ref={menuRef}
      style={{ position: 'fixed', top: coords.top, left: coords.left, zIndex: 9999 }}
      className="w-60 bg-card border border-border rounded-xl shadow-xl overflow-hidden"
    >
      <div className="px-3 py-2 border-b border-border/40">
        <p className="text-[10px] uppercase tracking-widest text-muted-foreground font-bold">
          {t('richTextEditor.slashHint') || 'Commandes Markdown'}
        </p>
      </div>
      <div className="max-h-64 overflow-y-auto py-1">
        {filtered.map((cmd, idx) => (
          <button
            key={cmd.title}
            className={cn(
              'w-full flex items-center gap-2.5 px-3 py-2 text-left transition-colors',
              idx === selectedIndex ? 'bg-muted text-foreground' : 'text-muted-foreground hover:bg-muted/50 hover:text-foreground'
            )}
            onMouseDown={e => { e.preventDefault(); applyCommand(cmd) }}
            onMouseEnter={() => setSelectedIndex(idx)}
          >
            <div className="w-7 h-7 rounded-lg border border-border bg-background flex items-center justify-center shrink-0">
              <cmd.icon className="w-3.5 h-3.5" />
            </div>
            <div className="min-w-0">
              <p className="text-[12px] font-medium leading-none truncate">{cmd.title}</p>
              <p className="text-[10px] text-muted-foreground/70 mt-0.5 truncate">{cmd.desc}</p>
            </div>
          </button>
        ))}
      </div>
    </div>,
    document.body
  )
}
