import React, { useMemo, useState, useRef, useEffect, useCallback } from 'react'

function normId(id) {
  return String(id)
}

/**
 * Mehrfachauswahl mit Typahead-Vorschlägen und optionaler Vollliste (Dropdown).
 * Auswahl mehrerer Einträge wird als ODER interpretiert (Aufrufer/API).
 */
export default function MultiSelectCombo({
  value = [],
  onChange,
  options = [],
  placeholder = 'Tippen und Eintrag wählen…',
  browseLabel = '▼ Alle',
  emptyHint = 'Keine Treffer',
  idKey = 'id',
  labelKey = 'label',
  className = '',
}) {
  const [query, setQuery] = useState('')
  const [open, setOpen] = useState(false)
  const [browseAll, setBrowseAll] = useState(false)
  const [highlight, setHighlight] = useState(0)
  const rootRef = useRef(null)

  const rows = useMemo(() => {
    return options.map((o) => ({
      id: o[idKey],
      label: typeof o[labelKey] === 'function' ? o[labelKey](o) : String(o[labelKey] ?? ''),
    }))
  }, [options, idKey, labelKey])

  const selectedSet = useMemo(() => new Set(value.map(normId)), [value])

  const selectedLabels = useMemo(() => {
    return value.map((id) => {
      const r = rows.find((x) => normId(x.id) === normId(id))
      return r ? r.label : `#${id}`
    })
  }, [value, rows])

  const suggestions = useMemo(() => {
    const avail = rows.filter((r) => !selectedSet.has(normId(r.id)))
    if (browseAll || !query.trim()) return avail
    const q = query.trim().toLowerCase()
    return avail.filter((r) => r.label.toLowerCase().includes(q) || normId(r.id).includes(q))
  }, [rows, selectedSet, query, browseAll])

  useEffect(() => {
    setHighlight(0)
  }, [suggestions.length, query, browseAll])

  const addId = useCallback(
    (id) => {
      const sid = normId(id)
      if (selectedSet.has(sid)) return
      onChange([...value, id])
      setQuery('')
      setBrowseAll(false)
    },
    [value, onChange, selectedSet]
  )

  const removeAt = useCallback(
    (idx) => {
      const next = value.filter((_, i) => i !== idx)
      onChange(next)
    },
    [value, onChange]
  )

  useEffect(() => {
    const onDoc = (e) => {
      if (!rootRef.current?.contains(e.target)) {
        setOpen(false)
        setBrowseAll(false)
      }
    }
    document.addEventListener('mousedown', onDoc)
    return () => document.removeEventListener('mousedown', onDoc)
  }, [])

  const onKeyDown = (e) => {
    if (!open && (e.key === 'ArrowDown' || e.key === 'Enter')) {
      setOpen(true)
      return
    }
    if (!open) return
    if (e.key === 'Escape') {
      setOpen(false)
      setBrowseAll(false)
      return
    }
    if (e.key === 'ArrowDown') {
      e.preventDefault()
      setHighlight((h) => Math.min(h + 1, Math.max(0, suggestions.length - 1)))
    }
    if (e.key === 'ArrowUp') {
      e.preventDefault()
      setHighlight((h) => Math.max(0, h - 1))
    }
    if (e.key === 'Enter' && suggestions[highlight]) {
      e.preventDefault()
      addId(suggestions[highlight].id)
    }
  }

  return (
    <div className={`multiselect-combo ${className}`} ref={rootRef}>
      <div className="multiselect-combo__chips">
        {value.map((id, idx) => (
          <button
            key={`${normId(id)}-${idx}`}
            type="button"
            className="multiselect-combo__chip"
            onClick={() => removeAt(idx)}
            title="Entfernen"
          >
            <span>{selectedLabels[idx]}</span>
            <span className="multiselect-combo__chip-x" aria-hidden>
              ×
            </span>
          </button>
        ))}
      </div>
      <div className="multiselect-combo__field">
        <input
          type="text"
          className="form-input multiselect-combo__input"
          placeholder={placeholder}
          value={query}
          onChange={(e) => {
            setQuery(e.target.value)
            setOpen(true)
            setBrowseAll(false)
          }}
          onFocus={() => setOpen(true)}
          onKeyDown={onKeyDown}
          autoComplete="off"
          aria-autocomplete="list"
          aria-expanded={open}
        />
        <button
          type="button"
          className="btn multiselect-combo__browse"
          title="Alle Einträge anzeigen"
          onClick={() => {
            setOpen(true)
            setBrowseAll(true)
            setQuery('')
          }}
        >
          {browseLabel}
        </button>
      </div>
      {open && (
        <ul className="multiselect-combo__list" role="listbox">
          {suggestions.length === 0 ? (
            <li className="multiselect-combo__empty">{emptyHint}</li>
          ) : (
            suggestions.map((r, i) => (
              <li key={normId(r.id)}>
                <button
                  type="button"
                  role="option"
                  aria-selected={i === highlight}
                  className={`multiselect-combo__opt${i === highlight ? ' multiselect-combo__opt--hi' : ''}`}
                  onMouseEnter={() => setHighlight(i)}
                  onMouseDown={(e) => e.preventDefault()}
                  onClick={() => addId(r.id)}
                >
                  {r.label}
                </button>
              </li>
            ))
          )}
        </ul>
      )}
    </div>
  )
}
