import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { useLocation, useNavigate } from 'react-router-dom';
import { api } from '../api.js';
import InvSelect from '../components/InvSelect.jsx';
import ConfirmModal from '../components/ConfirmModal.jsx';
import Modal from '../components/Modal.jsx';
import ResultBanner from '../components/ResultBanner.jsx';
import CountrySelect, { COUNTRIES, FlagIcon } from '../components/CountrySelect.jsx';
import { usePagination } from '../hooks/usePagination.js';
import Pagination from '../components/Pagination.jsx';

/* ── Icônes nav ───────────────────────────────────────────────── */
function IconDatabase() {
  return <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><ellipse cx="12" cy="5" rx="9" ry="3"/><path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3"/><path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"/></svg>;
}
function IconImage() {
  return <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>;
}
function IconLink() {
  return <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>;
}
function IconChevronLeft() {
  return <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><polyline points="15 18 9 12 15 6"/></svg>;
}
function IconEdit() {
  return <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>;
}
function IconTrash() {
  return <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/><path d="M10 11v6"/><path d="M14 11v6"/><path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg>;
}
function IconPushSoft() {
  return <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><polyline points="19 12 12 19 5 12"/><line x1="5" y1="21" x2="19" y2="21"/></svg>;
}
function IconPushForce() {
  return <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="17 8 12 13 7 8"/><polyline points="17 13 12 18 7 13"/><line x1="5" y1="21" x2="19" y2="21"/></svg>;
}
function IconDownload() {
  return <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>;
}
function IconUpload() {
  return <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>;
}

/* ── Constantes ───────────────────────────────────────────────── */
const countryLabel = code => COUNTRIES.find(c => c.code === code)?.name ?? code ?? '—';
const FISCALITE_LABELS = { flat_tax: 'Flat tax (30%)', sans_fiscalite_locale: 'Sans fiscalité locale', avec_fiscalite_locale: 'Avec fiscalité locale' };
const EMPTY_REF = { nom: '', url: '', domiciliation: 'france', fiscalite: 'flat_tax', taux_fiscalite_locale: '', type_produit_fiscal: '2TT', methode_remboursement: 'portefeuille', type_pret_defaut: '', freq_interets_defaut: '', description: '', categories: [], categories_inv_ids: [], secteurs_inv_ids: [] };

/* ── Modal création / édition référentiel ─────────────────────── */
function RefModal({ row, onClose, onSaved }) {
  const isNew = !row?.id;
  const [catsInv,      setCatsInv]      = useState([]);
  const [secteursInv,  setSecteursInv]  = useState([]);
  const [err, setErr] = useState(null);
  const [saving, setSaving] = useState(false);

  const [form, setForm] = useState(isNew ? { ...EMPTY_REF } : {
    nom: row.nom || '', url: row.url || '', domiciliation: row.domiciliation || 'france',
    fiscalite: row.fiscalite || 'flat_tax',
    taux_fiscalite_locale: row.taux_fiscalite_locale != null ? String(row.taux_fiscalite_locale) : '',
    type_produit_fiscal: row.type_produit_fiscal || '2TT',
    methode_remboursement: row.methode_remboursement || 'portefeuille',
    type_pret_defaut: row.type_pret_defaut || '',
    freq_interets_defaut: row.freq_interets_defaut || '',
    description: row.description || '',
    categories: [],
    categories_inv_ids: (row.categories_inv || []).map(c => c.id),
    secteurs_inv_ids:   (row.secteurs_inv   || []).map(s => s.id),
  });

  useEffect(() => {
    Promise.all([
      api.get('/ref-categories'),
      api.get('/ref-secteurs'),
    ]).then(([cats, sects]) => {
      setCatsInv(cats);
      setSecteursInv(sects);
    }).catch(() => {});
  }, []); // eslint-disable-line

  const set = (k, v) => setForm(f => ({ ...f, [k]: v }));
  const fiscalite = form.domiciliation === 'FR' ? 'flat_tax' : form.fiscalite;

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!form.nom.trim()) { setErr('Le nom est requis.'); return; }
    setSaving(true); setErr(null);
    try {
      // Champs gérés par RefModal
      const ownFields = {
        nom: form.nom.trim(), url: form.url.trim() || null,
        domiciliation: form.domiciliation, fiscalite,
        taux_fiscalite_locale: fiscalite === 'avec_fiscalite_locale' && form.taux_fiscalite_locale !== ''
          ? Number(form.taux_fiscalite_locale) : null,
        type_produit_fiscal: form.type_produit_fiscal,
        methode_remboursement: form.methode_remboursement || 'portefeuille',
        type_pret_defaut: form.type_pret_defaut || null,
        freq_interets_defaut: form.freq_interets_defaut || null,
        description: form.description.trim() || null,
        categories_inv_ids: form.categories_inv_ids || [],
        secteurs_inv_ids:   form.secteurs_inv_ids   || [],
      };

      if (isNew) {
        await api.post('/referentiel', { ...ownFields, categories: [], notation: [] });
      } else {
        // Récupérer l'entrée courante pour préserver les champs du profil
        const current = await api.get(`/referentiel/${row.id}`);
        const payload = {
          ...ownFields,
          // Champs préservés — gérés uniquement par PlatformeProfile
          categories:             current.categories             ?? [],
          notation:               current.notation               ?? [],
          logo_filename:          current.logo_filename          ?? null,
          annee_creation:         current.annee_creation         ?? null,
          investisseurs_types:    current.investisseurs_types    ?? null,
          regulateur:             current.regulateur             ?? null,
          numero_licence:         current.numero_licence         ?? null,
          is_regule:              current.is_regule              ?? false,
          pays_inscription:       current.pays_inscription       ?? null,
          pays_siege:             current.pays_siege             ?? null,
          pays_operation:         current.pays_operation         ?? [],
          investissement_minimum: current.investissement_minimum ?? null,
          rendement_annonce:      current.rendement_annonce      ?? null,
          nb_investisseurs:       current.nb_investisseurs       ?? null,
          volume_total_finance:   current.volume_total_finance   ?? null,
          duree_moyenne_pret:     current.duree_moyenne_pret     ?? null,
          garantie_rachat:        current.garantie_rachat        ?? false,
          statistiques_publiques: current.statistiques_publiques ?? false,
          bonus_inscription:      current.bonus_inscription      ?? false,
          marche_secondaire:      current.marche_secondaire      ?? false,
          investissement_auto:    current.investissement_auto    ?? false,
          url_trustpilot:         current.url_trustpilot         ?? null,
          url_linkedin:           current.url_linkedin           ?? null,
        };
        await api.put(`/referentiel/${row.id}`, payload);
      }
      onSaved(); onClose();
    } catch (ex) { setErr(ex.message); }
    finally { setSaving(false); }
  };

  return (
    <Modal open title={isNew ? 'Ajouter au référentiel' : `Modifier — ${row.nom}`}
      onClose={onClose} width={640}
      footer={<>
        <button type="button" onClick={onClose} disabled={saving}>Annuler</button>
        <button className="primary" form="ref-form" type="submit" disabled={saving}>{saving ? '…' : isNew ? 'Créer' : 'Enregistrer'}</button>
      </>}>
      <form id="ref-form" onSubmit={handleSubmit}>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
          <div><label>Nom *</label><input value={form.nom} onChange={e => set('nom', e.target.value)} placeholder="Ex : October, Lendosphere…" /></div>
          <div><label>URL</label><input value={form.url} onChange={e => set('url', e.target.value)} placeholder="https://…" /></div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <div>
              <label>Domiciliation</label>
              <CountrySelect
                value={form.domiciliation}
                onChange={code => set('domiciliation', code)}
                showCode
              />
            </div>
            <div>
              <label>Fiscalité</label>
              {form.domiciliation === 'FR'
                ? <input value="Flat tax (automatique)" disabled />
                : <select value={form.fiscalite} onChange={e => set('fiscalite', e.target.value)}>
                    <option value="sans_fiscalite_locale">Sans fiscalité locale</option>
                    <option value="avec_fiscalite_locale">Avec fiscalité locale</option>
                  </select>}
            </div>
          </div>
          {fiscalite === 'avec_fiscalite_locale' && (
            <div><label>Taux fiscalité locale (%)</label>
              <input type="number" min="0" max="100" step="0.1" value={form.taux_fiscalite_locale} onChange={e => set('taux_fiscalite_locale', e.target.value)} placeholder="Ex : 15" /></div>
          )}
          <div>
            <label>Type produit fiscal</label>
            <select value={form.type_produit_fiscal} onChange={e => set('type_produit_fiscal', e.target.value)}>
              <option value="2TT">2TT — Intérêts</option>
              <option value="2TR">2TR — Revenus assimilés</option>
            </select>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 12 }}>
            <div>
              <label>Méthode de remboursement</label>
              <select value={form.methode_remboursement} onChange={e => set('methode_remboursement', e.target.value)}>
                <option value="portefeuille">Porte-monnaie</option>
                <option value="compte_courant">Compte courant</option>
                <option value="choix_investisseur">Choix investisseur</option>
              </select>
            </div>
            <div>
              <label>Type de prêt (défaut)</label>
              <select value={form.type_pret_defaut} onChange={e => {
                const t = e.target.value;
                set('type_pret_defaut', t);
                if (t === 'differe') set('freq_interets_defaut', 'in_fine');
                else if (form.freq_interets_defaut === 'in_fine') set('freq_interets_defaut', 'mensuel');
              }}>
                <option value="">— Non défini —</option>
                <option value="in_fine">In fine</option>
                <option value="amortissable">Amortissable</option>
                <option value="differe">Différé</option>
              </select>
            </div>
            <div>
              <label>Périodicité (défaut)</label>
              <select value={form.type_pret_defaut === 'differe' ? 'in_fine' : form.freq_interets_defaut}
                disabled={form.type_pret_defaut === 'differe'}
                onChange={e => set('freq_interets_defaut', e.target.value)}>
                {form.type_pret_defaut === 'differe'
                  ? <option value="in_fine">In fine (unique)</option>
                  : <>
                      <option value="">— Non définie —</option>
                      <option value="mensuel">Mensuelle</option>
                      <option value="trimestriel">Trimestrielle</option>
                    </>
                }
              </select>
            </div>
          </div>
          <div><label>Description</label>
            <textarea value={form.description} onChange={e => set('description', e.target.value)}
              style={{ minHeight: 60, resize: 'vertical' }} placeholder="Informations générales sur la plateforme…" /></div>
          <div>
            <label>Catégories d'investissement</label>
            <InvSelect
              items={catsInv}
              selected={form.categories_inv_ids || []}
              onChange={ids => set('categories_inv_ids', ids)}
              emptyLabel="Aucune catégorie d'investissement"
            />
          </div>
          <div>
            <label>Secteurs d'investissement</label>
            <InvSelect
              items={secteursInv}
              selected={form.secteurs_inv_ids || []}
              onChange={ids => set('secteurs_inv_ids', ids)}
              emptyLabel="Aucun secteur d'investissement"
            />
          </div>
        </div>
        {err && <div className="error" style={{ marginTop: 12 }}>{err}</div>}
      </form>
    </Modal>
  );
}

/* ── Section référentiel plateformes ─────────────────────────── */
function ReferentielSection() {
  const navigate = useNavigate();
  const [rows,       setRows]       = useState([]);
  const [loading,    setLoading]    = useState(true);
  const [orphelineCount, setOrphelineCount] = useState(0);
  const [err,        setErr]        = useState(null);
  const [editing,    setEditing]    = useState(null);
  const [deleting,   setDeleting]   = useState(null);
  const [pushing,         setPushing]         = useState(null);
  const [pushResult,      setPushResult]      = useState(null);
  const [openMenu,        setOpenMenu]        = useState(null);
  const [forcePushConfirm, setForcePushConfirm] = useState(null);
  const [exporting,    setExporting]    = useState(false);
  const [importResult, setImportResult] = useState(null);
  const importRef = useRef(null);
  const { search: urlSearch } = useLocation();
  const [search,          setSearch]          = useState('');
  const [filterDomicil,   setFilterDomicil]   = useState('');
  const [filterCategorie, setFilterCategorie] = useState(
    () => new URLSearchParams(urlSearch).get('filterCat') || ''
  );

  const allCategories = useMemo(() => {
    const set = new Set();
    rows.forEach(r => (r.categories_inv || []).forEach(c => set.add(c.nom)));
    return [...set].sort((a, b) => a.localeCompare(b, 'fr'));
  }, [rows]);

  const allDomiciliations = useMemo(() => {
    const set = new Set();
    rows.forEach(r => { if (r.domiciliation) set.add(r.domiciliation); });
    return [...set].sort((a, b) => a.localeCompare(b, 'fr'));
  }, [rows]);

  const filteredRows = useMemo(() => {
    let r = rows;
    if (filterDomicil) r = r.filter(x => x.domiciliation === filterDomicil);
    if (filterCategorie) r = r.filter(x => (x.categories_inv || []).some(c => c.nom === filterCategorie));
    if (search.trim()) {
      const q = search.trim().toLowerCase();
      r = r.filter(x => x.nom.toLowerCase().includes(q));
    }
    return r;
  }, [rows, search, filterDomicil, filterCategorie]);

  const { pagedItems, page, setPage, pageSize, setPageSize, totalPages, totalItems, PAGE_SIZES } =
    usePagination(filteredRows, 'cl_pagesize_referentiel', [search, filterDomicil, filterCategorie]);

  const load = useCallback(async () => {
    try {
      setLoading(true);
      const [ref, orphelines] = await Promise.all([
        api.get('/referentiel'),
        api.get('/admin/plateformes-orphelines').catch(() => []),
      ]);
      setRows(ref);
      setOrphelineCount(orphelines.length);
    } catch (e) { setErr(e.message); }
    finally { setLoading(false); }
  }, []);

  useEffect(() => { load(); }, [load]);

  useEffect(() => {
    if (!openMenu) return;
    const close = () => setOpenMenu(null);
    window.addEventListener('scroll', close, true);
    return () => window.removeEventListener('scroll', close, true);
  }, [openMenu]);

  const handlePush = async (row, force = false) => {
    setPushing(row.id); setPushResult(null);
    try {
      const r = await api.post(`/referentiel/${row.id}/push`, { force });
      const label = force ? 'Poussée forcée' : 'Poussée douce';
      setPushResult({ ok: true, msg: `${label} — mis à jour : ${r.nb_updated} / ${r.nb_plateformes} plateforme(s)` });
      load();
    } catch (e) { setPushResult({ ok: false, msg: e.message }); }
    finally { setPushing(null); }
  };

  const handleDelete = (row) => {
    setDeleting({
      title: 'Supprimer ce référentiel ?',
      message: `Supprimer "${row.nom}" ? Les ${row.nb_plateformes_liees} plateforme(s) liée(s) seront détachées mais leurs données conservées.`,
      confirmLabel: 'Supprimer', danger: true,
      onConfirm: async () => {
        try { await api.del(`/referentiel/${row.id}`); load(); }
        catch (e) { setErr(e.message); }
        finally { setDeleting(null); }
      },
    });
  };

  const handleExportAll = async () => {
    try {
      setExporting(true);
      const blob = await api.blob('/referentiel/export');
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `referentiel-${new Date().toISOString().slice(0, 10)}.zip`;
      document.body.appendChild(a); a.click(); document.body.removeChild(a);
      URL.revokeObjectURL(url);
    } catch (e) { setImportResult({ ok: false, msg: e.message }); }
    finally { setExporting(false); }
  };

  const handleExportOne = async (row) => {
    try {
      const blob = await api.blob(`/referentiel/${row.id}/export`);
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `${row.nom.toLowerCase().replace(/[^a-z0-9]+/g, '-')}-${new Date().toISOString().slice(0, 10)}.zip`;
      document.body.appendChild(a); a.click(); document.body.removeChild(a);
      URL.revokeObjectURL(url);
    } catch (e) { setImportResult({ ok: false, msg: e.message }); }
  };

  const handleImportZip = async (file) => {
    try {
      const fd = new FormData();
      fd.append('file', file);
      const r = await api.upload('/referentiel/import-zip', fd);
      setImportResult({ ok: true, msg: `Import terminé : ${r.created} créée(s), ${r.updated} mise(s) à jour sur ${r.total} entrée(s).` });
      load();
    } catch (e) { setImportResult({ ok: false, msg: e.message }); }
  };


  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 16 }}>
        <div>
          <h2 style={{ margin: 0, fontSize: 18 }}>Référentiel des plateformes</h2>
          <p style={{ margin: '4px 0 0', color: 'var(--text-muted)', fontSize: 13 }}>
            Données communes héritées par les utilisateurs lors de la création de leurs plateformes.
          </p>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexShrink: 0 }}>
          <button
            onClick={() => navigate('/admin/plateformes?section=orphelines')}
            style={{
              padding: '7px 14px', borderRadius: 6, border: '1px solid',
              fontSize: 13, fontWeight: 600, cursor: 'pointer',
              background: orphelineCount > 0 ? 'rgba(239,68,68,.08)' : 'var(--surface-2)',
              color: orphelineCount > 0 ? '#dc2626' : 'var(--text-muted)',
              borderColor: orphelineCount > 0 ? 'rgba(239,68,68,.3)' : 'var(--border)',
            }}>
            {orphelineCount} plateforme{orphelineCount !== 1 ? 's' : ''} suggérée{orphelineCount !== 1 ? 's' : ''}
          </button>
          <button
            onClick={handleExportAll} disabled={exporting || rows.length === 0}
            title="Exporter tout le référentiel en ZIP"
            style={{ padding: '7px 14px', borderRadius: 6, border: '1px solid var(--border)', fontSize: 13, fontWeight: 600, cursor: 'pointer', background: 'var(--surface-2)', color: 'var(--text-muted)', display: 'flex', alignItems: 'center', gap: 6 }}>
            <IconDownload /> {exporting ? '…' : 'Exporter tout'}
          </button>
          <button
            onClick={() => importRef.current?.click()}
            title="Importer un fichier ZIP de référentiel"
            style={{ padding: '7px 14px', borderRadius: 6, border: '1px solid var(--border)', fontSize: 13, fontWeight: 600, cursor: 'pointer', background: 'var(--surface-2)', color: 'var(--text-muted)', display: 'flex', alignItems: 'center', gap: 6 }}>
            <IconUpload /> Importer
          </button>
          <button className="primary" style={{ flexShrink: 0 }} onClick={() => setEditing('new')}>+ Ajouter</button>
        </div>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 8, marginBottom: 16 }}>
        <input
          type="search"
          placeholder="Rechercher par nom…"
          value={search}
          onChange={e => setSearch(e.target.value)}
          style={{ width: '100%', boxSizing: 'border-box', padding: '9px 14px', fontSize: 14, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--text)' }}
        />
        <div style={{ display: 'flex', gap: 8 }}>
          <select
            value={filterDomicil}
            onChange={e => setFilterDomicil(e.target.value)}
            style={{ flex: 1, padding: '7px 12px', fontSize: 13, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--text)' }}
          >
            <option value="">Toutes les domiciliations</option>
            {allDomiciliations.map(v => (
              <option key={v} value={v}>{countryLabel(v)}</option>
            ))}
          </select>
          <select
            value={filterCategorie}
            onChange={e => setFilterCategorie(e.target.value)}
            style={{ flex: 1, padding: '7px 12px', fontSize: 13, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--surface)', color: 'var(--text)' }}
          >
            <option value="">Toutes les catégories</option>
            {allCategories.map(c => <option key={c} value={c}>{c}</option>)}
          </select>
          {(search || filterDomicil || filterCategorie) && (
            <button
              onClick={() => { setSearch(''); setFilterDomicil(''); setFilterCategorie(''); }}
              style={{ padding: '7px 12px', fontSize: 13, borderRadius: 6, border: '1px solid var(--border)', background: 'var(--surface-2)', color: 'var(--text-muted)', cursor: 'pointer', whiteSpace: 'nowrap' }}
            >Effacer les filtres</button>
          )}
        </div>
      </div>

      {err && <div className="error" style={{ marginBottom: 12 }}>{err}</div>}
      {pushResult && (
        <div style={{ marginBottom: 12, padding: '8px 14px', borderRadius: 8, fontSize: 13,
          background: pushResult.ok ? 'rgba(34,197,94,.1)' : 'rgba(239,68,68,.1)',
          color: pushResult.ok ? '#16a34a' : '#dc2626',
          border: `1px solid ${pushResult.ok ? 'rgba(34,197,94,.3)' : 'rgba(239,68,68,.3)'}` }}>
          {pushResult.msg}
          <button onClick={() => setPushResult(null)} style={{ marginLeft: 12, background: 'none', border: 'none', cursor: 'pointer', color: 'inherit', fontSize: 16, lineHeight: 1 }}>×</button>
        </div>
      )}

      {importResult && <ResultBanner result={importResult} onDismiss={() => setImportResult(null)} style={{ marginBottom: 12 }} />}

      <input ref={importRef} type="file" accept=".zip" style={{ display: 'none' }}
        onChange={e => { const f = e.target.files[0]; e.target.value = ''; if (f) handleImportZip(f); }} />

      {loading ? <p style={{ color: 'var(--text-muted)' }}>Chargement…</p> : (
        <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
            <thead>
              <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
                <th style={{ padding: '10px 8px', width: 40 }}></th>
                <th style={{ padding: '10px 16px', textAlign: 'left' }}>Nom</th>
                <th style={{ padding: '10px 8px', textAlign: 'left' }}>Domiciliation</th>
                <th style={{ padding: '10px 8px', textAlign: 'left' }}>Catégories</th>
                <th style={{ padding: '10px 8px', textAlign: 'left' }}>Secteurs</th>
                <th style={{ padding: '10px 8px', textAlign: 'center' }}>Héritage</th>
                <th style={{ padding: '10px 16px', width: 40 }}></th>
              </tr>
            </thead>
            <tbody>
              {filteredRows.length === 0 ? (
                <tr><td colSpan={7} style={{ padding: 32, textAlign: 'center', color: 'var(--text-muted)' }}>
                  {rows.length === 0
                    ? 'Aucune entrée dans le référentiel. Créez-en une ou importez une plateforme orpheline.'
                    : 'Aucun résultat pour ces critères.'}
                </td></tr>
              ) : pagedItems.map((row, i) => (
                <tr key={row.id}
                  onClick={() => navigate(`/referentiel/${row.id}`)}
                  style={{ borderBottom: i < pagedItems.length - 1 ? '1px solid var(--border)' : 'none', cursor: 'pointer' }}
                  onMouseEnter={e => e.currentTarget.style.background = 'var(--surface-2)'}
                  onMouseLeave={e => e.currentTarget.style.background = 'none'}>
                  <td style={{ padding: '8px 8px 8px 16px', width: 40 }}>
                    {row.icone_filename
                      ? <img src={`${(import.meta.env.VITE_API_URL || '/api').replace(/\/api$/, '')}/api/logos/${row.icone_filename}`}
                          alt="" title="Icône bibliothèque" style={{ width: 32, height: 32, objectFit: 'contain', borderRadius: 4, display: 'block' }} />
                      : row.logo_filename
                        ? <img src={`${(import.meta.env.VITE_API_URL || '/api').replace(/\/api$/, '')}/api/logos/${row.logo_filename}`}
                            alt="" title="Logo uploadé" style={{ width: 32, height: 32, objectFit: 'contain', borderRadius: 4, display: 'block' }} />
                        : <div title="Aucune image" style={{ width: 32, height: 32, borderRadius: 4, background: 'var(--surface-2)', border: '1px dashed var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'var(--text-muted)', fontSize: 16 }}>×</div>
                    }
                  </td>
                  <td style={{ padding: '10px 16px' }}>
                    <div style={{ fontWeight: 600 }}>{row.nom}</div>
                    {row.description && <div style={{ fontSize: 11, color: 'var(--text-muted)', marginTop: 2 }}>{row.description}</div>}
                  </td>
                  <td style={{ padding: '10px 8px', color: 'var(--text-muted)', fontSize: 12 }}><span style={{ display:'inline-flex', alignItems:'center', gap:5 }}><FlagIcon code={row.domiciliation} size={15} />{countryLabel(row.domiciliation)}</span></td>
                  <td style={{ padding: '10px 8px' }}>
                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
                      {(row.categories_inv || []).slice(0, 2).map(c => <span key={c.id} className="chip-cat" style={{ fontSize: 11 }}>{c.nom}</span>)}
                      {(row.categories_inv || []).length > 2 && <span style={{ fontSize: 11, color: 'var(--text-muted)' }}>+{row.categories_inv.length - 2}</span>}
                      {(row.categories_inv || []).length === 0 && <span style={{ fontSize: 11, color: 'var(--text-muted)' }}>—</span>}
                    </div>
                  </td>
                  <td style={{ padding: '10px 8px' }}>
                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4 }}>
                      {(row.secteurs_inv || []).slice(0, 2).map(s => <span key={s.id} className="chip-sect" style={{ fontSize: 11 }}>{s.nom}</span>)}
                      {(row.secteurs_inv || []).length > 2 && <span style={{ fontSize: 11, color: 'var(--text-muted)' }}>+{row.secteurs_inv.length - 2}</span>}
                      {(row.secteurs_inv || []).length === 0 && <span style={{ fontSize: 11, color: 'var(--text-muted)' }}>—</span>}
                    </div>
                  </td>
                  <td style={{ padding: '10px 8px', textAlign: 'center' }}>
                    <span style={{ display: 'inline-block', minWidth: 28, padding: '2px 8px', borderRadius: 12, fontSize: 12, fontWeight: 700,
                      background: row.nb_plateformes_liees > 0 ? 'rgba(99,102,241,.12)' : 'var(--surface-2)',
                      color: row.nb_plateformes_liees > 0 ? '#6366f1' : 'var(--text-muted)' }}>
                      {row.nb_plateformes_liees}
                    </span>
                  </td>
                  <td style={{ padding: '10px 16px', textAlign: 'right' }}>
                    <button
                      style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '4px 8px', borderRadius: 4, fontSize: 18, color: 'var(--text-muted)', lineHeight: 1 }}
                      onMouseEnter={e => e.currentTarget.style.background = 'var(--surface-2)'}
                      onMouseLeave={e => e.currentTarget.style.background = 'none'}
                      onClick={e => { e.stopPropagation(); const rect = e.currentTarget.getBoundingClientRect(); setOpenMenu({ row, x: rect.right, y: rect.bottom }); }}
                    >⋮</button>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}

      <Pagination
        page={page} setPage={setPage}
        pageSize={pageSize} setPageSize={setPageSize}
        totalPages={totalPages} totalItems={totalItems}
        PAGE_SIZES={PAGE_SIZES}
      />

      {openMenu && (
        <>
          <div style={{ position: 'fixed', inset: 0, zIndex: 299 }} onClick={() => setOpenMenu(null)} />
          <div style={{ position: 'fixed', left: openMenu.x, top: openMenu.y,
            transform: 'translateX(-100%) translateY(4px)', zIndex: 300,
            background: 'var(--surface)', border: '1px solid var(--border)',
            borderRadius: 8, boxShadow: '0 4px 20px rgba(0,0,0,0.15)', padding: '4px 0', minWidth: 180 }}>
            {[
              { icon: <IconEdit />, label: 'Modifier', onClick: () => { setOpenMenu(null); setEditing(openMenu.row); } },
              { icon: <IconPushSoft />, label: pushing === openMenu.row.id ? 'Poussée…' : `Pousser (douce) — ${openMenu.row.nb_plateformes_liees} pl.`,
                title: "Pousse uniquement les champs que l'utilisateur n'a pas modifiés",
                onClick: () => { const r = openMenu.row; setOpenMenu(null); handlePush(r, false); },
                disabled: openMenu.row.nb_plateformes_liees === 0 || pushing === openMenu.row.id, color: '#2563eb' },
              { icon: <IconPushForce />, label: pushing === openMenu.row.id ? 'Poussée…' : `Pousser (forcée) — ${openMenu.row.nb_plateformes_liees} pl.`,
                title: 'Écrase tous les champs, y compris les modifications des utilisateurs',
                onClick: () => { const r = openMenu.row; setOpenMenu(null); setForcePushConfirm(r); },
                disabled: openMenu.row.nb_plateformes_liees === 0 || pushing === openMenu.row.id, color: '#d97706' },
              { icon: <IconDownload />, label: 'Exporter', onClick: () => { const r = openMenu.row; setOpenMenu(null); handleExportOne(r); } },
              { icon: <IconTrash />, label: 'Supprimer', onClick: () => { const r = openMenu.row; setOpenMenu(null); handleDelete(r); }, color: 'var(--danger)' },
            ].map(({ icon, label, title, onClick, disabled, color }) => (
              <button key={label} disabled={disabled} title={title}
                style={{ display: 'flex', alignItems: 'center', gap: 8, width: '100%', padding: '8px 14px',
                  background: 'none', border: 'none', cursor: disabled ? 'default' : 'pointer',
                  fontSize: 'var(--fs-sm)', color: color || 'var(--text)', textAlign: 'left', opacity: disabled ? 0.5 : 1 }}
                onMouseEnter={e => { if (!disabled) e.currentTarget.style.background = 'var(--surface-2)'; }}
                onMouseLeave={e => e.currentTarget.style.background = 'none'}
                onClick={disabled ? undefined : onClick}>
                <span style={{ opacity: 0.7, flexShrink: 0, display: 'flex' }}>{icon}</span>
                {label}
              </button>
            ))}
          </div>
        </>
      )}

      {editing && <RefModal row={editing === 'new' ? null : editing} onClose={() => setEditing(null)} onSaved={load} />}
      {deleting && <ConfirmModal open title={deleting.title} message={deleting.message} confirmLabel={deleting.confirmLabel} danger={deleting.danger} onConfirm={deleting.onConfirm} onCancel={() => setDeleting(null)} />}
      {forcePushConfirm && (
        <ConfirmModal open
          title="Poussée forcée — confirmer ?"
          message={`Cette opération va écraser tous les champs des ${forcePushConfirm.nb_plateformes_liees} plateforme(s) liée(s) à "${forcePushConfirm.nom}", y compris les modifications apportées par les utilisateurs. Leurs overrides seront réinitialisés.`}
          confirmLabel="Forcer la poussée"
          danger
          onConfirm={() => { const r = forcePushConfirm; setForcePushConfirm(null); handlePush(r, true); }}
          onCancel={() => setForcePushConfirm(null)}
        />
      )}
    </div>
  );
}

/* ── Bibliothèque de logos/icones du référentiel ────────────────── */
function LogosBibliothequeSection() {
  const [rows,      setRows]      = useState([]);
  const [loading,   setLoading]   = useState(true);
  const [err,       setErr]       = useState(null);
  const [uploading, setUploading] = useState(null);
  const [deleting,  setDeleting]  = useState(null);
  const [result,    setResult]    = useState(null);
  const [type,      setType]      = useState('logo'); // 'logo' | 'icone'
  const fileInputRef = useRef(null);
  const [targetId,  setTargetId]  = useState(null);

  const API_BASE = (import.meta.env.VITE_API_URL || '/api').replace(/\/api$/, '');

  const load = async () => {
    try {
      setLoading(true);
      const data = await api.get('/referentiel');
      setRows(data);
    } catch (e) { setErr(e.message); }
    finally { setLoading(false); }
  };

  useEffect(() => { load(); }, []);

  const handleFileChange = async (e) => {
    const file = e.target.files?.[0];
    if (!file || !targetId) return;
    e.target.value = '';

    const allowed = ['.svg', '.png', '.jpg', '.jpeg', '.webp'];
    const ext = file.name.toLowerCase().match(/\.[^.]+$/)?.[0];
    if (!allowed.includes(ext)) {
      setResult({ ok: false, msg: 'Format non supporté — SVG, PNG, JPG ou WebP uniquement' });
      return;
    }

    setUploading(targetId);
    setResult(null);
    try {
      const formData = new FormData();
      formData.append('file', file);
      const token = localStorage.getItem('cl_token');
      const res = await fetch(`${API_BASE}/api/referentiel/${targetId}/${type}`, {
        method: 'POST',
        headers: token ? { Authorization: `Bearer ${token}` } : {},
        body: formData,
      });
      const json = await res.json();
      if (!res.ok) throw new Error(json.error || 'Erreur upload');
      const label = type === 'logo' ? 'Logo' : 'Icône';
      const countKey = json.nb_plateformes_updated;
      setResult({ ok: true, msg: `${label} importé — mis à jour sur ${countKey} plateforme(s) liée(s).` });
      load();
    } catch (ex) { setResult({ ok: false, msg: ex.message }); }
    finally { setUploading(null); setTargetId(null); }
  };

  const triggerUpload = (id) => {
    setTargetId(id);
    setTimeout(() => fileInputRef.current?.click(), 50);
  };

  const handleDelete = (row) => {
    const label = type === 'logo' ? 'logo' : 'icône';
    setDeleting({
      title: `Supprimer le ${label} de "${row.nom}" ?`,
      message: `Le ${label} sera supprimé du référentiel et retiré de toutes les plateformes liées non-overridées.`,
      confirmLabel: 'Supprimer', danger: true,
      onConfirm: async () => {
        try {
          await api.del(`/referentiel/${row.id}/${type}`);
          setResult({ ok: true, msg: `${label.charAt(0).toUpperCase() + label.slice(1)} de "${row.nom}" supprimé.` });
          load();
        } catch (ex) { setResult({ ok: false, msg: ex.message }); }
        finally { setDeleting(null); }
      },
    });
  };

  const getImageUrl = (row) => {
    const filename = type === 'logo' ? row.logo_filename : row.icone_filename;
    return filename ? `${API_BASE}/api/logos/${filename}` : null;
  };

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 16 }}>
        <div>
          <h2 style={{ margin: 0, fontSize: 18 }}>Bibliothèque d'images — Plateformes</h2>
          <p style={{ margin: '4px 0 0', color: 'var(--text-muted)', fontSize: 13 }}>
            {type === 'logo'
              ? 'Logos associés au référentiel. Une fois importé, le logo est poussé automatiquement vers les plateformes liées.'
              : 'Icônes associées au référentiel. Une fois importée, l\'icône est poussée automatiquement vers les plateformes liées.'}
          </p>
        </div>
      </div>

      <div className="dr-tabs" style={{ marginBottom: 20 }}>
        <button
          className={`dr-tab${type === 'logo' ? ' active' : ''}`}
          onClick={() => { setType('logo'); setResult(null); }}>
          Logos
        </button>
        <button
          className={`dr-tab${type === 'icone' ? ' active' : ''}`}
          onClick={() => { setType('icone'); setResult(null); }}>
          Icônes
        </button>
      </div>

      <input ref={fileInputRef} type="file" accept=".svg,.png,.jpg,.jpeg,.webp" style={{ display: 'none' }} onChange={handleFileChange} />

      {err && <div className="error" style={{ marginBottom: 12 }}>{err}</div>}
      <ResultBanner result={result} onDismiss={() => setResult(null)} style={{ marginBottom: 16 }} />

      {loading ? <p style={{ color: 'var(--text-muted)' }}>Chargement…</p> : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: 16 }}>
          {rows.length === 0 && (
            <p style={{ color: 'var(--text-muted)', gridColumn: '1 / -1' }}>Aucune entrée dans le référentiel.</p>
          )}
          {rows.map(row => {
            const imageUrl = getImageUrl(row);
            const isUploading = uploading === row.id;
            const missingLabel = type === 'logo' ? 'Logo manquant' : 'Icône manquante';

            return (
              <div key={row.id} className="card" style={{ padding: 0, overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
                <div style={{
                  height: 110,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                  background: 'var(--surface-2)',
                  borderBottom: '1px solid var(--border)',
                  position: 'relative',
                }}>
                  {isUploading ? (
                    <span style={{ color: 'var(--text-muted)', fontSize: 13 }}>Import…</span>
                  ) : imageUrl ? (
                    <img src={imageUrl} alt={row.nom}
                      style={{ maxWidth: 120, maxHeight: 80, objectFit: 'contain' }}
                      onError={e => { e.currentTarget.style.display = 'none'; e.currentTarget.nextSibling.style.display = 'flex'; }} />
                  ) : null}
                  <div style={{
                    display: imageUrl && !isUploading ? 'none' : 'flex',
                    flexDirection: 'column', alignItems: 'center', gap: 6,
                    color: 'var(--text-muted)',
                  }}>
                    {!isUploading && (
                      <>
                        <svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" opacity="0.45">
                          <circle cx="12" cy="12" r="10"/>
                          <line x1="8" y1="8" x2="16" y2="16"/>
                          <line x1="16" y1="8" x2="8" y2="16"/>
                        </svg>
                        <span style={{ fontSize: 11 }}>{missingLabel}</span>
                      </>
                    )}
                  </div>
                </div>

                <div style={{ padding: '10px 12px', flex: 1, display: 'flex', flexDirection: 'column', gap: 6 }}>
                  <div style={{ fontWeight: 600, fontSize: 13, lineHeight: 1.3 }}>{row.nom}</div>
                  {row.nb_plateformes_liees > 0 && (
                    <div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{row.nb_plateformes_liees} plateforme(s) liée(s)</div>
                  )}
                  <div style={{ marginTop: 'auto', paddingTop: 8, display: 'flex', gap: 6 }}>
                    <button
                      onClick={() => triggerUpload(row.id)}
                      disabled={isUploading}
                      style={{ flex: 1, fontSize: 12, padding: '5px 8px', cursor: 'pointer' }}>
                      {imageUrl ? 'Remplacer' : 'Importer'}
                    </button>
                    {imageUrl && (
                      <button
                        onClick={() => handleDelete(row)}
                        disabled={isUploading}
                        style={{ fontSize: 12, padding: '5px 8px', cursor: 'pointer', color: 'var(--danger)', background: 'rgba(239,68,68,.08)', border: '1px solid rgba(239,68,68,.25)', borderRadius: 6 }}>
                        ×
                      </button>
                    )}
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}

      {deleting && <ConfirmModal open title={deleting.title} message={deleting.message} confirmLabel={deleting.confirmLabel} danger={deleting.danger} onConfirm={deleting.onConfirm} onCancel={() => setDeleting(null)} />}
    </div>
  );
}

/* ── Section plateformes orphelines ──────────────────────────── */
function OrphelinesSection() {
  const navigate = useNavigate();
  const [rows,      setRows]      = useState([]);
  const [loading,   setLoading]   = useState(true);
  const [err,       setErr]       = useState(null);
  const [acting,    setActing]    = useState(null);
  const [confirm,   setConfirm]   = useState(null);
  const [result,    setResult]    = useState(null);

  const load = useCallback(async () => {
    try { setLoading(true); setRows(await api.get('/admin/plateformes-orphelines')); }
    catch (e) { setErr(e.message); }
    finally { setLoading(false); }
  }, []);

  useEffect(() => { load(); }, [load]);

  const handleLier = (p) => {
    setConfirm({
      title: 'Lier au référentiel existant',
      message: `Lier "${p.nom}" au référentiel "${p.suggestion.referentiel_nom}" (similarité ${p.suggestion.score}%) sans modifier les données ? Les champs ne seront pas écrasés.`,
      confirmLabel: 'Lier',
      onConfirm: async () => {
        setConfirm(null); setActing(p.id);
        try {
          await api.post(`/admin/plateformes-orphelines/${p.id}/lier`, { referentiel_id: p.suggestion.referentiel_id });
          setResult({ ok: true, msg: `"${p.nom}" lié à "${p.suggestion.referentiel_nom}".` });
          load();
        } catch (e) { setResult({ ok: false, msg: e.message }); }
        finally { setActing(null); }
      },
    });
  };

  const handleImport = (p) => {
    setConfirm({
      title: 'Importer dans le référentiel',
      message: `Créer une nouvelle entrée "${p.nom}" dans le référentiel commun et lier cette plateforme automatiquement ?`,
      confirmLabel: 'Importer',
      onConfirm: async () => {
        setConfirm(null); setActing(p.id);
        try {
          const r = await api.post(`/admin/plateformes-orphelines/${p.id}/importer`, {});
          setResult({ ok: true, msg: r.created ? `"${r.referentiel.nom}" créé dans le référentiel.` : `"${r.referentiel.nom}" existait déjà — plateforme liée.` });
          load();
        } catch (e) { setResult({ ok: false, msg: e.message }); }
        finally { setActing(null); }
      },
    });
  };

  const byUser = rows.reduce((acc, r) => { const k = r.user_email; if (!acc[k]) acc[k] = { display_name: r.user_display_name, plats: [] }; acc[k].plats.push(r); return acc; }, {});
  const totalSuggestions = rows.filter(r => r.suggestion).length;

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 20 }}>
        <div>
          <h2 style={{ margin: 0, fontSize: 18 }}>Plateformes suggérées</h2>
        <p style={{ margin: '4px 0 0', color: 'var(--text-muted)', fontSize: 13 }}>
          Plateformes créées par les utilisateurs non présentes dans le référentiel des plateformes connues.
          {totalSuggestions > 0 && <span style={{ color: '#f59e0b', marginLeft: 6 }}>⚡ {totalSuggestions} correspondance(s) suggérée(s) avec le référentiel existant.</span>}
        </p>
        </div>
        <button
          onClick={() => navigate('/admin/plateformes?section=referentiel')}
          style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '7px 14px',
            borderRadius: 6, border: '1px solid var(--border)', background: 'var(--surface-2)',
            color: 'var(--text-muted)', fontSize: 13, fontWeight: 500, cursor: 'pointer', flexShrink: 0 }}>
          ← Retour aux plateformes
        </button>
      </div>

      {err && <div className="error" style={{ marginBottom: 12 }}>{err}</div>}
      <ResultBanner result={result} onDismiss={() => { setResult(null); navigate('/admin/plateformes?section=referentiel'); }} style={{ marginBottom: 12 }} />

      {loading ? <p style={{ color: 'var(--text-muted)' }}>Chargement…</p>
       : Object.keys(byUser).length === 0
         ? <div className="card" style={{ textAlign: 'center', padding: 40, color: 'var(--text-muted)' }}>Aucune plateforme détectée.</div>
         : Object.entries(byUser).map(([email, { display_name, plats }]) => (
          <div key={email} className="card" style={{ marginBottom: 16 }}>
            <div style={{ marginBottom: 12, fontSize: 13, color: 'var(--text-muted)' }}>
              Plateforme déclarée par <strong style={{ color: 'var(--text)' }}>{display_name || email}</strong> ({email}) non présente dans le référentiel :
            </div>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
                  <th style={{ padding: '6px 12px', textAlign: 'left' }}>Plateforme</th>
                  <th style={{ padding: '6px 8px', textAlign: 'left' }}>Domiciliation</th>
                  <th style={{ padding: '6px 8px', textAlign: 'left' }}>Suggestion</th>
                  <th style={{ padding: '6px 12px', textAlign: 'right' }}>Actions</th>
                </tr>
              </thead>
              <tbody>
                {plats.map((p, i) => (
                  <tr key={p.id} style={{ borderBottom: i < plats.length - 1 ? '1px solid var(--border)' : 'none',
                    background: p.suggestion ? 'rgba(245,158,11,.04)' : 'transparent' }}>
                    <td style={{ padding: '10px 12px', fontWeight: 500 }}>{p.nom}</td>
                    <td style={{ padding: '10px 8px', color: 'var(--text-muted)', fontSize: 12 }}><span style={{ display:'inline-flex', alignItems:'center', gap:5 }}><FlagIcon code={p.domiciliation} size={15} />{countryLabel(p.domiciliation)}</span></td>
                    <td style={{ padding: '10px 8px' }}>
                      {p.suggestion ? (
                        <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, fontSize: 11, padding: '2px 8px', borderRadius: 10,
                          background: 'rgba(245,158,11,.15)', color: '#b45309', fontWeight: 600 }}>
                          ≈ {p.suggestion.referentiel_nom} ({p.suggestion.score}%)
                        </span>
                      ) : <span style={{ color: 'var(--text-muted)', fontSize: 12 }}>—</span>}
                    </td>
                    <td style={{ padding: '10px 12px', textAlign: 'right' }}>
                      <div style={{ display: 'flex', gap: 6, justifyContent: 'flex-end' }}>
                        {p.suggestion && (
                          <button
                            style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 12, padding: '4px 10px',
                              background: 'rgba(245,158,11,.12)', border: '1px solid rgba(245,158,11,.4)',
                              borderRadius: 6, color: '#b45309', cursor: 'pointer', whiteSpace: 'nowrap' }}
                            disabled={acting === p.id}
                            onClick={() => handleLier(p)}>
                            <IconLink /> {acting === p.id ? '…' : 'Lier'}
                          </button>
                        )}
                        <button
                          style={{ display: 'inline-flex', alignItems: 'center', gap: 5, fontSize: 12, padding: '4px 10px',
                            border: '1px solid var(--border)', borderRadius: 6, cursor: 'pointer',
                            background: 'var(--surface)', color: 'var(--text)', whiteSpace: 'nowrap' }}
                          disabled={acting === p.id}
                          onClick={() => handleImport(p)}>
                          {acting === p.id ? '…' : 'Importer'}
                        </button>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ))
      }

      {confirm && <ConfirmModal open title={confirm.title} message={confirm.message} confirmLabel={confirm.confirmLabel} onConfirm={confirm.onConfirm} onCancel={() => setConfirm(null)} />}
    </div>
  );
}

/* ── Icônes catégories / secteurs ────────────────────────────── */
function IconTag() {
  return <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"/><line x1="7" y1="7" x2="7.01" y2="7"/></svg>;
}
function IconLayers() {
  return <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg>;
}
function IconMerge() {
  return <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M8 6l4 4-4 4"/><path d="M16 6l-4 4 4 4"/><line x1="12" y1="10" x2="12" y2="20"/><line x1="8" y1="20" x2="16" y2="20"/></svg>;
}

/* ── Section générique catégories / secteurs ─────────────────── */
function RefListSection({ title, subtitle, apiPath, onRowClick, suggestType }) {
  const [items, setItems]   = useState([]);
  const [loading, setLoading] = useState(true);
  const [err, setErr]       = useState(null);
  const [suggestCount, setSuggestCount] = useState(0);

  // Création
  const [newNom, setNewNom] = useState('');
  const [adding, setAdding] = useState(false);

  // Édition inline
  const [editId, setEditId]   = useState(null);
  const [editNom, setEditNom] = useState('');
  const [saving, setSaving]   = useState(false);

  // Menu ⋮
  const [openMenu, setOpenMenu] = useState(null); // { item, x, y }

  // Suppression
  const [confirm, setConfirm] = useState(null);

  // Fusion
  const [mergeSource, setMergeSource] = useState(null);

  const navigate = useNavigate();

  const load = useCallback(() => {
    setLoading(true);
    api.get(apiPath)
      .then(data => { setItems(data); setErr(null); })
      .catch(e => setErr(e.message))
      .finally(() => setLoading(false));
  }, [apiPath]);

  useEffect(() => { load(); }, [load]);

  useEffect(() => {
    if (!suggestType) return;
    api.get('/admin/inv-suggestions-count')
      .then(d => setSuggestCount(suggestType === 'categories' ? d.cats : d.sects))
      .catch(() => {});
  }, [suggestType]);

  // Fermeture menu au scroll
  useEffect(() => {
    if (!openMenu) return;
    const close = () => setOpenMenu(null);
    window.addEventListener('scroll', close, true);
    return () => window.removeEventListener('scroll', close, true);
  }, [openMenu]);

  const handleAdd = async (e) => {
    e.preventDefault();
    if (!newNom.trim()) return;
    setAdding(true); setErr(null);
    try {
      await api.post(apiPath, { nom: newNom.trim() });
      setNewNom('');
      load();
    } catch (ex) { setErr(ex.message); }
    finally { setAdding(false); }
  };

  const startEdit = (item) => { setEditId(item.id); setEditNom(item.nom); };
  const cancelEdit = () => { setEditId(null); setEditNom(''); };

  const handleRename = async (e, id) => {
    e.preventDefault();
    if (!editNom.trim()) return;
    setSaving(true); setErr(null);
    try {
      await api.put(`${apiPath}/${id}`, { nom: editNom.trim() });
      cancelEdit();
      load();
    } catch (ex) { setErr(ex.message); }
    finally { setSaving(false); }
  };

  const handleDelete = (item) => {
    setConfirm({
      title: 'Confirmer la suppression',
      message: `Supprimer "${item.nom}" ?`,
      confirmLabel: 'Supprimer',
      onConfirm: async () => {
        setConfirm(null);
        try {
          await api.del(`${apiPath}/${item.id}`);
          load();
        } catch (ex) { setErr(ex.message); }
      },
    });
  };

  const openContextMenu = (e, item) => {
    e.stopPropagation();
    const rect = e.currentTarget.getBoundingClientRect();
    setOpenMenu({ item, x: rect.right - 160, y: rect.bottom + 4 });
  };

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 20 }}>
        <div>
          <h2 style={{ margin: 0, fontSize: 18 }}>{title}</h2>
          <p style={{ margin: '4px 0 0', color: 'var(--text-muted)', fontSize: 13 }}>{subtitle}</p>
        </div>
        {suggestType && (
          <button
            onClick={() => navigate('/admin/plateformes?section=inv-suggestions')}
            style={{
              padding: '7px 14px', borderRadius: 6, border: '1px solid',
              fontSize: 13, fontWeight: 600, cursor: 'pointer', flexShrink: 0,
              background: suggestCount > 0 ? 'rgba(239,68,68,.08)' : 'var(--surface-2)',
              color: suggestCount > 0 ? '#dc2626' : 'var(--text-muted)',
              borderColor: suggestCount > 0 ? 'rgba(239,68,68,.3)' : 'var(--border)',
            }}>
            {suggestCount} {suggestType === 'categories'
              ? `catégorie${suggestCount !== 1 ? 's' : ''} suggérée${suggestCount !== 1 ? 's' : ''}`
              : `secteur${suggestCount !== 1 ? 's' : ''} suggéré${suggestCount !== 1 ? 's' : ''}`}
          </button>
        )}
      </div>

      {err && <div className="error" style={{ marginBottom: 12 }}>{err}</div>}

      {/* Formulaire ajout */}
      <div className="card" style={{ marginBottom: 16, padding: '16px 20px' }}>
        <form onSubmit={handleAdd} style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
          <input
            value={newNom}
            onChange={e => setNewNom(e.target.value)}
            placeholder="Nouveau nom…"
            style={{ flex: 1, padding: '7px 12px', borderRadius: 7, border: '1px solid var(--border)',
              background: 'var(--surface)', color: 'var(--text)', fontSize: 13 }}
          />
          <button type="submit" disabled={adding || !newNom.trim()}
            style={{ padding: '7px 16px', borderRadius: 7, border: 'none', cursor: 'pointer',
              background: 'var(--primary)', color: '#fff', fontSize: 13, fontWeight: 600,
              opacity: adding || !newNom.trim() ? 0.6 : 1 }}>
            {adding ? '…' : 'Ajouter'}
          </button>
        </form>
      </div>

      {/* Liste */}
      {loading ? <p style={{ color: 'var(--text-muted)' }}>Chargement…</p>
       : items.length === 0
         ? <div className="card" style={{ textAlign: 'center', padding: 40, color: 'var(--text-muted)' }}>
             Aucun élément — commencez par en ajouter un.
           </div>
         : (
          <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
                  <th style={{ padding: '8px 16px', textAlign: 'left', fontWeight: 600, fontSize: 12, color: 'var(--text-muted)' }}>Nom</th>
                  <th style={{ padding: '8px 12px', textAlign: 'center', fontWeight: 600, fontSize: 12, color: 'var(--text-muted)', width: 140 }}>Utilisé par</th>
                  <th style={{ padding: '8px 12px', textAlign: 'right', width: 48 }}></th>
                </tr>
              </thead>
              <tbody>
                {items.map((item, i) => (
                  <tr key={item.id} style={{ borderBottom: i < items.length - 1 ? '1px solid var(--border)' : 'none' }}>
                    <td style={{ padding: '10px 16px' }}>
                      {editId === item.id ? (
                        <form onSubmit={e => handleRename(e, item.id)} style={{ display: 'flex', gap: 6 }}>
                          <input
                            autoFocus
                            value={editNom}
                            onChange={e => setEditNom(e.target.value)}
                            style={{ flex: 1, padding: '5px 10px', borderRadius: 6, border: '1px solid var(--primary)',
                              background: 'var(--surface)', color: 'var(--text)', fontSize: 13 }}
                          />
                          <button type="submit" disabled={saving}
                            style={{ padding: '5px 12px', borderRadius: 6, border: 'none', cursor: 'pointer',
                              background: 'var(--primary)', color: '#fff', fontSize: 12, fontWeight: 600 }}>
                            {saving ? '…' : 'OK'}
                          </button>
                          <button type="button" onClick={cancelEdit}
                            style={{ padding: '5px 10px', borderRadius: 6, border: '1px solid var(--border)',
                              background: 'var(--surface)', color: 'var(--text)', fontSize: 12, cursor: 'pointer' }}>
                            ✕
                          </button>
                        </form>
                      ) : (
                        <span
                          onClick={onRowClick ? () => onRowClick(item) : undefined}
                          style={{ fontWeight: 500,
                            cursor: onRowClick ? 'pointer' : 'default',
                            color: onRowClick ? 'var(--primary)' : 'inherit',
                            textDecoration: onRowClick ? 'underline' : 'none',
                            textDecorationColor: 'transparent',
                          }}
                          onMouseEnter={onRowClick ? e => { e.currentTarget.style.textDecorationColor = 'var(--primary)'; } : undefined}
                          onMouseLeave={onRowClick ? e => { e.currentTarget.style.textDecorationColor = 'transparent'; } : undefined}
                        >{item.nom}</span>
                      )}
                    </td>
                    <td style={{ padding: '10px 12px', textAlign: 'center' }}>
                      <span style={{ display: 'inline-block', padding: '2px 10px', borderRadius: 10, fontSize: 11, fontWeight: 600,
                        background: item.nb_utilises > 0 ? 'rgba(99,102,241,.12)' : 'var(--surface-2)',
                        color: item.nb_utilises > 0 ? '#6366f1' : 'var(--text-muted)' }}>
                        {item.nb_utilises} plateforme{item.nb_utilises !== 1 ? 's' : ''}
                      </span>
                    </td>
                    <td style={{ padding: '10px 12px', textAlign: 'right' }}>
                      {editId !== item.id && (
                        <button
                          onClick={e => openContextMenu(e, item)}
                          style={{ background: 'none', border: 'none', cursor: 'pointer', padding: '4px 6px',
                            borderRadius: 6, color: 'var(--text-muted)', fontSize: 18, lineHeight: 1,
                            display: 'inline-flex', alignItems: 'center' }}
                          title="Actions">
                          ⋮
                        </button>
                      )}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )
      }

      {/* Menu contextuel */}
      {openMenu && (
        <>
          <div style={{ position: 'fixed', inset: 0, zIndex: 999 }} onClick={() => setOpenMenu(null)} />
          <div style={{ position: 'fixed', left: openMenu.x, top: openMenu.y, zIndex: 1000,
            background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 10,
            boxShadow: '0 4px 20px rgba(0,0,0,.15)', minWidth: 160, overflow: 'hidden' }}>
            {[
              { icon: <IconEdit />, label: 'Renommer', onClick: () => { setOpenMenu(null); startEdit(openMenu.item); } },
              {
                icon: <IconMerge />,
                label: 'Fusionner avec…',
                disabled: items.length < 2,
                title: items.length < 2 ? 'Aucune autre entrée disponible' : '',
                onClick: () => { const it = openMenu.item; setOpenMenu(null); setMergeSource(it); },
                color: '#7c3aed',
              },
              {
                icon: <IconTrash />,
                label: 'Supprimer',
                disabled: openMenu.item.nb_utilises > 0,
                title: openMenu.item.nb_utilises > 0 ? 'Retirez-le des plateformes avant de le supprimer' : '',
                onClick: () => { const it = openMenu.item; setOpenMenu(null); handleDelete(it); },
                color: 'var(--danger)',
              },
            ].map(action => (
              <button key={action.label}
                disabled={action.disabled}
                title={action.title || ''}
                onClick={action.onClick}
                style={{ display: 'flex', alignItems: 'center', gap: 8, width: '100%', textAlign: 'left', padding: '8px 14px',
                  background: 'none', border: 'none', cursor: action.disabled ? 'not-allowed' : 'pointer',
                  fontSize: 13, color: action.disabled ? 'var(--text-muted)' : (action.color || 'var(--text)'),
                  opacity: action.disabled ? 0.5 : 1 }}
                onMouseEnter={e => { if (!action.disabled) e.currentTarget.style.background = 'var(--surface-2)'; }}
                onMouseLeave={e => e.currentTarget.style.background = 'none'}>
                <span style={{ opacity: 0.7, flexShrink: 0, display: 'flex' }}>{action.icon}</span>
                {action.label}
              </button>
            ))}
          </div>
        </>
      )}

      {confirm && <ConfirmModal open title={confirm.title} message={confirm.message} confirmLabel={confirm.confirmLabel} onConfirm={confirm.onConfirm} onCancel={() => setConfirm(null)} />}
      {mergeSource && (
        <MergeModal
          source={mergeSource}
          items={items}
          apiPath={apiPath}
          onClose={() => setMergeSource(null)}
          onDone={() => { setMergeSource(null); load(); }}
        />
      )}
    </div>
  );
}

/* ── Modal de fusion catégorie/secteur ───────────────────────── */
function MergeModal({ source, items, apiPath, onClose, onDone }) {
  const others = items.filter(i => i.id !== source.id);
  const [targetId, setTargetId] = useState(others[0]?.id ?? '');
  const [loading, setLoading]   = useState(false);
  const [result, setResult]     = useState(null);
  const [err, setErr]           = useState(null);

  const target = others.find(i => i.id === Number(targetId));

  const handleMerge = async () => {
    if (!targetId) return;
    setLoading(true); setErr(null);
    try {
      const res = await api.post(`${apiPath}/${source.id}/merge`, { target_id: Number(targetId) });
      setResult(res.message);
    } catch (ex) { setErr(ex.message); }
    finally { setLoading(false); }
  };

  return (
    <Modal open title={`Fusionner — ${source.nom}`} onClose={result ? onDone : onClose} width={480}
      footer={result ? (
        <button className="primary" onClick={onDone}>Fermer</button>
      ) : (
        <>
          <button onClick={onClose} disabled={loading}>Annuler</button>
          <button className="primary" onClick={handleMerge} disabled={loading || !targetId}
            style={{ background: '#7c3aed' }}>
            {loading ? 'Fusion…' : 'Fusionner'}
          </button>
        </>
      )}>
      {result ? (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
          <div style={{ padding: '12px 16px', borderRadius: 8, background: 'rgba(34,197,94,.1)',
            color: '#16a34a', border: '1px solid rgba(34,197,94,.3)', fontSize: 13 }}>
            ✓ {result}
          </div>
        </div>
      ) : (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <p style={{ margin: 0, fontSize: 13, color: 'var(--text-muted)' }}>
            Les plateformes du référentiel qui ont <strong style={{ color: 'var(--text)' }}>{source.nom}</strong> recevront
            la catégorie cible si elles ne l'ont pas déjà. La catégorie source sera ensuite supprimée.
          </p>
          <div>
            <label style={{ display: 'block', marginBottom: 6, fontSize: 12, fontWeight: 600,
              textTransform: 'uppercase', color: 'var(--text-muted)', letterSpacing: '.05em' }}>
              Fusionner dans
            </label>
            <select value={targetId} onChange={e => setTargetId(e.target.value)}
              style={{ width: '100%', padding: '8px 12px', borderRadius: 8, border: '1px solid var(--border)',
                background: 'var(--surface)', color: 'var(--text)', fontSize: 13 }}>
              {others.map(o => (
                <option key={o.id} value={o.id}>
                  {o.nom}{o.nb_utilises > 0 ? ` — ${o.nb_utilises} plateforme(s)` : ''}
                </option>
              ))}
            </select>
          </div>
          {target && (
            <div style={{ padding: '10px 14px', borderRadius: 8, background: 'rgba(124,58,237,.06)',
              border: '1px solid rgba(124,58,237,.2)', fontSize: 12, color: 'var(--text-muted)' }}>
              <strong style={{ color: '#7c3aed' }}>{source.nom}</strong>
              {' '}({source.nb_utilises} plateforme(s)) →{' '}
              <strong style={{ color: '#7c3aed' }}>{target.nom}</strong>
              {' '}({target.nb_utilises} plateforme(s))
            </div>
          )}
          {err && <div className="error">{err}</div>}
        </div>
      )}
    </Modal>
  );
}

/* ── Navigation ───────────────────────────────────────────────── */

/* ── Catégories & secteurs suggérés ─────────────────────────── */
function InvSuggestionsSection() {
  const navigate = useNavigate();
  const [data,       setData]      = useState(null);
  const [loading,    setLoading]   = useState(true);
  const [tab,        setTab]       = useState('categories');
  const [result,     setResult]    = useState(null);
  const [confirming, setConfirming] = useState(null);

  const load = async () => {
    setLoading(true);
    try {
      const d = await api.get('/admin/inv-suggestions');
      setData(d);
    } catch (e) { console.error(e); }
    finally { setLoading(false); }
  };

  useEffect(() => { load(); }, []);

  const promouvoir = async (type, row) => {
    try {
      const r = await api.post(`/admin/inv-suggestions/${type}/${row.id}/promouvoir`);
      setResult({ ok: true, msg: r.msg });
      load();
    } catch (e) { setResult({ ok: false, msg: e.message }); }
  };

  const supprimer = async (type, row) => {
    try {
      const r = await api.del(`/admin/inv-suggestions/${type}/${row.id}`);
      setResult({ ok: true, msg: r.msg });
      load();
    } catch (e) { setResult({ ok: false, msg: e.message }); }
  };

  const rows     = tab === 'categories' ? (data?.categories || []) : (data?.secteurs || []);
  const typeKey  = tab === 'categories' ? 'categories' : 'secteurs';
  const chipClass = tab === 'categories' ? 'chip-cat' : 'chip-sect';
  const emptyLabel = tab === 'categories' ? 'Aucune catégorie suggérée' : 'Aucun secteur suggéré';

  const byUser = rows.reduce((acc, r) => {
    const k = r.email;
    if (!acc[k]) acc[k] = { display_name: r.display_name, email: r.email, items: [] };
    acc[k].items.push(r);
    return acc;
  }, {});

  return (
    <div style={{ padding: 24 }}>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 20 }}>
        <div>
          <h2 style={{ margin: 0, fontSize: 18 }}>Tags suggérés</h2>
          <p style={{ margin: '4px 0 0', color: 'var(--text-muted)', fontSize: 13 }}>
            Catégories et secteurs créés par les utilisateurs, non présents dans le référentiel global.
          </p>
        </div>
        <button onClick={() => navigate('/admin/plateformes?section=categories')}
          style={{ fontSize: 12, padding: '5px 12px', borderRadius: 6, border: '1px solid var(--border)',
            background: 'var(--surface-2)', color: 'var(--text-muted)', cursor: 'pointer', flexShrink: 0 }}>
          ← Retour aux catégories
        </button>
      </div>

      <ResultBanner result={result} onDismiss={() => setResult(null)} style={{ marginBottom: 16 }} />

      <div className="dr-tabs" style={{ marginBottom: 20 }}>
        <button className={`dr-tab${tab === 'categories' ? ' active' : ''}`} onClick={() => setTab('categories')}>
          Catégories
          {data && data.categories.length > 0 && (
            <span style={{ marginLeft: 6, background: 'rgba(239,68,68,.15)', color: '#dc2626',
              borderRadius: 10, padding: '1px 7px', fontSize: 11, fontWeight: 600 }}>
              {data.categories.length}
            </span>
          )}
        </button>
        <button className={`dr-tab${tab === 'secteurs' ? ' active' : ''}`} onClick={() => setTab('secteurs')}>
          Secteurs
          {data && data.secteurs.length > 0 && (
            <span style={{ marginLeft: 6, background: 'rgba(239,68,68,.15)', color: '#dc2626',
              borderRadius: 10, padding: '1px 7px', fontSize: 11, fontWeight: 600 }}>
              {data.secteurs.length}
            </span>
          )}
        </button>
      </div>

      {loading ? (
        <p style={{ color: 'var(--text-muted)' }}>Chargement…</p>
      ) : rows.length === 0 ? (
        <div className="card" style={{ textAlign: 'center', padding: 40, color: 'var(--text-muted)' }}>
          {emptyLabel}
        </div>
      ) : (
        Object.entries(byUser).map(([email, { display_name, items }]) => (
          <div key={email} className="card" style={{ marginBottom: 16 }}>
            <div style={{ fontSize: 12, color: 'var(--text-muted)', marginBottom: 12, fontWeight: 500 }}>
              {display_name ? `Suggéré par ${display_name} (${email}) :` : `Suggéré par ${email} :`}
            </div>
            <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
              <thead>
                <tr style={{ borderBottom: '1px solid var(--border)' }}>
                  <th style={{ textAlign: 'left', padding: '6px 8px', color: 'var(--text-muted)', fontWeight: 500 }}>Nom</th>
                  <th style={{ textAlign: 'center', padding: '6px 8px', color: 'var(--text-muted)', fontWeight: 500 }}>Plateformes</th>
                  <th style={{ textAlign: 'center', padding: '6px 8px', color: 'var(--text-muted)', fontWeight: 500 }}>Investissements</th>
                  <th style={{ textAlign: 'right', padding: '6px 8px' }}></th>
                </tr>
              </thead>
              <tbody>
                {items.map(row => (
                  <tr key={row.id} style={{ borderBottom: '1px solid var(--border)' }}>
                    <td style={{ padding: '8px' }}><span className={chipClass}>{row.nom}</span></td>
                    <td style={{ textAlign: 'center', padding: '8px', color: 'var(--text-muted)' }}>{row.nb_plateformes}</td>
                    <td style={{ textAlign: 'center', padding: '8px', color: 'var(--text-muted)' }}>{row.nb_investissements}</td>
                    <td style={{ textAlign: 'right', padding: '8px' }}>
                      <button onClick={() => setConfirming({ type: 'promouvoir', typeKey, row })}
                        style={{ fontSize: 12, padding: '4px 10px', marginRight: 6,
                          background: 'rgba(99,102,241,.1)', color: 'var(--primary)',
                          border: '1px solid rgba(99,102,241,.25)', borderRadius: 6, cursor: 'pointer' }}>
                        Promouvoir
                      </button>
                      <button onClick={() => setConfirming({ type: 'supprimer', typeKey, row })}
                        style={{ fontSize: 12, padding: '4px 10px',
                          background: 'rgba(239,68,68,.08)', color: '#dc2626',
                          border: '1px solid rgba(239,68,68,.2)', borderRadius: 6, cursor: 'pointer' }}>
                        Supprimer
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ))
      )}

      {confirming?.type === 'promouvoir' && (
        <ConfirmModal open
          title="Promouvoir en global"
          message={`Rendre "${confirming.row.nom}" visible par tous les utilisateurs ?`}
          confirmLabel="Promouvoir"
          onConfirm={() => { promouvoir(confirming.typeKey, confirming.row); setConfirming(null); }}
          onClose={() => setConfirming(null)} />
      )}
      {confirming?.type === 'supprimer' && (
        <ConfirmModal open danger
          title="Supprimer ce tag"
          message={`Supprimer définitivement "${confirming.row.nom}" ?${confirming.row.nb_plateformes + confirming.row.nb_investissements > 0 ? ' Ce tag est déjà utilisé.' : ''}`}
          confirmLabel="Supprimer"
          onConfirm={() => { supprimer(confirming.typeKey, confirming.row); setConfirming(null); }}
          onClose={() => setConfirming(null)} />
      )}
    </div>
  );
}


/* ═══════════════════════════════════════════════════════════════
   ICÔNES GARANTIES / NOTATION
   ═══════════════════════════════════════════════════════════════ */
function IconShield() {
  return <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>;
}
function IconStar() {
  return <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>;
}
function IconImportGar() {
  return <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 14 12 9 17 14"/><line x1="12" y1="9" x2="12" y2="21"/></svg>;
}
function IconExportBtn() {
  return <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>;
}

/* ── Export helpers ───────────────────────────────────────────── */
function dlBlob(content, filename, type) {
  const blob = new Blob([content], { type });
  const url  = URL.createObjectURL(blob);
  const a    = document.createElement('a');
  a.href = url; a.download = filename; a.click();
  setTimeout(() => URL.revokeObjectURL(url), 1000);
}
function garantiesToCSV(rows) {
  const BOM = '\uFEFF';
  const sep = ';';
  const q   = v => `"${String(v ?? '').replace(/"/g, '\"\"')}"`;
  const headers = ['ID', 'Ordre', 'Libellé', 'Description'];
  const data = rows.map(r => [r.id, r.ordre, r.libelle, r.description || '']);
  return BOM + [headers, ...data].map(row => row.map(q).join(sep)).join('\r\n');
}
function garantiesToJSON(rows) {
  return JSON.stringify({
    exported_at: new Date().toISOString(),
    garanties: rows.map(({ id, ordre, libelle, description }) => ({ id, ordre, libelle, description })),
  }, null, 2);
}

function GarExportDropdown({ disabled, rows }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    if (!open) return;
    const handler = (e) => { if (!ref.current?.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, [open]);
  return (
    <div ref={ref} style={{ position: 'relative' }}>
      <button type="button" className="icon-btn" disabled={disabled}
        onClick={() => setOpen(o => !o)} title="Exporter">
        <IconExportBtn />
      </button>
      {open && (
        <div className="export-dropdown" role="menu">
          <button role="menuitem" onClick={() => { setOpen(false); dlBlob(garantiesToCSV(rows), 'garanties.csv', 'text/csv;charset=utf-8'); }}>
            <span><strong>Format CSV</strong><small>Compatible Excel, LibreOffice</small></span>
          </button>
          <button role="menuitem" onClick={() => { setOpen(false); dlBlob(garantiesToJSON(rows), 'garanties.json', 'application/json'); }}>
            <span><strong>Format JSON</strong><small>Données structurées</small></span>
          </button>
        </div>
      )}
    </div>
  );
}

/* ═══════════════════════════════════════════════════════════════
   SECTION GARANTIES
   ═══════════════════════════════════════════════════════════════ */
const EMPTY_GAR = { libelle: '', description: '', ordre: '' };

function GarantiesSection() {
  const [garanties,    setGaranties]    = useState([]);
  const [loading,      setLoading]      = useState(true);
  const [newRow,       setNewRow]       = useState(EMPTY_GAR);
  const [editId,       setEditId]       = useState(null);
  const [editRow,      setEditRow]      = useState({});
  const [err,          setErr]          = useState(null);
  const [saving,       setSaving]       = useState(false);
  const [importResult, setImportResult] = useState(null);
  const [importing,    setImporting]    = useState(false);
  const [importErr,    setImportErr]    = useState(null);
  const [deleteConfirm, setDeleteConfirm] = useState(null);
  const importRef = useRef(null);

  const load = useCallback(async () => {
    try { setLoading(true); setGaranties(await api.get('/garanties')); }
    catch (e) { setErr(e.message); }
    finally { setLoading(false); }
  }, []);
  useEffect(() => { load(); }, [load]);

  const handleImport = async (e) => {
    const file = e.target.files[0];
    if (!importRef.current) return;
    importRef.current.value = '';
    if (!file) return;
    setImporting(true); setImportErr(null); setImportResult(null);
    try {
      const fd = new FormData();
      fd.append('file', file);
      const r = await api.upload('/garanties/import', fd);
      setImportResult(r);
      load();
    } catch (ex) { setImportErr(ex.message); }
    finally { setImporting(false); }
  };

  const startEdit  = (g) => { setEditId(g.id); setEditRow({ libelle: g.libelle, description: g.description || '', ordre: String(g.ordre ?? 0) }); setErr(null); };
  const cancelEdit = () => { setEditId(null); setEditRow({}); setErr(null); };

  const saveEdit = async (g) => {
    if (!editRow.libelle?.trim()) { setErr('Le libellé est requis.'); return; }
    setSaving(true); setErr(null);
    try {
      await api.put(`/garanties/${g.id}`, { libelle: editRow.libelle.trim(), description: editRow.description?.trim() || null, ordre: Number(editRow.ordre || 0) });
      cancelEdit(); load();
    } catch (ex) { setErr(ex.message); }
    finally { setSaving(false); }
  };

  const saveNew = async () => {
    if (!newRow.libelle?.trim()) { setErr('Le libellé est requis.'); return; }
    setSaving(true); setErr(null);
    try {
      await api.post('/garanties', { libelle: newRow.libelle.trim(), description: newRow.description?.trim() || null, ordre: Number(newRow.ordre || 0) });
      setNewRow(EMPTY_GAR); load();
    } catch (ex) { setErr(ex.message); }
    finally { setSaving(false); }
  };

  const del = (id) => {
    setDeleteConfirm({
      message: 'Supprimer ce type de garantie ?',
      onConfirm: async () => {
        try { await api.del(`/garanties/${id}`); load(); }
        catch (ex) { setErr(ex.message); }
        finally { setDeleteConfirm(null); }
      },
    });
  };

  return (
    <>
    <div>
      <div style={{ display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', marginBottom: 20 }}>
        <div>
          <h2 style={{ margin: 0, fontSize: 18 }}>Types de garanties</h2>
          <p style={{ margin: '4px 0 0', color: 'var(--text-muted)', fontSize: 13 }}>
            Référentiel global des garanties associables à un investissement.
          </p>
        </div>
        <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
          <label title="Importer (.xlsx, .csv, .json)" style={{
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            width: 32, height: 32, borderRadius: 6, cursor: 'pointer',
            border: '1px solid var(--border)', background: 'var(--surface)',
            color: 'var(--text-muted)',
          }}>
            {importing ? '…' : <IconImportGar />}
            <input ref={importRef} type="file" accept=".xlsx,.xls,.csv,.json"
              style={{ display: 'none' }} disabled={importing} onChange={handleImport} />
          </label>
          <GarExportDropdown disabled={garanties.length === 0} rows={garanties} />
        </div>
      </div>

      {err       && <div className="error"       style={{ marginBottom: 10 }}>{err}</div>}
      {importErr && <div className="error"       style={{ marginBottom: 10 }}>{importErr}</div>}
      {importResult && (
        <div className="success-msg" style={{ marginBottom: 10 }}>
          ✔ Import terminé — {importResult.inserted} créée(s), {importResult.updated} mise(s) à jour
          {importResult.skipped > 0 && `, ${importResult.skipped} ignorée(s)`}.
        </div>
      )}

      <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
        {loading ? (
          <div style={{ padding: 32, textAlign: 'center', color: 'var(--text-muted)' }}>Chargement…</div>
        ) : (
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
            <thead>
              <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
                <th style={{ padding: '10px 12px', width: 48, textAlign: 'center', fontWeight: 600 }}>#</th>
                <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600, width: '24%' }}>Libellé</th>
                <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600 }}>Description</th>
                <th style={{ padding: '10px 12px', width: 100 }} />
              </tr>
            </thead>
            <tbody>
              {garanties.length === 0 && editId === null && (
                <tr><td colSpan={4} style={{ padding: 32, textAlign: 'center', color: 'var(--text-muted)', fontStyle: 'italic' }}>Aucun type de garantie défini.</td></tr>
              )}
              {garanties.map((g, i) => (
                <tr key={g.id} style={{ borderBottom: i < garanties.length - 1 ? '1px solid var(--border)' : 'none', verticalAlign: 'top' }}>
                  {editId === g.id ? (
                    <>
                      <td style={{ padding: '8px 12px' }}><input type="number" min="0" value={editRow.ordre} style={{ width: 52 }} onChange={e => setEditRow({ ...editRow, ordre: e.target.value })} /></td>
                      <td style={{ padding: '8px 8px' }}><input required autoFocus value={editRow.libelle} placeholder="Libellé *" onChange={e => setEditRow({ ...editRow, libelle: e.target.value })} onKeyDown={e => { if (e.key === 'Enter') saveEdit(g); if (e.key === 'Escape') cancelEdit(); }} /></td>
                      <td style={{ padding: '8px 8px' }}><textarea rows={2} value={editRow.description} placeholder="Description…" style={{ width: '100%', resize: 'vertical', fontSize: 13 }} onChange={e => setEditRow({ ...editRow, description: e.target.value })} /></td>
                      <td style={{ padding: '8px 12px' }}>
                        <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                          <button className="primary" style={{ padding: '3px 10px', fontSize: 11 }} disabled={saving} onClick={() => saveEdit(g)}>{saving ? '…' : '✓ OK'}</button>
                          <button style={{ padding: '3px 10px', fontSize: 11 }} onClick={cancelEdit}>Annuler</button>
                        </div>
                      </td>
                    </>
                  ) : (
                    <>
                      <td style={{ padding: '8px 12px', textAlign: 'center', color: 'var(--text-muted)', fontSize: 11 }}>{g.ordre}</td>
                      <td style={{ padding: '8px 8px', fontWeight: 500 }}>{g.libelle}</td>
                      <td style={{ padding: '8px 8px', fontSize: 12, color: 'var(--text-muted)', whiteSpace: 'pre-wrap' }}>{g.description || <em style={{ opacity: .5 }}>—</em>}</td>
                      <td style={{ padding: '8px 12px' }}>
                        <div style={{ display: 'flex', gap: 4 }}>
                          <button style={{ padding: '3px 8px', fontSize: 11 }} onClick={() => { cancelEdit(); startEdit(g); }}>Éditer</button>
                          <button style={{ padding: '3px 8px', fontSize: 11, background: 'rgba(239,68,68,.08)', color: '#dc2626', border: '1px solid rgba(239,68,68,.2)', borderRadius: 4, cursor: 'pointer' }} onClick={() => del(g.id)}>✕</button>
                        </div>
                      </td>
                    </>
                  )}
                </tr>
              ))}
              {/* Ligne d'ajout */}
              <tr style={{ borderTop: '2px solid var(--border)', verticalAlign: 'top' }}>
                <td style={{ padding: '8px 12px' }}><input type="number" min="0" value={newRow.ordre} style={{ width: 52 }} placeholder="0" onChange={e => setNewRow({ ...newRow, ordre: e.target.value })} /></td>
                <td style={{ padding: '8px 8px' }}><input value={newRow.libelle} placeholder="Nouveau libellé *" onChange={e => setNewRow({ ...newRow, libelle: e.target.value })} onKeyDown={e => { if (e.key === 'Enter') saveNew(); }} /></td>
                <td style={{ padding: '8px 8px' }}><textarea rows={2} value={newRow.description} placeholder="Description (optionnelle)…" style={{ width: '100%', resize: 'vertical', fontSize: 13 }} onChange={e => setNewRow({ ...newRow, description: e.target.value })} /></td>
                <td style={{ padding: '8px 12px', paddingTop: 12 }}>
                  <button className="primary" style={{ padding: '3px 10px', fontSize: 11, whiteSpace: 'nowrap' }} disabled={saving || !newRow.libelle.trim()} onClick={saveNew}>
                    {saving ? '…' : '+ Ajouter'}
                  </button>
                </td>
              </tr>
            </tbody>
          </table>
        )}
      </div>
    </div>
    <ConfirmModal
      open={!!deleteConfirm}
      message={deleteConfirm?.message}
      onConfirm={deleteConfirm?.onConfirm}
      onCancel={() => setDeleteConfirm(null)}
    />
    </>
  );
}

/* ═══════════════════════════════════════════════════════════════
   SECTION NOTATION — référentiel
   ═══════════════════════════════════════════════════════════════ */
const TYPE_LABELS = {
  etoiles: '⭐ Étoiles (1 – 5)',
  lettres: '🔤 Lettres (ex. A, B, C…)',
  score:   '🔢 Score numérique',
  custom:  '🏷️ Valeurs personnalisées',
};

const EMPTY_NOTATION_FORM = {
  nom: '', type: 'etoiles', valeurs: '', min_val: '0', max_val: '10', description: '', ordre: '0',
};

function NotationRefSection() {
  const [refs,     setRefs]     = useState([]);    // plateformes référentiel
  const [selRef,   setSelRef]   = useState('');    // id sélectionné
  const [criteres, setCriteres] = useState([]);
  const [busy,     setBusy]     = useState(false);
  const [form,     setForm]     = useState(EMPTY_NOTATION_FORM);
  const [editing,  setEditing]  = useState(null);
  const [err,      setErr]      = useState(null);
  const [saving,   setSaving]   = useState(false);
  const [deleteConfirm, setDeleteConfirm] = useState(null);

  // Charger la liste des plateformes référentiel
  useEffect(() => {
    api.get('/referentiel').then(data => setRefs(data)).catch(() => {});
  }, []);

  // Charger les critères quand la plateforme change
  const loadCriteres = useCallback(async (refId) => {
    if (!refId) { setCriteres([]); return; }
    setBusy(true);
    try { setCriteres(await api.get(`/referentiel/${refId}/notation`)); }
    catch (e) { setErr(e.message); }
    finally { setBusy(false); }
  }, []);
  useEffect(() => { loadCriteres(selRef); }, [selRef, loadCriteres]);

  const resetForm = () => { setForm(EMPTY_NOTATION_FORM); setEditing(null); setErr(null); };

  const openEdit = (c) => {
    setEditing(c);
    setForm({
      nom: c.nom, type: c.type,
      valeurs:     Array.isArray(c.valeurs) ? c.valeurs.join(', ') : '',
      min_val:     String(c.min_val ?? 0),
      max_val:     String(c.max_val ?? 10),
      description: c.description || '',
      ordre:       String(c.ordre ?? 0),
    });
    setErr(null);
  };

  const buildPayload = () => ({
    nom:         form.nom.trim(),
    type:        form.type,
    valeurs:     (form.type === 'lettres' || form.type === 'custom')
                   ? form.valeurs.split(',').map(v => v.trim()).filter(Boolean)
                   : undefined,
    min_val:     form.type === 'score' ? Number(form.min_val) : undefined,
    max_val:     form.type === 'score' ? Number(form.max_val) : undefined,
    description: form.description || undefined,
    ordre:       Number(form.ordre || 0),
  });

  const save = async (e) => {
    e.preventDefault(); setSaving(true); setErr(null);
    try {
      if (editing) {
        await api.put(`/referentiel/notation/${editing.id}`, buildPayload());
      } else {
        await api.post(`/referentiel/${selRef}/notation`, buildPayload());
      }
      resetForm();
      loadCriteres(selRef);
    } catch (ex) { setErr(ex.message); }
    finally { setSaving(false); }
  };

  const del = (id) => {
    setDeleteConfirm({
      message: 'Supprimer ce critère ?',
      onConfirm: async () => {
        try { await api.del(`/referentiel/notation/${id}`); loadCriteres(selRef); }
        catch (ex) { setErr(ex.message); }
        finally { setDeleteConfirm(null); }
      },
    });
  };

  return (
    <>
    <div>
      <div style={{ marginBottom: 20 }}>
        <h2 style={{ margin: 0, fontSize: 18 }}>Notation des plateformes</h2>
        <p style={{ margin: '4px 0 0', color: 'var(--text-muted)', fontSize: 13 }}>
          Définissez les critères de notation propres à chaque plateforme du référentiel (risque, qualité emprunteur, rendement, etc.).
        </p>
      </div>

      <div style={{ marginBottom: 20 }}>
        <label style={{ display: 'block', marginBottom: 6, fontSize: 13, fontWeight: 500 }}>Plateforme</label>
        <select value={selRef} onChange={e => { setSelRef(e.target.value); resetForm(); }} style={{ maxWidth: 340 }}>
          <option value="">— Choisir une plateforme —</option>
          {refs.map(r => <option key={r.id} value={r.id}>{r.nom}</option>)}
        </select>
      </div>

      {!selRef && (
        <p style={{ color: 'var(--text-muted)', fontSize: 13, fontStyle: 'italic' }}>
          Sélectionnez une plateforme pour gérer ses critères de notation.
        </p>
      )}

      {selRef && (
        <>
          {err && <div className="error" style={{ marginBottom: 12 }}>{err}</div>}

          {busy ? (
            <p style={{ color: 'var(--text-muted)' }}>Chargement…</p>
          ) : criteres.length === 0 ? (
            <p style={{ color: 'var(--text-muted)', fontSize: 13, fontStyle: 'italic' }}>
              Aucun critère défini pour cette plateforme.
            </p>
          ) : (
            <div className="card" style={{ padding: 0, overflow: 'hidden', marginBottom: 20 }}>
              <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
                <thead>
                  <tr style={{ borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
                    <th style={{ padding: '10px 12px', width: 32, fontWeight: 600 }}>#</th>
                    <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600 }}>Critère</th>
                    <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600 }}>Type</th>
                    <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600 }}>Barème</th>
                    <th style={{ padding: '10px 8px', textAlign: 'left', fontWeight: 600 }}>Description</th>
                    <th style={{ padding: '10px 12px', width: 80 }} />
                  </tr>
                </thead>
                <tbody>
                  {criteres.map((c, i) => (
                    <tr key={c.id} style={{
                      borderBottom: i < criteres.length - 1 ? '1px solid var(--border)' : 'none',
                      background: editing?.id === c.id ? 'rgba(59,130,246,.04)' : 'transparent',
                    }}>
                      <td style={{ padding: '8px 12px', textAlign: 'center', color: 'var(--text-muted)', fontSize: 11 }}>{c.ordre}</td>
                      <td style={{ padding: '8px 8px', fontWeight: 500 }}>{c.nom}</td>
                      <td style={{ padding: '8px 8px' }}>
                        <span className="badge en_cours" style={{ fontSize: 11 }}>{TYPE_LABELS[c.type] ?? c.type}</span>
                      </td>
                      <td style={{ padding: '8px 8px', fontSize: 12, color: 'var(--text-muted)' }}>
                        {c.type === 'etoiles' && '1 — 5 ⭐'}
                        {c.type === 'score'   && `${c.min_val} — ${c.max_val}`}
                        {(c.type === 'lettres' || c.type === 'custom') && Array.isArray(c.valeurs) && c.valeurs.join(' · ')}
                      </td>
                      <td style={{ padding: '8px 8px', fontSize: 12, color: 'var(--text-muted)' }}>{c.description}</td>
                      <td style={{ padding: '8px 12px' }}>
                        <div style={{ display: 'flex', gap: 4 }}>
                          <button style={{ padding: '3px 8px', fontSize: 11 }} onClick={() => openEdit(c)}>Éditer</button>
                          <button style={{ padding: '3px 8px', fontSize: 11, background: 'rgba(239,68,68,.08)', color: '#dc2626', border: '1px solid rgba(239,68,68,.2)', borderRadius: 4, cursor: 'pointer' }} onClick={() => del(c.id)}>✕</button>
                        </div>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}

          <div className="card" style={{ marginTop: 8 }}>
            <h4 style={{ margin: '0 0 12px', fontSize: 14 }}>
              {editing ? `Modifier le critère « ${editing.nom} »` : 'Ajouter un critère'}
            </h4>
            {err && !criteres.length && <div className="error" style={{ marginBottom: 10 }}>{err}</div>}
            <form onSubmit={save}>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12 }}>
                <div style={{ gridColumn: 'span 2' }}>
                  <label>Nom du critère *</label>
                  <input required value={form.nom} placeholder="ex. Risque emprunteur, Qualité projet…"
                    onChange={e => setForm({ ...form, nom: e.target.value })} />
                </div>
                <div>
                  <label>Ordre</label>
                  <input type="number" min="0" value={form.ordre} onChange={e => setForm({ ...form, ordre: e.target.value })} />
                </div>
                <div>
                  <label>Type de notation *</label>
                  <select value={form.type} onChange={e => setForm({ ...form, type: e.target.value })}>
                    {Object.entries(TYPE_LABELS).map(([k, v]) => <option key={k} value={k}>{v}</option>)}
                  </select>
                </div>
                {form.type === 'score' && (
                  <>
                    <div><label>Valeur min *</label><input type="number" step="any" required value={form.min_val} onChange={e => setForm({ ...form, min_val: e.target.value })} /></div>
                    <div><label>Valeur max *</label><input type="number" step="any" required value={form.max_val} onChange={e => setForm({ ...form, max_val: e.target.value })} /></div>
                  </>
                )}
                {(form.type === 'lettres' || form.type === 'custom') && (
                  <div style={{ gridColumn: 'span 2' }}>
                    <label>Valeurs possibles * <span style={{ fontSize: 11, fontWeight: 400, color: 'var(--text-muted)' }}>(séparées par des virgules)</span></label>
                    <input required value={form.valeurs}
                      placeholder={form.type === 'lettres' ? 'ex. A+, A, B+, B, C, D' : 'ex. Excellent, Bon, Moyen, Faible'}
                      onChange={e => setForm({ ...form, valeurs: e.target.value })} />
                  </div>
                )}
                <div style={{ gridColumn: 'span 3' }}>
                  <label>Description <span style={{ fontSize: 11, fontWeight: 400, color: 'var(--text-muted)' }}>(optionnelle)</span></label>
                  <input value={form.description} placeholder="ex. Évalue la solidité financière de l'emprunteur"
                    onChange={e => setForm({ ...form, description: e.target.value })} />
                </div>
              </div>
              <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
                <button className="primary" type="submit" disabled={saving}>
                  {editing ? 'Enregistrer' : 'Ajouter le critère'}
                </button>
                {editing && <button type="button" onClick={resetForm}>Annuler</button>}
              </div>
            </form>
          </div>
        </>
      )}
    </div>

    <ConfirmModal
      open={!!deleteConfirm}
      message={deleteConfirm?.message}
      onConfirm={deleteConfirm?.onConfirm}
      onCancel={() => setDeleteConfirm(null)}
    />
    </>
  );
}

const NAV = [
  { id: 'referentiel', label: 'Plateformes',                  icon: <IconDatabase /> },
  { id: 'logos-ref',   label: 'Logos des plateformes',        icon: <IconImage /> },
  { id: 'categories',  label: "Catégories d'investissement",  icon: <IconTag /> },
  { id: 'secteurs',    label: "Secteurs d'investissement",    icon: <IconLayers /> },
  { id: 'garanties',   label: 'Types de garanties',           icon: <IconShield /> },
  { id: 'notation',    label: 'Notation',                     icon: <IconStar /> },
];

/* ── Page principale ──────────────────────────────────────────── */
export default function AdminPlateformes() {
  const { search } = useLocation();
  const navigate = useNavigate();

  const section = new URLSearchParams(search).get('section') || 'referentiel';

  return (
    <div className="account-layout">
      <aside className="account-sidebar">
        <div style={{ marginBottom: 4 }}>
          <button
            onClick={() => navigate('/admin')}
            style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12,
              color: 'var(--text-muted)', background: 'none', border: 'none', cursor: 'pointer',
              padding: '4px 0', marginBottom: 8 }}>
            <IconChevronLeft /> Administration
          </button>
        </div>
        <h1 className="account-title">Plateformes</h1>
        <div className="account-nav-group">
          {NAV.map(item => (
            <button
              key={item.id}
              className={`account-nav-item${section === item.id ? ' active' : ''}`}
              onClick={() => navigate(`/admin/plateformes?section=${item.id}`, { replace: true })}
            >
              {item.icon}
              {item.label}
            </button>
          ))}
        </div>
      </aside>
      <div className="account-content">
        {section === 'referentiel' && <ReferentielSection />}
        {section === 'logos-ref'   && <LogosBibliothequeSection />}
        {section === 'orphelines'  && <OrphelinesSection />}
        {section === 'categories'  && (
          <RefListSection
            title="Catégories d'investissement"
            subtitle="Liste globale des catégories disponibles sur les profils du référentiel. Cliquez sur un nom pour filtrer les plateformes."
            apiPath="/ref-categories"
            suggestType="categories"
            onRowClick={item => navigate(`/admin/plateformes?section=referentiel&filterCat=${encodeURIComponent(item.nom)}`, { replace: true })}
          />
        )}
        {section === 'inv-suggestions' && <InvSuggestionsSection />}
        {section === 'secteurs'    && (
          <RefListSection
            title="Secteurs d'investissement"
            subtitle="Liste globale des secteurs disponibles sur les profils du référentiel."
            apiPath="/ref-secteurs"
            suggestType="secteurs"
          />
        )}
        {section === 'garanties'   && <GarantiesSection />}
        {section === 'notation'    && <NotationRefSection />}
      </div>
    </div>
  );
}
