// ============================================================
// autocomplete.jsx — Autocomplete generico client-side (s127)
// ------------------------------------------------------------
// Fratello "data-driven" di PersonaAutocomplete: stessa UX (typeahead +
// barra spaziatrice → tendina piena + X clear + frecce/Invio/Esc) ma su una
// lista di opzioni passata come prop (già nel seed, filtro client-side), per i
// menù a tendina non-persona (progetto, vendor, categoria, tipo doc, sito, …).
//
// Solo-da-lista: non crea valori nuovi (coerente coi <select> sostituiti).
//
// Props:
//  - value: string|null — value selezionato (match su option.value)
//  - onChange(value): callback; su clear riceve `clearValue` (default '')
//  - options: Array<{ value, label, sublabel?, keywords? }>
//  - placeholder?: string
//  - disabled?: boolean
//  - allowClear?: boolean = true (mostra X per azzerare)
//  - clearValue?: any = '' (valore inviato a onChange su clear — mirror del <option value="">)
//  - maxOptions?: number = 200 (cap voci mostrate per perf; le nostre liste sono < 200
//    → "spazio" mostra tutti i valori. Alza solo se una lista supera 200.)
//  - testId?: string (data-testid sull'input)
//
// VINCOLO Babel-in-browser: niente ...rest / {...spread}. JSX semplice ok.
// ============================================================

function acFilterOptions(options, query, max) {
  const list = Array.isArray(options) ? options : [];
  const q = String(query || '').trim().toLowerCase();
  let out;
  if (!q) {
    out = list;
  } else {
    out = list.filter((o) => {
      const hay = (
        (o.label || '') + ' ' + (o.sublabel || '') + ' ' + (o.keywords || '') + ' ' + (o.value || '')
      ).toLowerCase();
      return hay.indexOf(q) !== -1;
    });
  }
  return out.slice(0, Math.max(1, max || 50));
}

function Autocomplete({
  value,
  onChange,
  options = [],
  placeholder = 'Cerca o premi spazio…',
  disabled = false,
  allowClear = true,
  clearValue = '',
  maxOptions = 200,
  testId,
}) {
  const [query, setQuery] = React.useState('');
  const [open, setOpen] = React.useState(false);
  const [highlightIdx, setHighlightIdx] = React.useState(0);
  const containerRef = React.useRef(null);
  const inputRef = React.useRef(null);

  const selected = React.useMemo(() => {
    if (value == null || value === '') return null;
    return (Array.isArray(options) ? options : []).find((o) => o.value === value) || null;
  }, [value, options]);

  const results = React.useMemo(
    () => acFilterOptions(options, open ? query : '', maxOptions),
    [options, query, open, maxOptions],
  );

  React.useEffect(() => {
    function onDocClick(e) {
      // 1) click dentro il container del trigger → niente da fare
      if (containerRef.current && containerRef.current.contains(e.target)) return;
      // 2) click dentro un pannello floating-dropdown (può essere il NOSTRO
      //    panel renderizzato via portal su document.body)
      if (e.target && e.target.closest && e.target.closest('[data-floating-dropdown]')) return;
      // 3) altrove → chiudi
      setOpen(false);
    }
    document.addEventListener('mousedown', onDocClick);
    return () => document.removeEventListener('mousedown', onDocClick);
  }, []);

  function handleSelect(o) {
    onChange?.(o.value);
    setOpen(false);
    setQuery('');
    setHighlightIdx(0);
  }

  function handleClear(e) {
    if (e) e.stopPropagation();
    onChange?.(clearValue);
    setQuery('');
    setOpen(true);
    setTimeout(() => inputRef.current?.focus(), 0);
  }

  function handleKeyDown(e) {
    // Barra spaziatrice su input vuoto → apri come tendina (lista piena), senza
    // digitare lo spazio. Spazi dentro la query restano normali.
    if (e.key === ' ' && !query) {
      e.preventDefault();
      setOpen(true);
      return;
    }
    if (!open) {
      if (e.key === 'ArrowDown' || e.key === 'Enter') setOpen(true);
      return;
    }
    if (e.key === 'ArrowDown') {
      e.preventDefault();
      setHighlightIdx((i) => Math.min(i + 1, results.length - 1));
    } else if (e.key === 'ArrowUp') {
      e.preventDefault();
      setHighlightIdx((i) => Math.max(i - 1, 0));
    } else if (e.key === 'Enter') {
      e.preventDefault();
      const r = results[highlightIdx];
      if (r) handleSelect(r);
    } else if (e.key === 'Escape') {
      setOpen(false);
    }
  }

  const showSelectedChip = selected && !open;

  return (
    <div ref={containerRef} style={{ position: 'relative' }}>
      {showSelectedChip ? (
        <button
          type="button"
          disabled={disabled}
          data-testid={testId}
          onClick={() => {
            if (disabled) return;
            setOpen(true);
            setTimeout(() => inputRef.current?.focus(), 0);
          }}
          style={{
            width: '100%',
            display: 'flex',
            alignItems: 'center',
            gap: 8,
            padding: '6px 8px',
            background: 'var(--bg-1)',
            border: '1px solid var(--line)',
            borderRadius: 4,
            cursor: disabled ? 'not-allowed' : 'pointer',
            textAlign: 'left',
            fontSize: 12,
            color: 'var(--text-0)',
          }}
          aria-label={`Cambia selezione, attuale ${selected.label}`}
        >
          <span style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{selected.label}</div>
            {selected.sublabel && (
              <div style={{ fontSize: 10.5, color: 'var(--text-2)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                <span style={{ fontStyle: 'italic' }}>{selected.sublabel}</span>
              </div>
            )}
          </span>
          {allowClear && !disabled && (
            <span
              role="button"
              tabIndex={0}
              onClick={handleClear}
              onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') handleClear(e); }}
              style={{ color: 'var(--text-2)', padding: 4, cursor: 'pointer' }}
              aria-label="Rimuovi selezione"
            >
              ×
            </span>
          )}
        </button>
      ) : (
        <input
          ref={inputRef}
          type="text"
          value={query}
          disabled={disabled}
          data-testid={testId}
          onChange={(e) => { setQuery(e.target.value); setOpen(true); setHighlightIdx(0); }}
          onFocus={() => setOpen(true)}
          onKeyDown={handleKeyDown}
          placeholder={placeholder}
          autoComplete="off"
          aria-autocomplete="list"
          aria-expanded={open}
          style={{ width: '100%', boxSizing: 'border-box' }}
        />
      )}
      <FloatingDropdown anchorRef={containerRef} open={open} maxHeight={280}>
        {results.length === 0 && (
          <div style={{ padding: '10px 12px', fontSize: 11, color: 'var(--text-2)' }}>
            {query.trim() ? `Nessun risultato per "${query.trim()}"` : 'Nessuna opzione'}
          </div>
        )}
        {results.map((o, i) => (
          <div
            key={(o.value != null ? o.value : '') + '|' + i}
            onMouseDown={(e) => { e.preventDefault(); handleSelect(o); }}
            onMouseEnter={() => setHighlightIdx(i)}
            style={{
              display: 'flex',
              alignItems: 'center',
              gap: 8,
              padding: '6px 10px',
              cursor: 'pointer',
              background: i === highlightIdx ? 'var(--bg-2)' : (o.value === value ? 'var(--accent-soft, var(--bg-2))' : 'transparent'),
              borderBottom: i < results.length - 1 ? '1px solid var(--line)' : 'none',
            }}
          >
            <span style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{o.label}</div>
              {o.sublabel && (
                <div style={{ fontSize: 10.5, color: 'var(--text-2)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                  <span style={{ fontStyle: 'italic' }}>{o.sublabel}</span>
                </div>
              )}
            </span>
          </div>
        ))}
      </FloatingDropdown>
    </div>
  );
}

Object.assign(window, { Autocomplete, acFilterOptions });
