import { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { api } from '../api.js';

/**
 * CategorySelect — multi-select with checkboxes + inline "Add category"
 *
 * Props:
 *   selected        : number[]          — ids sélectionnés
 *   onChange        : (ids: number[]) => void
 *   categories      : { id, nom }[]     — liste complète fournie par le parent
 *   onCategoryAdded : ({ id, nom }) => void  — appelé après création inline
 *
 * Le dropdown est rendu en position:fixed (calculé depuis getBoundingClientRect)
 * pour échapper au overflow:auto des modales parentes.
 */
export default function CategorySelect({ selected = [], onChange, categories = [], onCategoryAdded }) {
  const [open, setOpen]       = useState(false);
  const [adding, setAdding]   = useState(false);
  const [newName, setNewName] = useState('');
  const [err, setErr]         = useState(null);
  const [busy, setBusy]       = useState(false);
  const [dropPos, setDropPos] = useState({ top: 0, left: 0, width: 0 });

  const wrapRef    = useRef(null);
  const triggerRef = useRef(null);

  /* ── Position fixe calculée à chaque ouverture ───────────────── */
  useLayoutEffect(() => {
    if (!open || !triggerRef.current) return;
    const rect = triggerRef.current.getBoundingClientRect();
    setDropPos({
      top:   rect.bottom + 4,
      left:  rect.left,
      width: rect.width,
    });
  }, [open]);

  /* ── Fermeture : clic extérieur + scroll + resize ────────────── */
  useEffect(() => {
    if (!open) return;
    const close = (e) => {
      if (wrapRef.current?.contains(e.target)) return;
      // Exclure aussi le dropdown lui-même (rendu en fixed hors du wrap)
      const drop = document.getElementById('cat-select-dropdown-portal');
      if (drop?.contains(e.target)) return;
      setOpen(false);
    };
    const closeOnScroll = (e) => {
      const drop = document.getElementById('cat-select-dropdown-portal');
      if (drop?.contains(e.target)) return;
      setOpen(false);
    };

    document.addEventListener('mousedown', close);
    window.addEventListener('scroll', closeOnScroll, true);
    window.addEventListener('resize', closeOnScroll);
    return () => {
      document.removeEventListener('mousedown', close);
      window.removeEventListener('scroll', closeOnScroll, true);
      window.removeEventListener('resize', closeOnScroll);
    };
  }, [open]);

  const toggle = (id) => {
    onChange(selected.includes(id) ? selected.filter(x => x !== id) : [...selected, id]);
  };

  const addCategory = async (e) => {
    e.preventDefault();
    if (!newName.trim()) return;
    setBusy(true); setErr(null);
    try {
      const cat = await api.post('/categories', { nom: newName.trim() });
      onCategoryAdded(cat);
      onChange([...selected, cat.id]);
      setNewName('');
      setAdding(false);
    } catch (e) {
      setErr(e.message);
    } finally {
      setBusy(false);
    }
  };

  /* ── Label du bouton déclencheur ─────────────────────────────── */
  const label = (() => {
    if (selected.length === 0) return "Aucune catégorie d'investissement";
    const names = categories.filter(c => selected.includes(c.id)).map(c => c.nom);
    if (names.length <= 2) return names.join(', ');
    return `${names.length} catégories d'invest.`;
  })();

  /* ── Dropdown rendu en position:fixed ────────────────────────── */
  const dropdown = open ? (
    <div
      id="cat-select-dropdown-portal"
      className="cat-select-dropdown"
      role="listbox"
      aria-multiselectable="true"
      style={{
        position: 'fixed',
        top:      dropPos.top,
        left:     dropPos.left,
        width:    dropPos.width,
        zIndex:   9999,
      }}
    >
      {/* Liste des catégories */}
      {categories.length === 0 && (
        <div className="cat-select-empty">Aucune catégorie d'investissement disponible</div>
      )}
      {categories.map(cat => {
        const checked = selected.includes(cat.id);
        return (
          <label key={cat.id} className={`cat-select-item${checked ? ' checked' : ''}`}>
            <input
              type="checkbox"
              checked={checked}
              onChange={() => toggle(cat.id)}
            />
            <span>{cat.nom}</span>
            {checked && (
              <svg width="13" height="13" viewBox="0 0 24 24" fill="none"
                stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"
                style={{ marginLeft: 'auto', color: 'var(--accent)' }} aria-hidden="true">
                <polyline points="20 6 9 17 4 12"/>
              </svg>
            )}
          </label>
        );
      })}

      {/* Séparateur + ajout */}
      <div className="cat-select-sep" />

      {!adding ? (
        <button type="button" className="cat-select-add-btn"
          onClick={() => { setAdding(true); setErr(null); }}>
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none"
            stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"
            aria-hidden="true">
            <line x1="12" y1="5" x2="12" y2="19"/>
            <line x1="5" y1="12" x2="19" y2="12"/>
          </svg>
          Ajouter une catégorie d'investissement
        </button>
      ) : (
        <form onSubmit={addCategory} className="cat-select-new-form">
          <input
            autoFocus
            value={newName}
            onChange={e => setNewName(e.target.value)}
            placeholder="Nom de la catégorie d'investissement"
            maxLength={100}
          />
          <div className="cat-select-new-actions">
            <button type="submit" className="primary" disabled={busy || !newName.trim()}>
              {busy ? '…' : 'Créer'}
            </button>
            <button type="button" className="ghost"
              onClick={() => { setAdding(false); setNewName(''); setErr(null); }}>
              Annuler
            </button>
          </div>
          {err && <div className="cat-select-err">{err}</div>}
        </form>
      )}
    </div>
  ) : null;

  return (
    <>
      <div ref={wrapRef} className="cat-select-wrap">
        <button
          ref={triggerRef}
          type="button"
          className={`cat-select-trigger${open ? ' open' : ''}`}
          onClick={() => { setOpen(o => !o); setAdding(false); setErr(null); }}
          aria-haspopup="listbox"
          aria-expanded={open}
        >
          <span className="cat-select-label">{label}</span>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none"
            stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"
            style={{ flexShrink: 0, transition: 'transform .15s', transform: open ? 'rotate(0deg)' : 'rotate(180deg)' }}
            aria-hidden="true">
            <path d="M18 15l-6-6-6 6"/>
          </svg>
        </button>
      </div>

      {/* Dropdown rendu hors du wrap pour échapper à overflow:auto */}
      {dropdown}
    </>
  );
}
