// ============================================================
// persona-autocomplete.jsx — autocomplete server-side per persone
// (FASE 3a.14)
// ------------------------------------------------------------
// Sostituisce i <select value=personaId> nei form Customizing
// (Delegations, BU manager, future: escalation, notifications,
// approval matrix). Vantaggi:
//  - Search su name/email/role server-side via /api/personas?q=
//  - Lista non limitata da quanto carichiamo in __SEED
//  - UX a typeahead invece di dropdown lunga
//  - Avatar initials + ruolo + email visibili nel dropdown
//
// Props:
//  - value: string|null (personaId selezionato)
//  - onChange(id|null): callback selezione/clear
//  - placeholder?: string
//  - disabled?: boolean
//  - excludeIds?: string[] (es. nascondere il "from" nello "to" delegation)
//  - personasFallback?: PersonaDto[] (per risolvere display dello id già
//    selezionato senza fare fetch dedicata; tipicamente seed.PERSONAS)
//  - autoFocus?: boolean
//
// Pattern:
//  - useEffect debounced 200ms su input → fetch /api/personas?q=&limit=N
//    (N=50 a query vuota = "browsing/tendina", N=10 in typeahead) (s125)
//  - barra spaziatrice su input vuoto → apre come menù a tendina con la lista
//    piena (preventDefault, niente spazio digitato); spazi dentro la query OK (s125)
//  - dropdown nasconde se nessun input + nessuna selezione attiva
//  - click su row → onChange(id), input mostra display, dropdown chiusa
//  - tasto X (a destra input) → onChange(null), focus torna in input
// ============================================================

function PersonaAutocomplete({
  value,
  onChange,
  placeholder = 'Cerca persona…',
  disabled = false,
  excludeIds = [],
  personasFallback = [],
  autoFocus = false,
  // Pre-rank morbido (s124): role.id RBAC suggeriti → i candidati affini salgono
  // in cima, anche a query vuota. Mai un filtro: chiunque resta cercabile.
  boostRoleIds = [],
  // HARD filter (s133): role.id RBAC che la persona DEVE avere. Se non vuoto,
  // restringe il pool a quelle persone. Se vuoto, no filter.
  filterRoleIds = [],
}) {
  const [query, setQuery] = React.useState('');
  const [results, setResults] = React.useState([]);
  const [open, setOpen] = React.useState(false);
  const [loading, setLoading] = React.useState(false);
  const [highlightIdx, setHighlightIdx] = React.useState(0);
  const containerRef = React.useRef(null);
  const inputRef = React.useRef(null);
  const debounceRef = React.useRef(null);

  // Risolve display per personaId selezionato.
  const selected = React.useMemo(() => {
    if (!value) return null;
    return personasFallback.find((p) => p.id === value) || null;
  }, [value, personasFallback]);

  // Fetch debounced sull'input.
  React.useEffect(() => {
    if (!open) return;
    if (debounceRef.current) clearTimeout(debounceRef.current);
    setLoading(true);
    debounceRef.current = setTimeout(async () => {
      try {
        const boostParam = boostRoleIds.length
          ? `&boostRoleIds=${encodeURIComponent(boostRoleIds.join(','))}`
          : '';
        // s133 — Hard filter per ruolo di sistema (es. "mostrami solo i Reviewer").
        const filterParam = filterRoleIds.length
          ? `&filterRoleIds=${encodeURIComponent(filterRoleIds.join(','))}`
          : '';
        // Browsing (query vuota, es. aperto con spazio/focus) → lista piena come una
        // tendina; typeahead (query) → top 10. (s125)
        const limit = query.trim() ? 10 : 50;
        const url = `/api/personas?q=${encodeURIComponent(query.trim())}&limit=${limit}${boostParam}${filterParam}`;
        const res = await fetch(url);
        const json = await res.json().catch(() => ({}));
        const data = Array.isArray(json?.data) ? json.data : [];
        const filtered = data.filter((p) => !excludeIds.includes(p.id));
        setResults(filtered);
        setHighlightIdx(0);
      } catch (e) {
        setResults([]);
      } finally {
        setLoading(false);
      }
    }, 200);
    return () => {
      if (debounceRef.current) clearTimeout(debounceRef.current);
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [query, open, excludeIds.join(','), boostRoleIds.join(','), filterRoleIds.join(',')]);

  // Click outside → chiudi dropdown. Considera anche il portale floating
  // (il pannello è renderizzato fuori da containerRef via createPortal).
  React.useEffect(() => {
    function onDocClick(e) {
      if (containerRef.current && containerRef.current.contains(e.target)) return;
      if (e.target && e.target.closest && e.target.closest('[data-floating-dropdown]')) return;
      setOpen(false);
    }
    document.addEventListener('mousedown', onDocClick);
    return () => document.removeEventListener('mousedown', onDocClick);
  }, []);

  React.useEffect(() => {
    if (autoFocus && inputRef.current) inputRef.current.focus();
  }, [autoFocus]);

  function handleSelect(p) {
    onChange?.(p.id);
    setOpen(false);
    setQuery('');
    setResults([]);
  }

  function handleClear(e) {
    e?.stopPropagation();
    onChange?.(null);
    setQuery('');
    setOpen(true);
    if (inputRef.current) inputRef.current.focus();
  }

  function handleKeyDown(e) {
    // Barra spaziatrice su input vuoto → apri come menù a tendina (lista piena),
    // senza digitare lo spazio. Gli spazi DENTRO una query (es. "Mario Rossi")
    // restano normali perché qui interviene solo con query vuota. (s125)
    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);
    }
  }

  // Display: se selezionato e input vuoto → mostra "Mario Rossi · Project Manager"
  // altrimenti mostra l'input testuale per query.
  const showSelectedChip = selected && !open;

  return (
    <div ref={containerRef} style={{ position: 'relative' }}>
      {showSelectedChip ? (
        <button
          type="button"
          disabled={disabled}
          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 persona, attualmente ${selected.name}`}
        >
          <PersonaAvatar persona={selected} />
          <span style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{selected.name}</div>
            <div style={{ fontSize: 10.5, color: 'var(--text-2)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
              <span style={{ fontStyle: 'italic' }}>({selected.role})</span>{selected.email ? ` · ${selected.email}` : ''}
            </div>
          </span>
          {!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}
          onChange={(e) => { setQuery(e.target.value); setOpen(true); }}
          onFocus={() => setOpen(true)}
          onKeyDown={handleKeyDown}
          placeholder={placeholder}
          autoComplete="off"
          aria-autocomplete="list"
          aria-expanded={open}
        />
      )}
      <FloatingDropdown anchorRef={containerRef} open={open} maxHeight={280}>
        {loading && (
          <div style={{ padding: '10px 12px', fontSize: 11, color: 'var(--text-2)' }}>Cercando…</div>
        )}
        {!loading && results.length === 0 && (
          <div style={{ padding: '10px 12px', fontSize: 11, color: 'var(--text-2)' }}>
            {query.trim() ? `Nessun risultato per "${query.trim()}"` : 'Digita per cercare · barra spaziatrice per la lista'}
          </div>
        )}
        {!loading && results.map((p, i) => (
          <div
            key={p.id}
            onMouseDown={(e) => { e.preventDefault(); handleSelect(p); }}
            onMouseEnter={() => setHighlightIdx(i)}
            style={{
              display: 'flex',
              alignItems: 'center',
              gap: 8,
              padding: '6px 10px',
              cursor: 'pointer',
              background: i === highlightIdx ? 'var(--bg-2)' : 'transparent',
              borderBottom: i < results.length - 1 ? '1px solid var(--line)' : 'none',
            }}
          >
            <PersonaAvatar persona={p} />
            <span style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12, fontWeight: 500, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{p.name}</div>
              <div style={{ fontSize: 10.5, color: 'var(--text-2)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                <span style={{ fontStyle: 'italic' }}>({p.role})</span>{p.email ? ` · ${p.email}` : ''}
              </div>
            </span>
          </div>
        ))}
      </FloatingDropdown>
    </div>
  );
}

function PersonaAvatar({ persona }) {
  return (
    <div
      style={{
        width: 28,
        height: 28,
        borderRadius: '50%',
        background: 'var(--accent)',
        color: '#fff',
        display: 'grid',
        placeItems: 'center',
        fontSize: 10.5,
        fontWeight: 600,
        flex: 'none',
      }}
      aria-hidden="true"
    >
      {persona.initials || persona.name?.slice(0, 2).toUpperCase() || '?'}
    </div>
  );
}
