// ─────────────────────────────────────────────────────────────
// DoricMatch AI — src/components/investors.jsx
// Écrans investisseurs : liste, fiche, édition, import, résultats.
// Chargé via <script type="text/babel"> dans index.html (ordre important).
// ─────────────────────────────────────────────────────────────

function Investors({ investors, onOpen, onCreate, onDelete, onOpenImport }) {
  const [q, setQ] = useState(""); const [f, setF] = useState("Tous");
  const [sort, setSort] = useState({ key: "name", dir: 1 });
  const [onlyIncomplete, setOnlyIncomplete] = useState(false);
  const types = ["Tous", ...new Set(investors.map(i => i.type))];
  const isIncomplete = (i) => !i.email || !i.phone || !i.contact;

  const filtered = investors.filter(i => (f === "Tous" || i.type === f) &&
    (!onlyIncomplete || isIncomplete(i)) &&
    (i.name + i.type + i.city + i.contact + (i.typologies || []).join(" ")).toLowerCase().includes(q.toLowerCase()));

  const getVal = (i, k) => {
    if (k === "name") return i.name.toLowerCase();
    if (k === "type") return i.type;
    if (k === "budget") return i.budgetMax;
    if (k === "yield") return i.yieldMin;
    if (k === "lease") return i.walbMin || 0;
    if (k === "freshness") return i.freshness;
    if (k === "relation") return i.relation;
    if (k === "status") return i.status;
    return "";
  };
  const list = [...filtered].sort((a, b) => {
    const va = getVal(a, sort.key), vb = getVal(b, sort.key);
    return (va < vb ? -1 : va > vb ? 1 : 0) * sort.dir;
  });
  const toggleSort = (k) => setSort(s => s.key === k ? { key: k, dir: -s.dir } : { key: k, dir: 1 });

  // sélection multiple
  const [selected, setSelected] = useState([]);
  const toggleSel = (id) => setSelected(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
  const allVisibleSelected = list.length > 0 && list.every(i => selected.includes(i.id));
  const toggleAll = () => setSelected(allVisibleSelected ? selected.filter(id => !list.some(i => i.id === id)) : [...new Set([...selected, ...list.map(i => i.id)])]);
  const selectedInv = investors.filter(i => selected.includes(i.id));

  const EXPORT_COLS = [
    ["Société", i => i.name], ["Type", i => i.type], ["Contact", i => i.contact],
    ["Fonction", i => i.role], ["Email", i => i.email], ["Mobile", i => i.phone],
    ["LinkedIn contact", i => i.linkedin], ["Site web", i => i.website], ["Tél. société", i => i.companyPhone],
    ["LinkedIn société", i => i.companyLinkedin], ["Ville", i => i.city], ["Pays", i => i.country],
    ["Budget min", i => i.budgetMin], ["Budget max", i => i.budgetMax], ["Rdt min (%)", i => i.yieldMin],
    ["WALB résiduel min (ans)", i => i.walbMin], ["Stratégies", i => (i.strategies || []).join(" / ")],
    ["Typologies", i => (i.typologies || []).join(" / ")], ["Locataires", i => (i.tenants || []).join(" / ")],
    ["Zones", i => (i.zones || []).map(z => `${z.name} (${fmtRadius(z.radius)})`).join(" / ")],
    ["Statut", i => i.status],
  ];

  const exportCSV = () => {
    const rows = [EXPORT_COLS.map(c => c[0])];
    selectedInv.forEach(i => rows.push(EXPORT_COLS.map(c => { const v = c[1](i); return v == null ? "" : String(v); })));
    const esc = (s) => `"${String(s).replace(/"/g, '""')}"`;
    const csv = "\uFEFF" + rows.map(r => r.map(esc).join(";")).join("\r\n"); // ; + BOM pour Excel FR
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = `investisseurs_${new Date().toISOString().slice(0, 10)}.csv`;
    a.click();
  };

  const exportPDF = () => {
    const w = window.open("", "_blank");
    if (!w) { alert("Autorisez les pop-ups pour générer le PDF."); return; }
    const today = new Date().toLocaleDateString("fr-FR");
    const cards = selectedInv.map(i => `
      <div class="card">
        <h2>${i.name} <span class="badge">${i.type}</span></h2>
        <div class="grid">
          <div><b>Contact</b> ${i.contact || "—"}${i.role ? " · " + i.role : ""}</div>
          <div><b>Email</b> ${i.email || "—"}</div>
          <div><b>Mobile</b> ${i.phone || "—"}</div>
          <div><b>Tél. société</b> ${i.companyPhone || "—"}</div>
          <div><b>Site</b> ${i.website || "—"}</div>
          <div><b>Ville</b> ${i.city || "—"}, ${i.country || ""}</div>
          <div><b>Budget</b> ${i.budgetMin.toLocaleString("fr-FR")} – ${i.budgetMax.toLocaleString("fr-FR")} €</div>
          <div><b>Rendement min</b> ${i.yieldMin} %</div>
          <div><b>WALB résiduel min</b> ${i.walbMin || 0} ans</div>
          <div><b>Stratégies</b> ${(i.strategies || []).join(", ")}</div>
        </div>
        <div class="row"><b>Typologies</b> ${(i.typologies || []).join(", ") || "—"}</div>
        <div class="row"><b>Locataires</b> ${(i.tenants || []).join(", ") || "—"}</div>
        <div class="row"><b>Zones</b> ${(i.zones || []).map(z => `${z.name} (${fmtRadius(z.radius)})`).join(", ") || "—"}</div>
      </div>`).join("");
    w.document.write(`<!DOCTYPE html><html lang="fr"><head><meta charset="utf-8"><title>Investisseurs — DoricMatch AI</title>
      <style>
        body{font-family:-apple-system,Segoe UI,Roboto,sans-serif;color:#1c1b33;margin:32px;}
        h1{font-size:22px;margin:0;} .sub{color:#6b6a85;font-size:12px;margin:4px 0 22px;}
        .card{border:1px solid #e4e3f0;border-radius:12px;padding:16px 18px;margin-bottom:14px;page-break-inside:avoid;}
        h2{font-size:16px;margin:0 0 10px;} .badge{font-size:11px;font-weight:400;color:#5b63e8;border:1px solid #c9cbf5;padding:2px 8px;border-radius:6px;margin-left:6px;}
        .grid{display:grid;grid-template-columns:1fr 1fr;gap:4px 24px;font-size:12.5px;margin-bottom:8px;}
        .row{font-size:12.5px;margin-top:4px;} b{color:#6b6a85;font-weight:600;margin-right:4px;}
        @media print{ .noprint{display:none;} }
      </style></head><body>
      <h1>Sélection d'investisseurs</h1>
      <div class="sub">DoricMatch AI · ${selectedInv.length} contact(s) · ${today}</div>
      ${cards}
      <button class="noprint" onclick="window.print()" style="margin-top:16px;padding:10px 18px;border:none;border-radius:8px;background:#5b63e8;color:#fff;font-size:13px;cursor:pointer;">Imprimer / Enregistrer en PDF</button>
      </body></html>`);
    w.document.close();
  };

  // métriques agrégées
  const actifs = filtered.filter(i => i.status === "Actif").length;
  const incompleteCount = investors.filter(isIncomplete).length;

  const dot = (v) => { const c = v >= 0.75 ? C.emerald : v >= 0.5 ? C.amber : C.rose; return <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}><span style={{ width: 7, height: 7, borderRadius: "50%", background: c }} />{Math.round(v * 100)}%</span>; };

  const cols = [
    ["name", "Investisseur", "left"], ["type", "Type", "left"], ["budget", "Budget max", "right"],
    ["yield", "Rdt min", "right"], ["lease", "WALB résid.", "right"], ["freshness", "Fraîcheur", "left"],
    ["relation", "Relation", "left"], ["status", "Statut", "left"],
  ];
  const Th = ({ k, label, align }) => (
    <th onClick={() => toggleSort(k)} style={{ textAlign: align, padding: "11px 14px", fontSize: 11, fontWeight: 600,
      color: sort.key === k ? C.indigo : C.faint, textTransform: "uppercase", letterSpacing: ".5px", cursor: "pointer",
      whiteSpace: "nowrap", userSelect: "none", borderBottom: `1px solid ${C.line}` }}>
      {label}{sort.key === k ? (sort.dir === 1 ? " ↑" : " ↓") : ""}
    </th>
  );

  return (
    <>
      <div className="rise" style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", marginBottom: 22 }}>
        <div>
          <h1 className="serif" style={{ fontSize: 34, margin: 0, fontWeight: 700, letterSpacing: "-.5px" }}>Base investisseurs</h1>
          <p style={{ color: C.dim, fontSize: 14, marginTop: 7 }}>Vue analytique des mandats d'acquisition. Cliquez une ligne pour la fiche complète.</p>
        </div>
        <div style={{ display: "flex", gap: 10 }}>
          <button className="btn btn-g" onClick={onOpenImport}>⬆ Importer (CSV)</button>
          <button className="btn btn-p" onClick={onCreate}>+ Nouveau contact</button>
        </div>
      </div>

      {/* bandeau métriques */}
      <div className="grid-2" style={{ gap: 12, marginBottom: 18 }}>
        <div className="card" style={{ padding: "14px 16px" }}>
          <div style={{ fontSize: 18, fontWeight: 700, color: C.violet }}>{actifs} / {filtered.length}</div>
          <div style={{ fontSize: 11, color: C.dim, marginTop: 3 }}>Mandats actifs</div>
        </div>
        <div className="card" onClick={() => setOnlyIncomplete(v => !v)}
          title="Cliquez pour filtrer les contacts dont l'email ou le téléphone manque"
          style={{ padding: "14px 16px", cursor: "pointer",
            border: onlyIncomplete ? `1.5px solid ${C.amber}` : `1px solid ${C.line}`,
            background: onlyIncomplete ? "rgba(217,144,22,.08)" : C.panel }}>
          <div style={{ fontSize: 18, fontWeight: 700, color: incompleteCount ? C.amber : C.emerald }}>
            {incompleteCount ? `⚠ ${incompleteCount}` : "✓ 0"}</div>
          <div style={{ fontSize: 11, color: C.dim, marginTop: 3 }}>Coordonnées incomplètes {onlyIncomplete ? "· filtre actif" : ""}</div>
        </div>
      </div>

      <div style={{ display: "flex", gap: 10, marginBottom: 14, alignItems: "center", flexWrap: "wrap" }}>
        <input placeholder="Rechercher (nom, type, ville, contact, typologie)…" value={q} onChange={e => setQ(e.target.value)}
          style={{ flex: 1, minWidth: 240, padding: "11px 16px", borderRadius: 11, border: `1px solid ${C.line}`, fontSize: 13.5, background: C.panel, color: C.text, outline: "none" }} />
        <select value={f} onChange={e => setF(e.target.value)}
          style={{ padding: "11px 14px", borderRadius: 11, border: `1px solid ${C.line}`, fontSize: 13.5, background: C.panel, color: C.text, outline: "none" }}>
          {types.map(t => <option key={t}>{t}</option>)}
        </select>
        <span style={{ fontSize: 12, color: C.faint }}>{list.length} résultat{list.length > 1 ? "s" : ""}</span>
      </div>

      {/* barre d'export (sélection active) */}
      <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 14, padding: "10px 16px", borderRadius: 12,
        background: selected.length ? "rgba(91,99,232,.08)" : C.panel2, border: `1px solid ${selected.length ? C.indigo + "55" : C.line}`, transition: ".18s" }}>
        <span style={{ fontSize: 13, fontWeight: 600, color: selected.length ? C.indigo : C.faint }}>
          {selected.length ? `${selected.length} investisseur(s) sélectionné(s)` : "Cochez des investisseurs pour les exporter"}
        </span>
        <div style={{ flex: 1 }} />
        {selected.length > 0 && <span onClick={() => setSelected([])} style={{ fontSize: 12, color: C.dim, cursor: "pointer" }}>Tout désélectionner</span>}
        <button className="btn btn-g" disabled={!selected.length} onClick={exportCSV} style={{ opacity: selected.length ? 1 : 0.45 }}>⬇ CSV</button>
        <button className="btn btn-p" disabled={!selected.length} onClick={exportPDF} style={{ opacity: selected.length ? 1 : 0.45 }}>⬇ PDF</button>
      </div>

      {/* tableau technique */}
      <div className="card rise" style={{ overflow: "hidden", padding: 0 }}>
        <div style={{ overflowX: "auto" }}>
          <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 13 }}>
            <thead><tr style={{ background: C.panel2 }}>
              <th style={{ padding: "11px 14px", borderBottom: `1px solid ${C.line}`, width: 36 }}>
                <input type="checkbox" checked={allVisibleSelected} onChange={toggleAll} style={{ cursor: "pointer" }} />
              </th>
              {cols.map(([k, label, align]) => <Th key={k} k={k} label={label} align={align} />)}
              <th style={{ padding: "11px 14px", borderBottom: `1px solid ${C.line}` }}></th>
            </tr></thead>
            <tbody>
              {list.map((inv) => {
                const sel = selected.includes(inv.id);
                return (
                <tr key={inv.id} onClick={() => onOpen(inv.id)} style={{ cursor: "pointer", transition: ".12s", background: sel ? "rgba(91,99,232,.06)" : "transparent" }}
                  onMouseEnter={e => e.currentTarget.style.background = C.sky}
                  onMouseLeave={e => e.currentTarget.style.background = sel ? "rgba(91,99,232,.06)" : "transparent"}>
                  <td onClick={e => e.stopPropagation()} style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, textAlign: "center" }}>
                    <input type="checkbox" checked={sel} onChange={() => toggleSel(inv.id)} style={{ cursor: "pointer" }} />
                  </td>
                  <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}` }}>
                    <div style={{ fontWeight: 600 }}>{inv.name}</div>
                    <div style={{ fontSize: 11.5, color: C.faint, marginTop: 2 }}>{inv.contact || <span style={{ color: C.amber }}>contact manquant</span>} · {inv.city}</div>
                    {(() => {
                      const miss = []; if (!inv.email) miss.push("email"); if (!inv.phone) miss.push("tél.");
                      return miss.length ? (
                        <div title={`Coordonnées interlocuteur incomplètes : ${miss.join(", ")} manquant${miss.length > 1 ? "s" : ""}`}
                          style={{ marginTop: 4, display: "inline-flex", alignItems: "center", gap: 5, fontSize: 10.5, fontWeight: 600,
                            color: C.amber, background: "rgba(217,144,22,.12)", border: `1px solid ${C.amber}55`, padding: "2px 8px", borderRadius: 6 }}>
                          ⚠ {miss.join(" + ")} manquant{miss.length > 1 ? "s" : ""}
                        </div>
                      ) : null;
                    })()}
                    <div style={{ marginTop: 5, display: "flex", gap: 4, flexWrap: "wrap" }}>
                      {(inv.typologies || []).slice(0, 3).map(t => <span key={t} style={{ fontSize: 10, padding: "2px 6px", borderRadius: 5, background: C.panel2, color: C.dim }}>{t}</span>)}
                      {(inv.typologies || []).length > 3 && <span style={{ fontSize: 10, color: C.faint }}>+{inv.typologies.length - 3}</span>}
                    </div>
                  </td>
                  <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, color: C.dim }}>{inv.type}</td>
                  <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, textAlign: "right", whiteSpace: "nowrap" }}>
                    <div style={{ fontWeight: 600, color: C.cyan }}>{eur(inv.budgetMax)}</div>
                    <div style={{ fontSize: 11, color: C.faint }}>dès {eur(inv.budgetMin)}</div>
                  </td>
                  <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, textAlign: "right", fontWeight: 600, color: C.emerald }}>{inv.yieldMin} %</td>
                  <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, textAlign: "right" }}>{inv.walbMin || 0} ans</td>
                  <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, fontSize: 12 }}>{dot(inv.freshness)}</td>
                  <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, fontSize: 12 }}>{dot(inv.relation)}</td>
                  <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}` }}>
                    <span style={{ fontSize: 11, color: STATUS_C[inv.status], border: `1px solid ${STATUS_C[inv.status]}55`, padding: "2px 9px", borderRadius: 7, whiteSpace: "nowrap" }}>{inv.status}</span>
                  </td>
                  <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, textAlign: "right", whiteSpace: "nowrap" }}>
                    <span onClick={(e) => { e.stopPropagation(); if (window.confirm(`Supprimer définitivement le contact « ${inv.name} » ?`)) onDelete(inv.id); }}
                      title="Supprimer ce contact" style={{ cursor: "pointer", color: C.faint, fontSize: 15, padding: "0 6px" }}
                      onMouseEnter={e => e.currentTarget.style.color = C.rose} onMouseLeave={e => e.currentTarget.style.color = C.faint}>🗑</span>
                    <span style={{ color: C.faint, marginLeft: 4 }}>›</span>
                  </td>
                </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
      <div style={{ fontSize: 11, color: C.faint, marginTop: 10 }}>
        Fraîcheur = ancienneté des données du mandat · Relation = qualité du lien commercial. Cliquez un en-tête pour trier.
      </div>
    </>
  );
}

function Upload({ onAnalyze, analyzing, analyzeErr }) {
  const [drag, setDrag] = useState(false); const [step, setStep] = useState(0);
  const [text, setText] = useState("");
  const [fileName, setFileName] = useState("");
  const [fileData, setFileData] = useState(null);
  const steps = ["Lecture du document…", "Extraction de l'actif…", "Géocodage & analyse…", "Matching investisseurs…"];
  useEffect(() => { if (!analyzing) { setStep(0); return; } const t = setInterval(() => setStep(s => Math.min(s + 1, steps.length - 1)), 700); return () => clearInterval(t); }, [analyzing]);

  const handleFile = (fl) => {
    if (!fl) return;
    setFileName(fl.name);
    const r = new FileReader();
    r.onload = () => setFileData({ b64: r.result.split(",")[1], mime: fl.type || "application/pdf" });
    r.readAsDataURL(fl);
  };
  const clearFile = () => { setFileData(null); setFileName(""); };
  const run = () => { if (!fileData && !text.trim()) return; onAnalyze({ file: fileData || undefined, text: text.trim() || undefined }); };

  if (analyzing) return (
    <>
      <H sub="L'IA traite votre dossier.">Analyse en cours</H>
      <div className="card" style={{ padding: 50, textAlign: "center" }}>
        <div style={{ width: 56, height: 56, margin: "0 auto 24px", borderRadius: "50%", border: `3px solid ${C.line}`, borderTopColor: C.violet, animation: "spin .8s linear infinite" }} />
        {steps.map((s, i) => <div key={i} style={{ fontSize: 15, padding: "7px 0", transition: ".3s", color: i < step ? C.emerald : i === step ? C.text : C.faint, fontWeight: i === step ? 600 : 400 }}>{i < step ? "✓ " : i === step ? "→ " : "  "}{s}</div>)}
      </div>
    </>
  );
  return (
    <>
      <H sub="Importez un dossier (PDF ou image) ET/OU ajoutez une description. L'IA combine les deux, extrait l'actif, le géocode, puis lance le matching sur vos investisseurs.">Analyser un dossier</H>

      {analyzeErr && <div className="card" style={{ padding: "12px 16px", marginBottom: 14, background: "rgba(217,144,22,.08)", border: `1px solid ${C.amber}55`, fontSize: 13, color: C.dim }}>⚠ {analyzeErr}</div>}

      <label onDragOver={e => { e.preventDefault(); setDrag(true); }} onDragLeave={() => setDrag(false)}
        onDrop={e => { e.preventDefault(); setDrag(false); handleFile(e.dataTransfer.files[0]); }}
        className="card" style={{ display: "block", padding: "60px 30px", textAlign: "center", cursor: "pointer", border: `2px dashed ${drag ? C.violet : C.lineStrong}`, background: drag ? C.sky : C.panel, transition: ".18s" }}>
        <input type="file" accept="application/pdf,image/*" style={{ display: "none" }} onChange={e => handleFile(e.target.files[0])} />
        <div style={{ width: 64, height: 64, margin: "0 auto 18px", borderRadius: 18, background: `linear-gradient(135deg,${C.indigo},${C.violet})`, display: "grid", placeItems: "center", fontSize: 28, color: "#fff", boxShadow: `0 14px 30px -12px ${C.violet}` }}>⬆</div>
        <div className="serif" style={{ fontSize: 21, fontWeight: 600 }}>Déposez votre dossier ici (PDF ou image)</div>
        <div style={{ color: C.dim, fontSize: 13.5, marginTop: 8, lineHeight: 1.5 }}>ou cliquez pour choisir un fichier{fileName ? <><br/><span style={{ color: C.cyan }}>✓ {fileName}</span></> : ""}</div>
      </label>

      <div style={{ marginTop: 18 }}>
        <div style={{ fontSize: 12.5, color: C.dim, marginBottom: 8 }}>{fileData ? "Ajoutez si besoin des informations complémentaires — elles seront combinées au PDF :" : "…ou collez le contenu du dossier :"}</div>
        <textarea value={text} onChange={e => setText(e.target.value)} placeholder="Collez ici la description de l'actif (loyer, prix, locataire, ville, surface…)"
          style={{ width: "100%", height: 110, padding: 12, borderRadius: 12, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13, lineHeight: 1.5, resize: "vertical", outline: "none" }} />
        <div style={{ marginTop: 10, display: "flex", gap: 10, flexWrap: "wrap", alignItems: "center" }}>
          <button className="btn btn-p" onClick={run} disabled={!fileData && !text.trim()} style={{ opacity: (!fileData && !text.trim()) ? .5 : 1 }}>Analyser {fileData && text.trim() ? "le dossier + la description" : fileData ? "le dossier" : "le texte"} →</button>
          {fileData && <button className="btn btn-g" onClick={clearFile}>Retirer le PDF</button>}
          <button className="btn btn-g" onClick={() => onAnalyze()}>Lancer la démo (actif exemple)</button>
        </div>
      </div>
      <div style={{ marginTop: 16, fontSize: 12, color: C.faint }}>L'analyse IA passe par le proxy serveur sécurisé (clé côté serveur). La démo fonctionne sans appel IA.</div>
    </>
  );
}

function InvestorDrawer({ inv, deal, onClose, onSave, onDelete }) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(inv);
  const [linkedinCheck, setLinkedinCheck] = useState(null); // {status, message}
  const [checking, setChecking] = useState(false);
  useEffect(() => { setDraft(inv); setEditing(false); setLinkedinCheck(null); }, [inv.id]);
  const m = deal ? scoreInvestor(inv, deal) : null;

  const checkLinkedin = async () => {
    setChecking(true); setLinkedinCheck(null);
    try {
      const data = await callClaude({
        model: AI_MODELS.standard, max_tokens: 400,
        tools: webTools(4, true),
        messages: [{ role: "user", content: `Vérifie sur le web si ${inv.contact} (${inv.role} chez ${inv.name}, LinkedIn ${inv.linkedin || "n.c."}) occupe toujours ce poste dans cette société, ou s'il a changé d'employeur récemment. Réponds en 2 phrases max : commence par "INCHANGÉ" ou "CHANGEMENT" puis explique.` }],
      });
      const txt = data.content.filter(b => b.type === "text").map(b => b.text).join(" ").trim();
      const changed = /changement/i.test(txt.slice(0, 30));
      setLinkedinCheck({ status: changed ? "change" : "ok", message: txt });
    } catch (e) {
      setLinkedinCheck({ status: "err", message: e.isAuth ? "IA indisponible : secret ANTHROPIC_API_KEY manquant ou invalide côté serveur (Supabase)." : "Vérification impossible pour le moment." });
    } finally { setChecking(false); }
  };

  const save = () => { onSave(draft); setEditing(false); };

  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, background: "rgba(28,27,51,.3)", backdropFilter: "blur(3px)", zIndex: 60, display: "flex", justifyContent: "flex-end" }}>
      <div onClick={e => e.stopPropagation()} className="drawer-panel" style={{ width: "80vw", maxWidth: "80vw", height: "100%", background: C.bg, borderLeft: `1px solid ${C.lineStrong}`, padding: "30px 40px", overflowY: "auto", animation: "slideIn .35s cubic-bezier(.2,.7,.3,1) both" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
          <div>
            <div className="serif" style={{ fontSize: 25, fontWeight: 700 }}>{inv.name}</div>
            <div style={{ fontSize: 13, color: C.dim, marginTop: 4 }}>{inv.type} · {inv.city}, {inv.country}</div>
          </div>
          <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
            {!editing && <button className="btn btn-g" onClick={() => setEditing(true)}>✎ Modifier</button>}
            {!editing && <button className="btn btn-g" onClick={() => { if (window.confirm(`Supprimer définitivement le contact « ${inv.name} » ?`)) onDelete(inv.id); }} style={{ color: C.rose }}>🗑 Supprimer</button>}
            <span onClick={onClose} style={{ cursor: "pointer", fontSize: 26, color: C.dim, lineHeight: 1 }}>×</span>
          </div>
        </div>
        <span style={{ display: "inline-block", marginTop: 14, fontSize: 11, color: STATUS_C[inv.status], border: `1px solid ${STATUS_C[inv.status]}55`, padding: "3px 11px", borderRadius: 8 }}>{inv.status}</span>

        {editing ? <EditForm draft={draft} setDraft={setDraft} onCancel={() => { setDraft(inv); setEditing(false); }} onSave={save} />
          : <ReadView inv={inv} m={m} onSave={onSave} checkLinkedin={checkLinkedin} checking={checking} linkedinCheck={linkedinCheck} />}
      </div>
    </div>
  );
}

function ReadView({ inv, m, onSave, checkLinkedin, checking, linkedinCheck }) {
  // Badge « IA » : marque une donnée renseignée automatiquement par l'enrichissement IA.
  const ia = (k) => (inv.aiFields || []).includes(k);
  const IaTag = () => <span style={{ fontSize: 9.5, fontWeight: 700, letterSpacing: .3, padding: "2px 6px", borderRadius: 5, background: `${C.violet}1a`, color: C.violet, border: `1px solid ${C.violet}44` }}>IA</span>;
  const withIa = (node, key) => ia(key) ? <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>{node} <IaTag /></span> : node;
  const [fbText, setFbText] = useState("");
  const [fbDossier, setFbDossier] = useState(""); // id du dossier concerné
  const [suggesting, setSuggesting] = useState(false);
  const [suggestion, setSuggestion] = useState(null); // { criteria:[{label,value}], note }
  const [sugErr, setSugErr] = useState("");
  const dossiers = inv.dossiers || [];
  const DOSSIER_STATUSES = ["Matché", "Envoyé", "Relancé", "Intéressé", "Refusé", "En négociation", "Signé", "Archivé"];
  const STATUS_COLORS = { "Matché": C.cyan, "Envoyé": C.indigo, "Relancé": C.amber, "Intéressé": C.emerald, "Refusé": C.rose, "En négociation": C.violet, "Signé": C.emerald, "Archivé": C.faint };
  const setDossierStatus = (dosId, status) => {
    onSave({ ...inv, dossiers: dossiers.map(x => x.id === dosId ? { ...x, status } : x) });
  };

  // Ajoute un retour, rattaché à un dossier si choisi
  const addFeedback = () => {
    if (!fbText.trim()) return;
    const dossier = dossiers.find(x => x.id === fbDossier);
    const entry = { text: fbText.trim(), dossierId: fbDossier || null, dossierTitle: dossier ? dossier.title : "", date: new Date().toLocaleDateString("fr-FR") };
    // on enregistre aussi le retour DANS le dossier concerné (pour le récap)
    const updatedDossiers = dossier ? dossiers.map(x => x.id === fbDossier ? { ...x, feedback: fbText.trim() } : x) : dossiers;
    onSave({ ...inv, feedback: [entry, ...(inv.feedback || [])], dossiers: updatedDossiers });
    setFbText("");
  };

  // L'IA propose des critères à partir du DOSSIER + du RETOUR
  const completeCriteria = async () => {
    setSuggesting(true); setSugErr(""); setSuggestion(null);
    // associe chaque retour à son dossier (récap) si disponible
    const fbBlocks = (inv.feedback || []).map(f => {
      const dos = dossiers.find(x => x.id === f.dossierId);
      const recap = dos ? `Dossier envoyé : ${dos.title} — actif ${dos.actif || "?"}, ${dos.localisation || "?"}, prix ${dos.prix || "?"} ${dos.prixType || ""}, rendement ${dos.rendement || "?"}, WALB ${dos.walb || "?"}, locataire ${dos.locataire || "?"}, capex ${dos.capex || "?"}.` : "Dossier : (non précisé).";
      return `${recap}\nRetour de l'investisseur : ${f.text}`;
    }).join("\n\n");
    const sys = `Tu es analyste en immobilier d'investissement. On te donne, pour un investisseur, les DOSSIERS qu'on lui a envoyés (avec leurs caractéristiques) et son RETOUR sur chacun. Déduis comment affiner ses CRITÈRES D'ACHAT en croisant les caractéristiques du dossier et la réaction. Renvoie UNIQUEMENT un JSON : {"criteria":[{"label":"libellé court","value":"précision chiffrée si possible"}],"note":"synthèse en 1 phrase"}. Exemples : si refus d'un actif à 6 % → relever rendement min ; si refus d'une zone → exclure la zone ; si intérêt pour WALB long → relever WALB min. Maximum 5 critères.`;
    try {
      const data = await callClaude({
        model: AI_MODELS.standard, max_tokens: 800, system: sys,
        messages: [{ role: "user", content: `Investisseur : ${inv.name} (${inv.type}). Critères actuels : budget ${inv.budgetMin}-${inv.budgetMax} €, rendement min ${inv.yieldMin} %, WALB min ${inv.walbMin || 0} ans, monovalent ${inv.monovalent || "indifférent"}, typologies ${(inv.typologies||[]).join(", ")}, stratégies ${(inv.strategies||[]).join(", ")}.\n\nDossiers envoyés et retours :\n${fbBlocks || "(aucun retour)"}` }],
      });
      const txt = data.content.filter(b => b.type === "text").map(b => b.text).join("").replace(/```json|```/g, "").trim();
      setSuggestion(JSON.parse(txt.slice(txt.indexOf("{"), txt.lastIndexOf("}") + 1)));
    } catch (e) {
      setSugErr(e.isAuth ? "IA indisponible : secret ANTHROPIC_API_KEY manquant ou invalide côté serveur (Supabase)." : "Génération impossible pour le moment.");
    } finally { setSuggesting(false); }
  };

  const addCriterion = (c) => {
    const entry = { field: "other", label: c.label, value: c.value, source: "Retour dossier", url: "", confidence: 90, date: new Date().toLocaleDateString("fr-FR") };
    onSave({ ...inv, enrichments: [entry, ...(inv.enrichments || [])] });
    setSuggestion(s => ({ ...s, criteria: s.criteria.filter(x => x !== c) }));
  };

  // ── Enrichir avec une note ou un document (cahier des charges, mail, PDF…) ──
  const [noteText, setNoteText] = useState("");
  const [noteDocs, setNoteDocs] = useState([]); // {name, b64, mime, isImg}
  const [noteBusy, setNoteBusy] = useState(false);
  const [noteErr, setNoteErr] = useState("");
  const [noteOut, setNoteOut] = useState(null); // { found:[], criteria:[] }
  const CRIT_LABELS_RV = { typologie: "Typologie à ajouter", tenant: "Locataire recherché", region: "Région ciblée", departement: "Département ciblé", strategy: "Stratégie", yieldMin: "Rendement min", budgetMax: "Budget max", walbMin: "WALB min", monovalent: "Monovalent" };
  const NOTE_FIELD_KEY = { typologie: "typologies", tenant: "tenants", region: "regions", departement: "departements", strategy: "strategies", yieldMin: "yieldMin", budgetMax: "budgetMax", walbMin: "walbMin", monovalent: "monovalent" };
  const addNoteDocs = (files) => {
    Array.from(files || []).forEach(fl => {
      const r = new FileReader();
      r.onload = () => setNoteDocs(ds => [...ds, { name: fl.name, b64: r.result.split(",")[1], mime: fl.type, isImg: fl.type.startsWith("image/") }]);
      r.readAsDataURL(fl);
    });
  };
  const removeNoteDoc = (i) => setNoteDocs(ds => ds.filter((_, j) => j !== i));

  const analyzeNote = async () => {
    if (!noteText.trim() && noteDocs.length === 0) return;
    if (!confirmCost("Analyse d'une note / document par IA (0,20 €).", IA_COSTS.enrich)) return;
    setNoteBusy(true); setNoteErr(""); setNoteOut(null);
    const sys = `Tu es analyste en immobilier d'investissement. À partir d'une NOTE et/ou de DOCUMENTS (cahier des charges, mail, PDF) concernant un investisseur, tu extrais (1) des informations utiles pour sa fiche et (2) des CRITÈRES D'ACHAT STRUCTURÉS qui affineront le matching. Réponds UNIQUEMENT en JSON :
{"found":[{"label":"libellé court","value":"texte court","confidence":0-100}],
"criteria":[{"field":"typologie|tenant|region|departement|strategy|yieldMin|budgetMax|walbMin|monovalent","value":"valeur précise (ex: 'Logistique','Île-de-France','14 — Calvados','6.5','15000000','oui')","label":"libellé court","confidence":0-100}]}
Pour les listes (typologie/tenant/region/departement/strategy) une valeur = un élément (répète l'objet si plusieurs). region = une région française, departement = 'code — nom' (ex: '14 — Calvados'). yieldMin/walbMin = nombre. budgetMax = nombre en euros. monovalent = oui/non/indifférent. Si rien de fiable, listes vides.`;
    const content = [{ type: "text", text: `Investisseur : ${inv.name} (${inv.type}). Critères actuels : budget ${inv.budgetMin}-${inv.budgetMax} €, rendement min ${inv.yieldMin} %, WALB min ${inv.walbMin || 0} ans, monovalent ${inv.monovalent || "indifférent"}, typologies ${(inv.typologies||[]).join(", ") || "—"}, régions ${(inv.regions||[]).join(", ") || "—"}, stratégies ${(inv.strategies||[]).join(", ") || "—"}.\n\nNote : ${noteText || "(aucune)"}` }];
    noteDocs.forEach(x => {
      if (x.isImg) content.push({ type: "image", source: { type: "base64", media_type: x.mime, data: x.b64 } });
      else if (x.mime === "application/pdf") content.push({ type: "document", source: { type: "base64", media_type: "application/pdf", data: x.b64 } });
    });
    try {
      const data = await callClaude({ model: AI_MODELS.standard, max_tokens: 1200, system: sys, messages: [{ role: "user", content }] });
      const txt = data.content.filter(b => b.type === "text").map(b => b.text).join("").replace(/```json|```/g, "").trim();
      const parsed = JSON.parse(txt.slice(txt.indexOf("{"), txt.lastIndexOf("}") + 1));
      const found = (parsed.found || []).map(f => ({ ...f, applied: true }));
      const criteria = (parsed.criteria || []).map(c => ({ ...c, applied: true }));
      // Application AUTOMATIQUE : les champs se remplissent seuls (une seule écriture).
      const uni = (arr, v) => [...new Set([...(arr || []), v])];
      const next = { ...inv };
      const aiKeys = new Set(inv.aiFields || []);
      criteria.forEach(c => {
        switch (c.field) {
          case "typologie": next.typologies = uni(next.typologies, c.value); break;
          case "tenant": next.tenants = uni(next.tenants, c.value); break;
          case "region": next.regions = uni(next.regions, c.value); break;
          case "departement": next.departements = uni(next.departements, c.value); break;
          case "strategy": next.strategies = uni(next.strategies, c.value); break;
          case "yieldMin": { const n = parseFloat(String(c.value).replace(",", ".")); if (!isNaN(n)) next.yieldMin = n; break; }
          case "budgetMax": { const n = parseFloat(String(c.value).replace(/[^0-9.]/g, "")); if (!isNaN(n)) next.budgetMax = n; break; }
          case "walbMin": { const n = parseFloat(String(c.value).replace(",", ".")); if (!isNaN(n)) next.walbMin = n; break; }
          case "monovalent": next.monovalent = c.value; break;
          default: break;
        }
        const k = NOTE_FIELD_KEY[c.field]; if (k) aiKeys.add(k);
      });
      next.aiFields = [...aiKeys];
      const now = new Date().toLocaleDateString("fr-FR");
      const entries = [
        ...found.map(f => ({ field: "other", label: f.label, value: f.value, source: "Note / document", url: "", confidence: f.confidence || 90, date: now })),
        ...criteria.map(c => ({ field: "other", label: "Critère affiné", value: (c.label || CRIT_LABELS_RV[c.field] || "Critère") + " : " + c.value, source: "Note / document", url: "", confidence: c.confidence || 88, date: now })),
      ];
      next.enrichments = [...entries, ...(inv.enrichments || [])];
      onSave(next);
      setNoteOut({ found, criteria });
    } catch (e) {
      setNoteErr(e.isAuth ? "IA indisponible : secret ANTHROPIC_API_KEY manquant ou invalide côté serveur (Supabase)." : "Analyse impossible. Vérifiez le document ou la note.");
    } finally { setNoteBusy(false); }
  };

  const applyNoteFound = (idx) => {
    const f = noteOut.found[idx];
    const entry = { field: "other", label: f.label, value: f.value, source: "Note / document", url: "", confidence: f.confidence || 90, date: new Date().toLocaleDateString("fr-FR") };
    onSave({ ...inv, enrichments: [entry, ...(inv.enrichments || [])] });
    setNoteOut(o => ({ ...o, found: o.found.map((x, j) => j === idx ? { ...x, applied: true } : x) }));
  };

  const applyNoteCriterion = (idx) => {
    const c = noteOut.criteria[idx];
    const next = { ...inv };
    const uni = (arr, v) => [...new Set([...(arr || []), v])];
    switch (c.field) {
      case "typologie": next.typologies = uni(inv.typologies, c.value); break;
      case "tenant": next.tenants = uni(inv.tenants, c.value); break;
      case "region": next.regions = uni(inv.regions, c.value); break;
      case "departement": next.departements = uni(inv.departements, c.value); break;
      case "strategy": next.strategies = uni(inv.strategies, c.value); break;
      case "yieldMin": { const n = parseFloat(String(c.value).replace(",", ".")); if (!isNaN(n)) next.yieldMin = n; break; }
      case "budgetMax": { const n = parseFloat(String(c.value).replace(/[^0-9.]/g, "")); if (!isNaN(n)) next.budgetMax = n; break; }
      case "walbMin": { const n = parseFloat(String(c.value).replace(",", ".")); if (!isNaN(n)) next.walbMin = n; break; }
      case "monovalent": next.monovalent = c.value; break;
      default: break;
    }
    const nk = NOTE_FIELD_KEY[c.field]; if (nk) next.aiFields = [...new Set([...(inv.aiFields || []), nk])];
    next.enrichments = [{ field: "other", label: "Critère affiné", value: (c.label || CRIT_LABELS_RV[c.field] || "Critère") + " : " + c.value, source: "Note / document", url: "", confidence: c.confidence || 88, date: new Date().toLocaleDateString("fr-FR") }, ...(inv.enrichments || [])];
    onSave(next);
    setNoteOut(o => ({ ...o, criteria: o.criteria.map((x, j) => j === idx ? { ...x, applied: true } : x) }));
  };

  return (
    <div className="drawer-cols" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0 40px", alignItems: "start" }}>
      <div>
      <Block title="Informations générales" color={C.indigo} />
      {/* Interlocuteur */}
      <Section title="Interlocuteur">
        <ContactsView contacts={inv.contacts} />
        <div style={{ marginTop: 12 }}>
          <button className="btn btn-g" onClick={checkLinkedin} disabled={checking}>
            {checking ? "Vérification en cours…" : "⟳ Vérifier LinkedIn (changement de société ?)"}</button>
          {linkedinCheck && (
            <div style={{ marginTop: 10, padding: "12px 14px", borderRadius: 11, fontSize: 13, lineHeight: 1.5,
              background: linkedinCheck.status === "change" ? "rgba(217,144,22,.1)" : linkedinCheck.status === "ok" ? "rgba(16,168,126,.1)" : C.panel2,
              border: `1px solid ${linkedinCheck.status === "change" ? C.amber : linkedinCheck.status === "ok" ? C.emerald : C.line}`,
              color: linkedinCheck.status === "change" ? "#8a5a08" : C.text }}>
              {linkedinCheck.status === "change" ? "⚠ " : linkedinCheck.status === "ok" ? "✓ " : ""}{linkedinCheck.message}
            </div>
          )}
        </div>
      </Section>

      {/* Société */}
      <Section title="Société">
        <div className="grid-2" style={{ gap: "0 30px" }}>
          <Row k="Raison sociale" v={inv.name} />
          <Row k="Type" v={inv.type} />
          {inv.website && <Row k="Site internet" v={<a href={`https://${inv.website.replace(/^https?:\/\//, "")}`} target="_blank" rel="noreferrer">{inv.website}</a>} />}
          {inv.companyPhone && <Row k="Tél. fixe société" v={<a href={`tel:${inv.companyPhone.replace(/\s/g, "")}`}>{inv.companyPhone}</a>} />}
          {inv.companyLinkedin && <Row k="LinkedIn société" v={<a href={`https://${inv.companyLinkedin.replace(/^https?:\/\//, "")}`} target="_blank" rel="noreferrer">{inv.companyLinkedin}</a>} />}
        </div>
      </Section>

      {/* Profil déplacé dans le bloc Critères d'investissement */}

      {m && <Section title="Matching avec le dossier en cours">
        <div style={{ display: "flex", alignItems: "center", gap: 14 }}><ScoreRing value={m.global} color={tier(m.global).c} /><div style={{ fontSize: 13, color: C.dim }}>{tier(m.global).label} · confiance données {m.confidence} %</div></div>
      </Section>}

      <Block title="Critères d'investissement" color={C.emerald} />
      <Section title="Profil d'investissement (synthèse)">
        <div className="grid-2" style={{ gap: "0 30px" }}>
          <Row k="Budget" v={withIa(`${eur(inv.budgetMin)} – ${eur(inv.budgetMax)}`, "budgetMax")} />
          <Row k="Rendement min" v={withIa(inv.yieldMin + " %", "yieldMin")} />
          <Row k="WALB résiduel min" v={withIa((inv.walbMin || 0) + " ans", "walbMin")} />
          <Row k="Stratégies" v={withIa((inv.strategies || []).join(", ") || "—", "strategies")} />
          <Row k="Actif monovalent" v={withIa(inv.monovalent === "oui" ? "Oui" : inv.monovalent === "non" ? "Non accepté" : "Indifférent", "monovalent")} />
          <Row k="Vacance acceptée" v={inv.vacancy ? "Oui" : "Non"} />
          <Row k="Travaux acceptés" v={inv.works ? "Oui" : "Non"} />
        </div>
      </Section>
      <Section title="Zones de prospection">
        <ZoneMap zones={inv.zones || []} regions={inv.regions || []} departements={inv.departements || []} activeIdx={-1} editable={false} height={210} />
        <div style={{ marginTop: 10, display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" }}>
          {(inv.zones || []).map((z, i) => <span key={i} className="chip" style={{ color: C.indigo, borderColor: `${C.indigo}44` }}>{z.name} · {fmtRadius(z.radius)}</span>)}
          {(inv.regions || []).map(r => <span key={r} className="chip">{r}</span>)}
          {ia("regions") && <IaTag />}
          {!(inv.zones || []).length && !(inv.regions || []).length && <span style={{ fontSize: 13, color: C.faint }}>—</span>}
        </div>
        {(inv.departements || []).length > 0 && <div style={{ marginTop: 8, display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" }}>
          <span style={{ fontSize: 10.5, color: C.faint, marginRight: 2 }}>Départements :</span>
          {(inv.departements || []).map(d => <span key={d} className="chip" style={{ fontSize: 11 }}>{d}</span>)}
          {ia("departements") && <IaTag />}
        </div>}
      </Section>

      <Section title="Typologies recherchées">
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" }}>{inv.typologies.map(t => <span key={t} className="chip" style={{ color: C.emerald, borderColor: `${C.emerald}44` }}>{t}</span>)}{ia("typologies") && <IaTag />}{!inv.typologies.length && <span style={{ fontSize: 13, color: C.faint }}>—</span>}</div>
        {inv.excluded && inv.excluded.length > 0 && <div style={{ marginTop: 10, display: "flex", flexWrap: "wrap", gap: 6 }}>{inv.excluded.map(t => <span key={t} className="chip" style={{ color: C.rose, borderColor: `${C.rose}44` }}>⊘ {t}</span>)}</div>}
      </Section>

      <Section title="Types de locataires recherchés">
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" }}>{(inv.tenants || []).map(t => <span key={t} className="chip" style={{ color: C.violet, borderColor: `${C.violet}44` }}>{t}</span>)}{ia("tenants") && <IaTag />}{(!inv.tenants || !inv.tenants.length) && <span style={{ fontSize: 13, color: C.faint }}>—</span>}</div>
      </Section>

      </div>

      <div>
      <Block title="Données enrichies par IA" color={C.violet} />
      {/* Historique avec source + URL */}
      <Section title="Historique d'acquisition">
        {(inv.acquisitions || []).length === 0 && <div style={{ fontSize: 13, color: C.faint }}>Aucune acquisition enregistrée.</div>}
        <div style={{ maxHeight: (inv.acquisitions || []).length > 4 ? 280 : "none", overflowY: (inv.acquisitions || []).length > 4 ? "auto" : "visible", paddingRight: (inv.acquisitions || []).length > 4 ? 6 : 0 }}>
        {(inv.acquisitions || []).map((a, i) => (
          <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", padding: "10px 0", borderBottom: i < inv.acquisitions.length - 1 ? `1px solid ${C.line}` : "none", fontSize: 13 }}>
            <div style={{ flex: 1 }}>
              <div style={{ fontWeight: 500 }}>{a.asset} · {a.city}</div>
              <div style={{ color: C.faint, fontSize: 12, marginTop: 2, display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
                <span>{a.year}</span>
                <span className="chip" style={{ padding: "1px 7px", color: a.source === "IA" ? C.cyan : C.dim }}>{a.source === "IA" ? "⟐ IA" : "✎ Manuel"}</span>
                {a.url && <a href={a.url} target="_blank" rel="noreferrer" style={{ fontSize: 12 }}>↗ article</a>}
              </div>
            </div>
            <div style={{ textAlign: "right", color: C.cyan, marginLeft: 12 }}>{a.amount}<div style={{ color: C.emerald, fontSize: 12 }}>{a.yield}</div></div>
          </div>
        ))}
        </div>
        {(inv.acquisitions || []).length > 4 && <div style={{ fontSize: 11, color: C.faint, marginTop: 8, textAlign: "center" }}>↕ {(inv.acquisitions || []).length} acquisitions — faites défiler</div>}
      </Section>

      {/* Enrichissement IA */}
      <Section title="Enrichissement IA">
        {(inv.enrichments || []).length === 0
          ? <div style={{ fontSize: 13, color: C.faint }}>Aucun enrichissement. Lancez la recherche IA depuis le tableau de bord.</div>
          : <>
            {(() => {
              const parseFr = (s) => { const mm = /(\d{2})\/(\d{2})\/(\d{4})/.exec(s || ""); return mm ? new Date(+mm[3], +mm[2] - 1, +mm[1]).getTime() : 0; };
              const last = (inv.enrichments || []).reduce((a, e) => { const t = parseFr(e.date); return t > a.t ? { t, d: e.date } : a; }, { t: 0, d: "" });
              return last.d ? <div style={{ fontSize: 12, color: C.dim, marginBottom: 10, display: "inline-flex", alignItems: "center", gap: 6, padding: "3px 10px", borderRadius: 8, background: C.panel2 }}>
                <span style={{ width: 6, height: 6, borderRadius: "50%", background: C.emerald }} /> Dernier enrichissement : <b style={{ color: C.text }}>{last.d}</b></div> : null;
            })()}
            <div style={{ maxHeight: (inv.enrichments || []).length > 4 ? 280 : "none", overflowY: (inv.enrichments || []).length > 4 ? "auto" : "visible", paddingRight: (inv.enrichments || []).length > 4 ? 6 : 0 }}>
              {(inv.enrichments || []).map((e, i) => (
                <div key={i} style={{ padding: "10px 0", borderBottom: i < inv.enrichments.length - 1 ? `1px solid ${C.line}` : "none", fontSize: 13 }}>
                  <div><b style={{ color: C.violet }}>{e.label}</b> · {e.value}</div>
                  <div style={{ color: C.faint, fontSize: 11.5, marginTop: 3, display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
                    <span className="chip" style={{ padding: "1px 7px" }}>{e.source}</span>
                    {e.confidence != null && <span>fiabilité {e.confidence} %</span>}
                    <span>{e.date}</span>
                    {e.url && <a href={e.url} target="_blank" rel="noreferrer">↗ source</a>}
                  </div>
                </div>
              ))}
            </div>
            {(inv.enrichments || []).length > 4 && <div style={{ fontSize: 11, color: C.faint, marginTop: 8, textAlign: "center" }}>↕ {(inv.enrichments || []).length} entrées — faites défiler</div>}
          </>}
      </Section>

      {/* Enrichir avec une note ou un document */}
      <Section title="Enrichir avec une note ou un document">
        <div style={{ fontSize: 12.5, color: C.dim, marginBottom: 10 }}>Collez une note (cahier des charges, mail…) ou importez un document. L'IA en extrait des informations et des critères d'achat, ajoutables d'un clic. Les critères affinent le matching.</div>
        <textarea value={noteText} onChange={e => setNoteText(e.target.value)} placeholder="Ex : recherche désormais des actifs logistiques en Île-de-France, rendement ≥ 6,5 %, WALB > 6 ans, refuse le monovalent…"
          style={{ width: "100%", height: 80, padding: 11, borderRadius: 11, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13, lineHeight: 1.5, resize: "vertical", outline: "none" }} />
        <label className="card" style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 9, padding: "12px", borderRadius: 11, cursor: "pointer", border: `1.5px dashed ${C.lineStrong}`, background: C.panel2, marginTop: 10 }}>
          <input type="file" multiple accept="image/*,application/pdf" style={{ display: "none" }} onChange={e => addNoteDocs(e.target.files)} />
          <span style={{ fontSize: 15 }}>⬆</span><span style={{ fontSize: 12.5, color: C.dim }}>Importer un cahier des charges, un mail, un PDF, une image…</span>
        </label>
        {noteDocs.length > 0 && (
          <div style={{ marginTop: 10, display: "flex", flexWrap: "wrap", gap: 8 }}>
            {noteDocs.map((x, i) => (
              <span key={i} className="chip" style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
                {x.isImg ? "🖼" : "📄"} {x.name.slice(0, 22)}
                <span onClick={() => removeNoteDoc(i)} style={{ cursor: "pointer", color: C.rose, fontWeight: 700 }}>×</span>
              </span>
            ))}
          </div>
        )}
        <div style={{ marginTop: 12 }}>
          <button className="btn btn-p" onClick={analyzeNote} disabled={noteBusy || (!noteText.trim() && noteDocs.length === 0)} style={{ opacity: (noteBusy || (!noteText.trim() && noteDocs.length === 0)) ? .6 : 1 }}>
            {noteBusy ? "Analyse en cours…" : "✦ Analyser et enrichir"}</button>
        </div>
        {noteErr && <div style={{ marginTop: 10, fontSize: 12.5, color: C.amber }}>{noteErr}</div>}

        {noteOut && (
          <div style={{ marginTop: 14 }}>
            {noteOut.found.length === 0 && noteOut.criteria.length === 0 && <div style={{ fontSize: 13, color: C.faint }}>Rien d'exploitable détecté dans cette note.</div>}
            {noteOut.found.length > 0 && (
              <>
                <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: ".8px", color: C.violet, marginBottom: 6 }}>Informations détectées</div>
                {noteOut.found.map((f, i) => (
                  <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, padding: "8px 0", borderTop: i ? `1px solid ${C.line}` : "none" }}>
                    <div style={{ fontSize: 13 }}><b style={{ color: C.violet }}>{f.label}</b> · {f.value} <span style={{ fontSize: 11, color: C.faint }}>({f.confidence} %)</span></div>
                    {f.applied ? <span style={{ fontSize: 12, color: C.emerald, fontWeight: 600, whiteSpace: "nowrap" }}>✓ Ajouté</span>
                      : <button className="btn btn-g" style={{ padding: "6px 12px", whiteSpace: "nowrap" }} onClick={() => applyNoteFound(i)}>+ Ajouter à la fiche</button>}
                  </div>
                ))}
              </>
            )}
            {noteOut.criteria.length > 0 && (
              <div style={{ marginTop: 12, paddingTop: 12, borderTop: `1px solid ${C.line}` }}>
                <div style={{ fontSize: 11, textTransform: "uppercase", letterSpacing: ".8px", color: C.indigo, marginBottom: 6 }}>Critères d'achat (affinent le matching)</div>
                {noteOut.criteria.map((c, i) => (
                  <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, padding: "8px 0", borderTop: i ? `1px solid ${C.line}` : "none" }}>
                    <div style={{ fontSize: 13 }}><b style={{ color: C.indigo }}>{CRIT_LABELS_RV[c.field] || c.label || "Critère"}</b> · {c.value} <span style={{ fontSize: 11, color: C.faint }}>({c.confidence} %)</span></div>
                    {c.applied ? <span style={{ fontSize: 12, color: C.emerald, fontWeight: 600, whiteSpace: "nowrap" }}>✓ Appliqué</span>
                      : <button className="btn btn-p" style={{ padding: "6px 12px", whiteSpace: "nowrap" }} onClick={() => applyNoteCriterion(i)}>+ Affiner le matching</button>}
                  </div>
                ))}
              </div>
            )}
          </div>
        )}
      </Section>

      <Block title="Historique des dossiers" color={C.cyan} />
      {/* Dossiers envoyés */}
      <Section title="Historique des dossiers">
        {dossiers.length === 0
          ? <div style={{ fontSize: 13, color: C.faint }}>Aucun dossier. Depuis « Analyser un dossier » → résultats du matching, envoyez un dossier à cet investisseur.</div>
          : <>
            <div style={{ maxHeight: dossiers.length > 4 ? 320 : "none", overflowY: dossiers.length > 4 ? "auto" : "visible", paddingRight: dossiers.length > 4 ? 6 : 0 }}>
            {dossiers.map((dos, i) => {
            const st = dos.status || "Envoyé";
            return (
            <div key={dos.id} style={{ padding: "12px 0", borderBottom: i < dossiers.length - 1 ? `1px solid ${C.line}` : "none", fontSize: 13 }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
                <span style={{ fontWeight: 600 }}>{dos.title}</span>
                <span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
                  <span style={{ width: 8, height: 8, borderRadius: "50%", background: STATUS_COLORS[st] || C.dim }} />
                  <select value={st} onChange={e => setDossierStatus(dos.id, e.target.value)}
                    style={{ fontSize: 12, padding: "4px 8px", borderRadius: 8, border: `1px solid ${C.line}`, background: C.panel, color: C.text, outline: "none", cursor: "pointer" }}>
                    {DOSSIER_STATUSES.map(s => <option key={s} value={s}>{s}</option>)}
                  </select>
                </span>
              </div>
              <div style={{ fontSize: 12, color: C.dim, marginTop: 4, display: "flex", gap: 10, flexWrap: "wrap" }}>
                {dos.actif && <span>{dos.actif}</span>}
                {dos.localisation && <span>· {dos.localisation}</span>}
                {dos.prix && <span>· {dos.prix} {dos.prixType}</span>}
                {dos.rendement && <span>· rdt {dos.rendement}</span>}
                {dos.walb && <span>· WALB {dos.walb}</span>}
                {dos.locataire && <span>· {dos.locataire}</span>}
                {dos.capex && <span>· capex {dos.capex}</span>}
              </div>
              <div style={{ fontSize: 11.5, color: C.faint, marginTop: 3 }}>Envoyé le {dos.date}{dos.feedback ? " · retour reçu" : ""}</div>
            </div>
            );
          })}
            </div>
            {dossiers.length > 4 && <div style={{ fontSize: 11, color: C.faint, marginTop: 8, textAlign: "center" }}>↕ {dossiers.length} dossiers — faites défiler</div>}
          </>}
      </Section>

      {/* Retours après envoi de dossier */}
      <Section title="Retours après envoi d'un dossier">
        <div style={{ fontSize: 12.5, color: C.dim, marginBottom: 8 }}>Notez le retour de l'investisseur (ce qui l'a intéressé ou rebuté). Rattachez-le au dossier concerné pour un affinage plus pertinent.</div>
        {dossiers.length > 0 && (
          <select value={fbDossier} onChange={e => setFbDossier(e.target.value)} style={{ width: "100%", padding: "9px 12px", borderRadius: 11, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13, marginBottom: 8, outline: "none" }}>
            <option value="">— Retour général (sans dossier précis) —</option>
            {dossiers.map(dos => <option key={dos.id} value={dos.id}>{dos.title} ({dos.date})</option>)}
          </select>
        )}
        <textarea value={fbText} onChange={e => setFbText(e.target.value)} placeholder="Ex : trop loin de Paris, cherche plutôt du WALB > 6 ans, pas de monovalent, rendement visé relevé à 7 %…"
          style={{ width: "100%", height: 70, padding: 11, borderRadius: 11, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13, lineHeight: 1.5, resize: "vertical", outline: "none" }} />
        <div style={{ marginTop: 8 }}><button className="btn btn-g" onClick={addFeedback} disabled={!fbText.trim()} style={{ opacity: fbText.trim() ? 1 : .5 }}>+ Ajouter ce retour</button></div>

        {(inv.feedback || []).length > 0 && (
          <div style={{ marginTop: 14 }}>
            {(inv.feedback || []).map((f, i) => (
              <div key={i} style={{ fontSize: 13, padding: "8px 0", borderTop: `1px solid ${C.line}` }}>
                <div>{f.text}</div>
                <div style={{ fontSize: 11.5, color: C.faint, marginTop: 2 }}>{f.dossierTitle ? `↳ ${f.dossierTitle} · ` : ""}{f.date}</div>
              </div>
            ))}
            <button className="btn btn-p" style={{ marginTop: 12 }} onClick={completeCriteria} disabled={suggesting}>
              {suggesting ? "Analyse des retours…" : "✦ Compléter ses critères d'achat"}</button>
            {sugErr && <div style={{ marginTop: 10, fontSize: 12.5, color: C.amber }}>{sugErr}</div>}
          </div>
        )}

        {suggestion && (
          <div className="card" style={{ marginTop: 14, padding: 16, background: C.sky, border: `1px solid #c9cbf5` }}>
            <div style={{ fontSize: 12, textTransform: "uppercase", letterSpacing: ".8px", color: C.indigo, marginBottom: 6 }}>Critères à ajouter (proposés par l'IA)</div>
            {suggestion.note && <div style={{ fontSize: 13, color: C.dim, marginBottom: 10 }}>{suggestion.note}</div>}
            {(suggestion.criteria || []).map((c, i) => (
              <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, padding: "8px 0", borderTop: i ? `1px solid #d7d9f5` : "none" }}>
                <div style={{ fontSize: 13 }}><b style={{ color: C.indigo }}>{c.label}</b> · {c.value}</div>
                <button className="btn btn-g" style={{ padding: "6px 12px", whiteSpace: "nowrap" }} onClick={() => addCriterion(c)}>+ Ajouter</button>
              </div>
            ))}
            {(suggestion.criteria || []).length === 0 && <div style={{ fontSize: 13, color: C.dim }}>Tous les critères proposés ont été ajoutés.</div>}
          </div>
        )}
      </Section>

      <Block title="Notes internes" color={C.amber} />
      {/* Notes internes */}
      <Section title="Notes internes">
        <div className="grid-2" style={{ gap: 12 }}>
          <div>
            <label style={{ fontSize: 11.5, color: C.faint, marginBottom: 5, display: "block" }}>Priorité commerciale</label>
            <select value={inv.priority || "Moyenne"} onChange={e => onSave({ ...inv, priority: e.target.value })}
              style={{ width: "100%", padding: "10px 13px", borderRadius: 11, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13.5, outline: "none" }}>
              <option>Haute</option><option>Moyenne</option><option>Basse</option>
            </select>
          </div>
          <div>
            <label style={{ fontSize: 11.5, color: C.faint, marginBottom: 5, display: "block" }}>Date de relance</label>
            <input type="date" value={inv.relanceDate || ""} onChange={e => onSave({ ...inv, relanceDate: e.target.value })}
              style={{ width: "100%", padding: "10px 13px", borderRadius: 11, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13.5, outline: "none" }} />
          </div>
          <div style={{ gridColumn: "1 / -1" }}>
            <label style={{ fontSize: 11.5, color: C.faint, marginBottom: 5, display: "block" }}>Prochaine action</label>
            <input value={inv.nextAction || ""} onChange={e => onSave({ ...inv, nextAction: e.target.value })} placeholder="Ex : rappeler après envoi du dossier Saint-Lô"
              style={{ width: "100%", padding: "10px 13px", borderRadius: 11, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13.5, outline: "none" }} />
          </div>
          <div style={{ gridColumn: "1 / -1" }}>
            <label style={{ fontSize: 11.5, color: C.faint, marginBottom: 5, display: "block" }}>Commentaires libres</label>
            <textarea value={inv.internalNotes || ""} onChange={e => onSave({ ...inv, internalNotes: e.target.value })} placeholder="Notes internes, contexte, historique de la relation…"
              style={{ width: "100%", height: 80, padding: 11, borderRadius: 11, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13, lineHeight: 1.5, resize: "vertical", outline: "none" }} />
          </div>
        </div>
      </Section>
      </div>
    </div>
  );
}

function EditForm({ draft, setDraft, onCancel, onSave }) {
  const set = (k, v) => setDraft(s => ({ ...s, [k]: v }));
  const toggle = (k, v) => setDraft(s => ({ ...s, [k]: (s[k] || []).includes(v) ? s[k].filter(x => x !== v) : [...(s[k] || []), v] }));
  const inp = { width: "100%", padding: "9px 12px", borderRadius: 10, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13, outline: "none" };
  const lab = { fontSize: 11, color: C.faint, marginBottom: 5, display: "block" };

  // acquisitions edit
  const setAcq = (i, key, val) => setDraft(s => ({ ...s, acquisitions: s.acquisitions.map((a, j) => j === i ? { ...a, [key]: val } : a) }));
  const addAcq = () => setDraft(s => ({ ...s, acquisitions: [...(s.acquisitions || []), { asset: "", city: "", amount: "", yield: "", year: "", source: "Manuel", url: "" }] }));
  const delAcq = (i) => setDraft(s => ({ ...s, acquisitions: s.acquisitions.filter((_, j) => j !== i) }));

  return (
    <div style={{ marginTop: 20 }}>
      <Section title="Interlocuteur">
        <ContactsEditor contacts={(draft.contacts && draft.contacts.length) ? draft.contacts : ((draft.contact||draft.email||draft.phone||draft.role||draft.linkedin) ? [{name:draft.contact||"",role:draft.role||"",email:draft.email||"",phone:draft.phone||"",linkedin:draft.linkedin||""}] : [])} setContacts={(cs) => set("contacts", cs)} />
      </Section>
      <Section title="Société">
        <div className="grid-2" style={{ gap: 12 }}>
          <div><label style={lab}>Raison sociale</label><input style={inp} value={draft.name} onChange={e => set("name", e.target.value)} /></div>
          <div><label style={lab}>Type</label><select style={inp} value={draft.type} onChange={e => set("type", e.target.value)}>{TYPE_OPTIONS.map(o => <option key={o}>{o}</option>)}</select></div>
          <div><label style={lab}>Site internet</label><input style={inp} value={draft.website || ""} onChange={e => set("website", e.target.value)} placeholder="societe.fr" /></div>
          <div><label style={lab}>Tél. fixe société</label><input style={inp} value={draft.companyPhone || ""} onChange={e => set("companyPhone", e.target.value)} /></div>
          <div style={{ gridColumn: "1 / -1" }}><label style={lab}>LinkedIn société</label><input style={inp} value={draft.companyLinkedin || ""} onChange={e => set("companyLinkedin", e.target.value)} placeholder="linkedin.com/company/…" /></div>
          <div><label style={lab}>Ville</label><input style={inp} value={draft.city} onChange={e => set("city", e.target.value)} /></div>
          <div><label style={lab}>Statut</label><select style={inp} value={draft.status} onChange={e => set("status", e.target.value)}>{["Actif", "En négociation", "À relancer", "Inactif"].map(o => <option key={o}>{o}</option>)}</select></div>
        </div>
      </Section>
      <Section title="Profil d'investissement">
        <div className="grid-2" style={{ gap: 12 }}>
          <div><label style={lab}>Budget min (€)</label><input style={inp} type="number" value={draft.budgetMin} onChange={e => set("budgetMin", +e.target.value)} /></div>
          <div><label style={lab}>Budget max (€)</label><input style={inp} type="number" value={draft.budgetMax} onChange={e => set("budgetMax", +e.target.value)} /></div>
          <div><label style={lab}>Rendement min (%)</label><input style={inp} type="number" step="0.1" value={draft.yieldMin} onChange={e => set("yieldMin", +e.target.value)} /></div>
          <div><label style={lab}>WALB résiduel min (ans)</label><input style={inp} type="number" value={draft.walbMin || 0} onChange={e => set("walbMin", +e.target.value)} /></div>
          <div><label style={lab}>Actif monovalent</label><select style={inp} value={draft.monovalent || "indifférent"} onChange={e => set("monovalent", e.target.value)}><option value="indifférent">Indifférent</option><option value="oui">Recherché</option><option value="non">Non accepté</option></select></div>
        </div>
        <div style={{ marginTop: 12 }}><label style={lab}>Stratégies</label><div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{STRAT_OPTIONS.map(o => <span key={o} onClick={() => toggle("strategies", o)} className="chip" style={{ cursor: "pointer", background: (draft.strategies || []).includes(o) ? `linear-gradient(100deg,${C.indigo},${C.violet})` : undefined, color: (draft.strategies || []).includes(o) ? "#fff" : undefined, border: (draft.strategies || []).includes(o) ? "none" : undefined }}>{o}</span>)}</div></div>
        <div style={{ display: "flex", gap: 22, marginTop: 14 }}>
          <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, cursor: "pointer", color: C.dim }}><input type="checkbox" checked={draft.vacancy} onChange={e => set("vacancy", e.target.checked)} /> Accepte la vacance</label>
          <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, cursor: "pointer", color: C.dim }}><input type="checkbox" checked={draft.works} onChange={e => set("works", e.target.checked)} /> Accepte les travaux</label>
        </div>
      </Section>
      <Section title="Typologies recherchées">
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{TYPO_OPTIONS.map(o => <span key={o} onClick={() => toggle("typologies", o)} className="chip" style={{ cursor: "pointer", background: (draft.typologies || []).includes(o) ? "rgba(16,168,126,.12)" : undefined, color: (draft.typologies || []).includes(o) ? C.emerald : undefined, borderColor: (draft.typologies || []).includes(o) ? `${C.emerald}55` : undefined }}>{o}</span>)}</div>
      </Section>
      <Section title="Types de locataires recherchés">
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{TENANT_OPTIONS.map(o => <span key={o} onClick={() => toggle("tenants", o)} className="chip" style={{ cursor: "pointer", background: (draft.tenants || []).includes(o) ? "rgba(124,92,255,.12)" : undefined, color: (draft.tenants || []).includes(o) ? C.violet : undefined, borderColor: (draft.tenants || []).includes(o) ? `${C.violet}55` : undefined }}>{o}</span>)}</div>
      </Section>
      <Section title="Zones de prospection">
        <ZoneEditor zones={draft.zones || []} setZones={(z) => set("zones", z)} regions={draft.regions || []} departements={draft.departements || []} />
      </Section>
      <Section title="Régions & départements ciblés">
        <label style={lab}>Régions</label>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 14 }}>{REGION_OPTIONS.map(o => <span key={o} onClick={() => toggle("regions", o)} className="chip" style={{ cursor: "pointer", background: (draft.regions || []).includes(o) ? "rgba(91,99,232,.12)" : undefined, color: (draft.regions || []).includes(o) ? C.indigo : undefined, borderColor: (draft.regions || []).includes(o) ? `${C.indigo}55` : undefined }}>{o}</span>)}</div>
        <label style={lab}>Départements</label>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, maxHeight: 150, overflowY: "auto", padding: 2 }}>{DEPARTEMENT_OPTIONS.map(o => <span key={o} onClick={() => toggle("departements", o)} className="chip" style={{ cursor: "pointer", fontSize: 11.5, background: (draft.departements || []).includes(o) ? "rgba(91,99,232,.12)" : undefined, color: (draft.departements || []).includes(o) ? C.indigo : undefined, borderColor: (draft.departements || []).includes(o) ? `${C.indigo}55` : undefined }}>{o}</span>)}</div>
      </Section>
      <Section title="Historique d'acquisition">
        {(draft.acquisitions || []).map((a, i) => (
          <div key={i} className="card" style={{ padding: 12, marginBottom: 8 }}>
            <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr", gap: 8, marginBottom: 8 }}>
              <input style={inp} placeholder="Actif" value={a.asset} onChange={e => setAcq(i, "asset", e.target.value)} />
              <input style={inp} placeholder="Ville" value={a.city} onChange={e => setAcq(i, "city", e.target.value)} />
              <input style={inp} placeholder="Montant" value={a.amount} onChange={e => setAcq(i, "amount", e.target.value)} />
              <input style={inp} placeholder="Rendement" value={a.yield} onChange={e => setAcq(i, "yield", e.target.value)} />
              <input style={inp} placeholder="Année" value={a.year} onChange={e => setAcq(i, "year", e.target.value)} />
              <select style={inp} value={a.source} onChange={e => setAcq(i, "source", e.target.value)}><option>Manuel</option><option>IA</option></select>
            </div>
            <div style={{ display: "flex", gap: 8 }}>
              <input style={{ ...inp, flex: 1 }} placeholder="Lien article (URL)" value={a.url} onChange={e => setAcq(i, "url", e.target.value)} />
              <button className="btn btn-g" style={{ padding: "6px 12px", color: C.rose }} onClick={() => delAcq(i)}>Suppr.</button>
            </div>
          </div>
        ))}
        <button className="btn btn-g" onClick={addAcq}>+ Ajouter une acquisition</button>
      </Section>
      <div style={{ display: "flex", gap: 9, justifyContent: "flex-end", marginTop: 22, paddingBottom: 20 }}>
        <button className="btn btn-g" onClick={onCancel}>Annuler</button>
        <button className="btn btn-p" onClick={onSave}>Enregistrer les modifications</button>
      </div>
    </div>
  );
}

function ContactsEditor({ contacts, setContacts, max = 5, accent = C.indigo }) {
  const list = (contacts && contacts.length) ? contacts : [{ name: "", role: "", email: "", phone: "", linkedin: "" }];
  const inp = { width: "100%", padding: "9px 12px", borderRadius: 10, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13, outline: "none" };
  const lab = { fontSize: 11, color: C.faint, marginBottom: 5, display: "block" };
  const upd = (i, k, v) => setContacts(list.map((c, j) => j === i ? { ...c, [k]: v } : c));
  const add = () => { if (list.length >= max) return; setContacts([...list, { name: "", role: "", email: "", phone: "", linkedin: "" }]); };
  const del = (i) => { const next = list.filter((_, j) => j !== i); setContacts(next); };
  return (
    <div>
      {list.map((c, i) => (
        <div key={i} className="card" style={{ padding: 14, marginBottom: 10, border: `1px solid ${C.line}` }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10 }}>
            <span style={{ fontSize: 11.5, fontWeight: 700, color: accent }}>{i === 0 ? "Contact principal" : "Contact " + (i + 1)}</span>
            {list.length > 1 && <span onClick={() => del(i)} style={{ cursor: "pointer", fontSize: 12, color: C.rose }}>Retirer</span>}
          </div>
          <div className="grid-2" style={{ gap: 10 }}>
            <div><label style={lab}>Nom</label><input style={inp} value={c.name || ""} onChange={e => upd(i, "name", e.target.value)} /></div>
            <div><label style={lab}>Fonction</label><input style={inp} value={c.role || ""} onChange={e => upd(i, "role", e.target.value)} /></div>
            <div><label style={lab}>Email</label><input style={inp} value={c.email || ""} onChange={e => upd(i, "email", e.target.value)} /></div>
            <div><label style={lab}>Mobile</label><input style={inp} value={c.phone || ""} onChange={e => upd(i, "phone", e.target.value)} /></div>
            <div style={{ gridColumn: "1 / -1" }}><label style={lab}>LinkedIn</label><input style={inp} value={c.linkedin || ""} onChange={e => upd(i, "linkedin", e.target.value)} placeholder="linkedin.com/in/…" /></div>
          </div>
        </div>
      ))}
      {list.length < max
        ? <button className="btn btn-g" onClick={add}>+ Ajouter un contact ({list.length}/{max})</button>
        : <div style={{ fontSize: 11.5, color: C.faint }}>Maximum de {max} contacts atteint.</div>}
    </div>
  );
}

function ContactsView({ contacts }) {
  const list = (contacts || []).filter(c => c && (c.name || c.email || c.phone || c.role || c.linkedin));
  if (!list.length) return <div style={{ fontSize: 13, color: C.faint }}>Aucun contact renseigné.</div>;
  return (
    <div>
      {list.map((c, i) => (
        <div key={i} style={{ padding: "10px 0", borderTop: i ? `1px solid ${C.line}` : "none" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 4, flexWrap: "wrap" }}>
            <span style={{ fontSize: 13.5, fontWeight: 600 }}>{c.name || "—"}</span>
            {i === 0 && <span style={{ fontSize: 9.5, fontWeight: 700, color: C.indigo, border: `1px solid ${C.indigo}44`, padding: "1px 6px", borderRadius: 6 }}>PRINCIPAL</span>}
            {c.role && <span style={{ fontSize: 12, color: C.faint }}>· {c.role}</span>}
          </div>
          <div className="grid-2" style={{ gap: "2px 30px" }}>
            {c.email && <Row k="Email" v={<a href={`mailto:${c.email}`}>{c.email}</a>} />}
            {c.phone && <Row k="Mobile" v={<a href={`tel:${c.phone.replace(/\s/g, "")}`}>{c.phone}</a>} />}
            {c.linkedin && <Row k="LinkedIn" v={<a href={`https://${c.linkedin.replace(/^https?:\/\//, "")}`} target="_blank" rel="noreferrer">{c.linkedin}</a>} />}
          </div>
        </div>
      ))}
    </div>
  );
}

function ZoneEditor({ zones, setZones, regions = [], departements = [] }) {
  const [q, setQ] = useState(""); const [geo, setGeo] = useState(false); const [err, setErr] = useState(""); const [activeIdx, setActiveIdx] = useState(0);
  const add = async () => {
    if (!q.trim()) return; setGeo(true); setErr("");
    const r = await geocode(q.trim());
    setGeo(false);
    if (!r) { setErr("Adresse introuvable. Précisez (ville, pays)."); return; }
    const nz = [...zones, { name: r.label || q.trim(), lat: r.lat, lng: r.lng, radius: 25 }];
    setZones(nz); setActiveIdx(nz.length - 1); setQ("");
  };
  const setRadius = (i, val) => setZones(zones.map((p, j) => j === i ? { ...p, radius: val } : p));
  const remove = (i) => setZones(zones.filter((_, j) => j !== i));
  const inp = { width: "100%", padding: "10px 13px", borderRadius: 11, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13.5, outline: "none" };

  return (
    <>
      <div style={{ fontSize: 12, color: C.dim, marginBottom: 8 }}>Saisissez une adresse, un quartier, une ville ou une région → le point est placé sur la carte. Réglez ensuite le rayon (300 m → 100 km).</div>
      <div style={{ display: "flex", gap: 8, marginBottom: 12 }}>
        <input style={inp} value={q} onChange={e => setQ(e.target.value)} onKeyDown={e => e.key === "Enter" && add()} placeholder="Ex : 12 rue de Rivoli Paris · Croix-Rousse Lyon · Bretagne…" />
        <button className="btn btn-p" onClick={add} disabled={geo} style={{ whiteSpace: "nowrap" }}>{geo ? "…" : "+ Ajouter"}</button>
      </div>
      {err && <div style={{ color: C.rose, fontSize: 12.5, marginBottom: 10 }}>{err}</div>}
      <ZoneMap zones={zones} regions={regions} departements={departements} activeIdx={activeIdx} editable={true} onAddPoint={(lat, lng) => { const nz = [...zones, { name: `Point (${lat.toFixed(3)}, ${lng.toFixed(3)})`, lat, lng, radius: 25 }]; setZones(nz); setActiveIdx(nz.length - 1); }} height={260} />
      {zones.length > 0 && (
        <div style={{ marginTop: 12, display: "grid", gap: 10 }}>
          {zones.map((z, i) => (
            <div key={i} className="card" style={{ padding: "12px 14px", border: i === activeIdx ? `1.5px solid ${C.violet}` : `1px solid ${C.line}`, cursor: "pointer" }} onClick={() => setActiveIdx(i)}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
                <span style={{ fontSize: 13, fontWeight: 600 }}>◴ {z.name}</span>
                <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                  <span style={{ fontSize: 13, color: C.violet, fontWeight: 600, minWidth: 60, textAlign: "right" }}>{fmtRadius(z.radius)}</span>
                  <span onClick={(e) => { e.stopPropagation(); remove(i); }} style={{ cursor: "pointer", color: C.rose, fontSize: 16 }}>×</span>
                </div>
              </div>
              <input type="range" min="0.3" max="100" step="0.1" value={z.radius} onChange={e => setRadius(i, +e.target.value)} style={{ width: "100%" }} />
              <div style={{ display: "flex", justifyContent: "space-between", fontSize: 10, color: C.faint, marginTop: 2 }}><span>300 m</span><span>100 km</span></div>
            </div>
          ))}
        </div>
      )}
    </>
  );
}

function Results({ deal, matches, onEmail, onOpen, onAttach, go, history, onRecordRun, onOpenEns }) {
  const [subtab, setSubtab] = useState("current");
  const [sent, setSent] = useState([]);
  const [selected, setSelected] = useState([]);
  const [minScore, setMinScore] = useState(0);       // seuil de score minimum
  const [hideBlocking, setHideBlocking] = useState(false); // masquer les fiches avec points bloquants
  const toggleSel = (id) => setSelected(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
  const [aiRunning, setAiRunning] = useState(false);
  const [aiErr, setAiErr] = useState("");
  const [aiResults, setAiResults] = useState(null); // { [invId]: {aiScore, verdict, rationale, edge, flag} }
  const dealRecap = () => ({
    title: deal.name, prix: eur(deal.price), prixType: "Acte en main", vefa: false,
    actif: deal.typology || "", localisation: [deal.city, deal.region].filter(Boolean).join(", "),
    surface: deal.surface ? deal.surface + " m²" : "", loyer: eur(deal.rent),
    rendement: deal.yield + " %", walb: deal.waltDeal ? deal.waltDeal + " ans" : "",
    locataire: deal.tenants || "", capex: (deal.risks || []).find(r => /capex|travaux/i.test(r)) || "aucun connu",
    bailFerme: "", notes: "", date: new Date().toLocaleDateString("fr-FR"), feedback: "", status: "Envoyé",
  });
  const sendDossier = (id) => { if (!onAttach || sent.includes(id)) return; onAttach([id], dealRecap()); setSent(s => [...s, id]); };

  const VERDICT = { fort: C.emerald, moyen: C.amber, faible: C.rose };

  // ── Historique : instantané des fiches susceptibles + enregistrement du run ──
  const snapshot = () => matches.slice(0, 25).map(m => ({ id: m.inv.id, name: m.inv.name, sub: [m.inv.type, m.inv.city].filter(Boolean).join(" · "), global: m.global, matched: m.matched || [], blocking: m.blocking || [], confidence: m.confidence }));
  useEffect(() => {
    if (!deal || !deal.runId || !onRecordRun) return;
    onRecordRun({ runId: deal.runId, kind: "investors", subject: dealRecap(), matches: snapshot(), sent, ai: null });
  }, [deal && deal.runId]);

  const aiRerank = async () => {
    if (!selected.length) return;
    if (!confirmCost(`Affinage IA de ${selected.length} investisseur(s) (0,05 €/client).`, selected.length * IA_COSTS.rerank)) return;
    setAiRunning(true); setAiErr(""); setAiResults(null);
    const chosen = matches.filter(m => selected.includes(m.inv.id));
    const sys = "Tu es un analyste senior en immobilier d'investissement. On te donne un DEAL et une liste d'investisseurs pré-sélectionnés par un algorithme, avec leur pré-score et leurs critères. Ton rôle : challenger ce pré-classement en t'appuyant sur la pertinence sémantique et qualitative (au-delà des seuils chiffrés). Renvoie UNIQUEMENT un JSON valide, sans backticks.";
    const dealTxt = `DEAL : ${deal.name} | typologie ${deal.typology} | ${[deal.city, deal.region].filter(Boolean).join(", ")} | prix ${eur(deal.price)} | rendement ${deal.yield}% | locataire ${deal.tenants || "n.c."} | travaux ${deal.works ? "oui" : "non"} | vacance ${deal.vacancy ? "oui" : "non"}`;
    const invsTxt = chosen.map(m => {
      const i = m.inv;
      return `- id:${i.id} | ${i.name} (${i.type}) | typologies: ${(i.typologies||[]).join(", ")||"—"} | zones/régions: ${(i.regions||[]).join(", ")||(i.zones||[]).map(z=>z.name).join(", ")||"—"} | budget ${i.budgetMin}-${i.budgetMax} € | rendement min ${i.yieldMin}% | stratégies: ${(i.strategies||[]).join(", ")||"—"} | travaux: ${i.works?"oui":"non"} | vacance: ${i.vacancy?"oui":"non"} | PRÉ-SCORE algo: ${m.global}/100 | points forts: ${(m.matched||[]).join(", ")||"—"} | points bloquants: ${(m.blocking||[]).join(", ")||"—"}`;
    }).join("\n");
    const fmt = '{"ranking":[{"invId":"id","aiScore":0,"verdict":"fort|moyen|faible","rationale":"2-3 phrases d\'argumentaire commercial","edge":"ce que l\'algo a pu rater, sinon vide","flag":"réserve/alerte, sinon vide"}]}';
    try {
      const data = await callClaude({ model: AI_MODELS.standard, max_tokens: 1200, system: sys,
        messages: [{ role: "user", content: `${dealTxt}\n\nINVESTISSEURS PRÉ-SÉLECTIONNÉS :\n${invsTxt}\n\nRenvoie le re-classement au format JSON STRICT suivant (aiScore sur 100) :\n${fmt}` }] });
      const txt = data.content.filter(b => b.type === "text").map(b => b.text).join("").replace(/```json|```/g, "").trim();
      const parsed = JSON.parse(txt.slice(txt.indexOf("{"), txt.lastIndexOf("}") + 1));
      const map = {};
      (parsed.ranking || []).forEach(r => { if (r && r.invId != null) map[r.invId] = r; });
      setAiResults(map);
      if (onRecordRun && deal && deal.runId) onRecordRun({ runId: deal.runId, kind: "investors", subject: dealRecap(), matches: snapshot(), sent, ai: map });
    } catch (e) {
      setAiErr(e.isAuth ? "IA indisponible : secret ANTHROPIC_API_KEY manquant ou invalide côté serveur (Supabase)." : "Affinage IA impossible pour le moment.");
    } finally { setAiRunning(false); }
  };

  // ordre d'affichage : si re-classement IA dispo, trier par aiScore desc (les non-notés gardent l'ordre algo en dessous)
  const ordered = aiResults
    ? [...matches].sort((a, b) => {
        const A = aiResults[a.inv.id], B = aiResults[b.inv.id];
        if (A && B) return (B.aiScore || 0) - (A.aiScore || 0);
        if (A) return -1; if (B) return 1;
        return b.global - a.global;
      })
    : matches;
  // Filtres d'affichage (seuil de score + masquer les fiches bloquantes)
  const visible = ordered.filter(m => m.global >= minScore && (!hideBlocking || !(m.blocking || []).length));

  if (subtab === "history") {
    return (
      <>
        <H sub="Résumé du dossier, puis classement des investisseurs par pertinence. Envoyez le dossier aux investisseurs ciblés.">Résultats du matching</H>
        <ResultTabs tab={subtab} setTab={setSubtab} count={(history || []).length} />
        <MatchHistory history={history} onOpenInv={onOpen} onOpenEns={onOpenEns} />
      </>
    );
  }
  if (!deal) {
    return (
      <>
        <H sub="Résumé du dossier, puis classement des investisseurs par pertinence. Envoyez le dossier aux investisseurs ciblés.">Résultats du matching</H>
        <ResultTabs tab={subtab} setTab={setSubtab} count={(history || []).length} />
        <Empty go={go} />
      </>
    );
  }

  return (
    <>
      <H sub="Résumé du dossier, puis classement des investisseurs par pertinence. Envoyez le dossier aux investisseurs ciblés.">Résultats du matching</H>
      <ResultTabs tab={subtab} setTab={setSubtab} count={(history || []).length} />
      <div className="card rise" style={{ padding: 26, marginBottom: 24, background: `linear-gradient(110deg,${C.sky},#fff)` }}>
        <div className="serif" style={{ fontSize: 22, fontWeight: 700 }}>{deal.name}</div>
        <div style={{ display: "flex", gap: 26, marginTop: 14, flexWrap: "wrap", fontSize: 13.5 }}>
          <Stat label="Prix" v={eur(deal.price)} /><Stat label="Loyer / an" v={eur(deal.rent)} /><Stat label="Rendement" v={deal.yield + " %"} c={C.emerald} />
          <Stat label="Surface" v={deal.surface + " m²"} /><Stat label="WALT" v={deal.waltDeal + " ans"} /><Stat label="Occupation" v={deal.occupation} />
        </div>
        <div style={{ display: "flex", gap: 30, marginTop: 20, flexWrap: "wrap" }}>
          <div style={{ flex: 1, minWidth: 240 }}><div style={{ color: C.emerald, fontWeight: 600, marginBottom: 6, fontSize: 13 }}>Points forts</div>{deal.strengths.map(s => <div key={s} style={{ fontSize: 13, color: C.dim, padding: "2px 0" }}>+ {s}</div>)}</div>
          <div style={{ flex: 1, minWidth: 240 }}><div style={{ color: C.rose, fontWeight: 600, marginBottom: 6, fontSize: 13 }}>Risques identifiés</div>{deal.risks.map(s => <div key={s} style={{ fontSize: 13, color: C.dim, padding: "2px 0" }}>− {s}</div>)}</div>
        </div>
      </div>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14, gap: 12, flexWrap: "wrap" }}>
        <span style={{ fontSize: 12, textTransform: "uppercase", letterSpacing: "1.4px", color: C.faint }}>{matches.length} investisseurs classés{selected.length ? ` · ${selected.length} sélectionné(s)` : ""}</span>
        <div style={{ display: "flex", gap: 9, flexWrap: "wrap" }}>
          <button className="btn btn-p" onClick={aiRerank} disabled={!selected.length || aiRunning} style={{ opacity: (!selected.length || aiRunning) ? .5 : 1 }}>
            {aiRunning ? "Analyse IA en cours…" : "✦ Affiner avec l'IA"}</button>
          <button className="btn btn-g" style={{ padding: "8px 14px" }}>⬇ Exporter la short-list (Excel)</button>
        </div>
      </div>
      {!selected.length && <div style={{ fontSize: 12.5, color: C.faint, marginBottom: 14 }}>Cochez des investisseurs, puis « Affiner avec l'IA » pour un re-classement qualitatif (le score algorithmique est conservé).</div>}
      {aiErr && <div className="card" style={{ padding: "10px 14px", marginBottom: 14, background: "rgba(217,144,22,.08)", border: `1px solid ${C.amber}55`, fontSize: 13, color: C.dim }}>⚠ {aiErr}</div>}

      <div className="card" style={{ padding: "12px 16px", marginBottom: 16, display: "flex", alignItems: "center", gap: 20, flexWrap: "wrap" }}>
        <label style={{ display: "flex", alignItems: "center", gap: 10, fontSize: 12.5, color: C.dim }}>
          Score minimum
          <input type="range" min="0" max="100" step="5" value={minScore} onChange={e => setMinScore(+e.target.value)} style={{ cursor: "pointer" }} />
          <span style={{ fontWeight: 700, color: C.text, minWidth: 34 }}>{minScore}</span>
        </label>
        <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 12.5, color: C.dim, cursor: "pointer" }}>
          <input type="checkbox" checked={hideBlocking} onChange={e => setHideBlocking(e.target.checked)} /> Masquer les fiches avec points bloquants
        </label>
        <span style={{ marginLeft: "auto", fontSize: 12, color: C.faint }}>{visible.length} / {matches.length} affichés</span>
      </div>

      {visible.length === 0 && <div className="card" style={{ padding: 20, textAlign: "center", fontSize: 13, color: C.faint }}>Aucun investisseur au-dessus de ce seuil. Baissez le score minimum.</div>}

      {visible.map((m, i) => {
        const t = tier(m.global);
        const labels = { typologie: "Typologie", zone: "Zone / secteur", budget: "Budget", rendement: "Rendement", walb: "WALB", strategie: "Stratégie", risque: "Risque", monovalent: "Monovalent" };
        const isSent = sent.includes(m.inv.id);
        const sel = selected.includes(m.inv.id);
        const ai = aiResults && aiResults[m.inv.id];
        const vColor = ai ? (VERDICT[(ai.verdict || "").toLowerCase()] || C.dim) : null;
        return (
          <div key={m.inv.id} className="card rise" style={{ padding: 22, marginBottom: 13, animationDelay: `${i * 60}ms`, border: sel ? `1.5px solid ${C.indigo}` : undefined }}>
            <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
              <div style={{ display: "flex", gap: 12, alignItems: "flex-start" }}>
                <input type="checkbox" checked={sel} onChange={() => toggleSel(m.inv.id)} style={{ cursor: "pointer", marginTop: 5 }} />
                <div>
                  <div className="serif" style={{ fontSize: 18, fontWeight: 600, cursor: "pointer" }} onClick={() => onOpen(m.inv.id)}>{m.inv.name}</div>
                  <div style={{ fontSize: 12.5, color: C.dim, marginTop: 3 }}>{m.inv.type} · {m.inv.city} · confiance données <span style={{ color: C.cyan }}>{m.confidence} %</span></div>
                </div>
              </div>
              <div style={{ display: "flex", alignItems: "center", gap: 16 }}>
                <div style={{ textAlign: "center" }}>
                  <ScoreRing value={m.global} color={t.c} />
                  <div style={{ fontSize: 10, color: C.faint, marginTop: 2 }}>algorithme</div>
                </div>
                {ai && <div style={{ textAlign: "center" }}>
                  <ScoreRing value={ai.aiScore || 0} color={vColor} />
                  <div style={{ fontSize: 10, color: C.faint, marginTop: 2 }}>IA</div>
                </div>}
              </div>
            </div>

            {ai && (
              <div style={{ marginTop: 14, padding: 14, borderRadius: 12, background: C.panel2, border: `1px solid ${vColor}33` }}>
                <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }}>
                  <span style={{ fontSize: 11, fontWeight: 700, textTransform: "uppercase", letterSpacing: ".5px", color: "#fff", background: vColor, padding: "2px 9px", borderRadius: 7 }}>{ai.verdict || "—"}</span>
                  <span style={{ fontSize: 12, color: C.faint }}>Analyse IA</span>
                </div>
                {ai.rationale && <div style={{ fontSize: 13, color: C.text, lineHeight: 1.5 }}>{ai.rationale}</div>}
                {ai.edge && <div style={{ fontSize: 12.5, color: C.emerald, marginTop: 6 }}>＋ {ai.edge}</div>}
                {ai.flag && <div style={{ fontSize: 12.5, color: C.rose, marginTop: 4 }}>⚠ {ai.flag}</div>}
              </div>
            )}

            <div className="grid-crit" style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: "12px 26px", marginTop: 16 }}>
              {Object.entries(labels).map(([k, label]) => (
                <div key={k}><div style={{ display: "flex", justifyContent: "space-between", fontSize: 11, marginBottom: 4, color: C.dim }}><span>{label}</span><span>{m.parts[k]}</span></div>
                  <div className="bar"><div className="fill" style={{ width: m.parts[k] + "%", background: `linear-gradient(90deg,${C.indigo},${t.c})` }} /></div></div>
              ))}
            </div>
            <div style={{ marginTop: 16, display: "flex", gap: 8, flexWrap: "wrap" }}>
              {m.matched.map(x => <span key={x} style={{ fontSize: 11.5, background: "rgba(16,168,126,.12)", color: C.emerald, padding: "4px 11px", borderRadius: 8 }}>✓ {x}</span>)}
              {m.blocking.map(x => <span key={x} style={{ fontSize: 11.5, background: "rgba(226,72,107,.1)", color: C.rose, padding: "4px 11px", borderRadius: 8 }}>✕ {x}</span>)}
            </div>
            <div style={{ marginTop: 16, display: "flex", gap: 9, flexWrap: "wrap" }}>
              {isSent
                ? <button className="btn btn-g" disabled style={{ color: C.emerald, borderColor: `${C.emerald}55` }}>✓ Dossier envoyé</button>
                : <button className="btn btn-p" onClick={() => sendDossier(m.inv.id)}>✉ Envoyer le dossier</button>}
              <button className="btn btn-g" onClick={() => onEmail(m)}>Email d'approche</button>
              <button className="btn btn-g" onClick={() => onOpen(m.inv.id)}>Voir la fiche</button>
            </div>
          </div>
        );
      })}
    </>
  );
}

function ImportInvestorsModal({ existing, onClose, onImport }) {
  const norm = (s) => String(s || "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
  const TARGETS = [
    ["name", "Société", true], ["contact", "Nom du contact", false], ["role", "Fonction / titre", false],
    ["email", "Email", false], ["phone", "Téléphone / mobile", false], ["companyPhone", "Tél. société", false],
    ["linkedin", "LinkedIn (perso)", false], ["companyLinkedin", "LinkedIn (société)", false],
    ["website", "Site web", false], ["city", "Ville", false], ["country", "Pays", false], ["type", "Type d'investisseur", false],
  ];
  const SYN = {
    name: ["societe", "company", "companyname", "entreprise", "raisonsociale", "nomsociete", "organization", "accountname", "currentcompany", "compte"],
    contact: ["contact", "nomcomplet", "fullname", "name", "nomcontact", "personne", "prenomnom"],
    role: ["fonction", "titre", "title", "position", "poste", "jobtitle", "currentposition", "headline"],
    email: ["email", "mail", "adresseemail", "emailaddress", "workemail", "courriel", "emailpro"],
    phone: ["telephone", "mobile", "portable", "phone", "phonenumber", "tel", "gsm"],
    companyPhone: ["telsociete", "companyphone", "telephonesociete", "standard", "telephoneentreprise"],
    linkedin: ["linkedin", "linkedinurl", "profileurl", "lienlinkedin", "linkedinperso", "linkedinprofile", "urllinkedin", "profillinkedin"],
    companyLinkedin: ["linkedinsociete", "companylinkedin", "companylinkedinurl", "companyurl", "pagelinkedin", "linkedincompany", "linkedinentreprise"],
    website: ["siteweb", "site", "website", "siteinternet", "companywebsite", "urlsite", "domaine", "domain"],
    city: ["ville", "city", "localisation", "location", "localite"],
    country: ["pays", "country"],
    type: ["type", "categorie", "category", "typeinvestisseur", "investortype"],
  };
  const [step, setStep] = useState("up");
  const [rows, setRows] = useState([]);
  const [headers, setHeaders] = useState([]);
  const [mapping, setMapping] = useState({});
  const [pasted, setPasted] = useState("");
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState(false);
  const [result, setResult] = useState(null);

  const autoMap = (hdrs) => {
    const m = {}, used = new Set();
    // passe 1 : correspondances EXACTES (prioritaires) pour tous les champs
    for (const [t] of TARGETS) {
      const syns = SYN[t] || [t];
      const hit = hdrs.find(h => !used.has(h) && syns.includes(norm(h)));
      if (hit) { m[t] = hit; used.add(hit); }
    }
    // passe 2 : correspondances approximatives (sous-chaîne) pour le reste
    for (const [t] of TARGETS) {
      if (m[t]) continue;
      const syns = SYN[t] || [t];
      const hit = hdrs.find(h => !used.has(h) && syns.some(s => s.length >= 4 && norm(h).includes(s)));
      if (hit) { m[t] = hit; used.add(hit); }
    }
    return m;
  };
  const ingest = (data, fields) => {
    let hdrs = (fields || Object.keys(data[0] || {})).filter(Boolean);
    const fn = hdrs.find(h => ["firstname", "prenom"].includes(norm(h)));
    const ln = hdrs.find(h => ["lastname", "nom", "nomdefamille", "surname"].includes(norm(h)));
    const hasFull = hdrs.some(h => ["fullname", "nomcomplet"].includes(norm(h)));
    let prepared = data;
    if (fn && ln && !hasFull) {
      const col = "Nom complet (Prénom + Nom)";
      hdrs = [col, ...hdrs];
      prepared = data.map(r => ({ [col]: `${r[fn] || ""} ${r[ln] || ""}`.trim(), ...r }));
    }
    setHeaders(hdrs); setRows(prepared); setMapping(autoMap(hdrs)); setErr(""); setStep("map");
  };
  const cleanRows = (data) => (data || []).filter(r => Object.values(r).some(v => String(v || "").trim()));
  const parseFile = (file) => {
    if (!file) return;
    if (!window.Papa) { setErr("Module CSV en cours de chargement, réessayez dans un instant."); return; }
    window.Papa.parse(file, {
      header: true, skipEmptyLines: "greedy", transformHeader: h => h.trim(),
      complete: (res) => { const data = cleanRows(res.data); if (!data.length) { setErr("Fichier vide ou sans données."); return; } ingest(data, res.meta && res.meta.fields); },
      error: (e) => setErr("Erreur de lecture : " + (e.message || e)),
    });
  };
  const parsePasted = () => {
    if (!pasted.trim()) { setErr("Collez d'abord le contenu CSV."); return; }
    if (!window.Papa) { setErr("Module CSV en cours de chargement, réessayez."); return; }
    const res = window.Papa.parse(pasted.trim(), { header: true, skipEmptyLines: "greedy", transformHeader: h => h.trim() });
    const data = cleanRows(res.data);
    if (!data.length) { setErr("Aucune donnée. Vérifiez que la 1re ligne contient les en-têtes."); return; }
    ingest(data, res.meta && res.meta.fields);
  };

  const built = useMemo(() => {
    const get = (r, t) => mapping[t] ? String(r[mapping[t]] || "").trim() : "";
    const existKeys = new Set(existing.map(i => ((i.email || "").toLowerCase().trim()) || norm(i.name)).filter(Boolean));
    const seen = new Set();
    const out = []; let dup = 0, noName = 0;
    for (const r of rows) {
      const name = get(r, "name");
      if (!name) { noName++; continue; }
      const email = get(r, "email").toLowerCase();
      const key = email || norm(name);
      if (existKeys.has(key) || seen.has(key)) { dup++; continue; }
      seen.add(key);
      out.push({ ...EMPTY, name, type: get(r, "type") || "Investisseur privé", contact: get(r, "contact"), role: get(r, "role"),
        email: get(r, "email"), phone: get(r, "phone"), companyPhone: get(r, "companyPhone"),
        linkedin: get(r, "linkedin"), companyLinkedin: get(r, "companyLinkedin"),
        website: get(r, "website"), city: get(r, "city"), country: get(r, "country") || "France" });
    }
    return { out, dup, noName };
  }, [rows, mapping, existing]);

  const doImport = async () => {
    if (!built.out.length) return;
    setBusy(true);
    const res = await onImport(built.out);
    setBusy(false);
    setResult({ ...res, dup: built.dup, noName: built.noName });
    setStep("done");
  };

  const sel = { width: "100%", padding: "7px 9px", borderRadius: 8, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 12.5, outline: "none" };
  const th = { textAlign: "left", padding: "7px 10px", color: C.faint, fontWeight: 600, borderBottom: `1px solid ${C.line}`, position: "sticky", top: 0, background: C.panel, fontSize: 11 };

  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, background: "rgba(28,27,51,.35)", backdropFilter: "blur(3px)", display: "flex", alignItems: "center", justifyContent: "center", padding: 24, zIndex: 85 }}>
      <div onClick={e => e.stopPropagation()} className="card" style={{ width: "min(880px,96vw)", maxHeight: "90vh", overflow: "auto", padding: 26 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14 }}>
          <div className="serif" style={{ fontSize: 20, fontWeight: 700 }}>Importer des investisseurs (CSV)</div>
          <span onClick={onClose} style={{ cursor: "pointer", fontSize: 24, color: C.dim }}>×</span>
        </div>

        {step === "up" && (
          <>
            <div style={{ fontSize: 13, color: C.dim, marginBottom: 14, lineHeight: 1.55 }}>
              Importez un fichier <b>.csv</b> (export Sales Navigator, Evaboot, Excel…). La 1re ligne doit contenir les en-têtes. Les colonnes sont détectées automatiquement (séparateur <b>,</b> ou <b>;</b>) ; vous pourrez les ajuster à l'étape suivante.
            </div>
            <label className="card" style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 10, padding: 18, borderRadius: 12, cursor: "pointer", border: `1.5px dashed ${C.lineStrong}`, background: C.panel2, marginBottom: 16 }}>
              <input type="file" accept=".csv,text/csv" style={{ display: "none" }} onChange={e => { parseFile(e.target.files[0]); e.target.value = ""; }} />
              <span style={{ fontSize: 18 }}>⬆</span><span style={{ fontSize: 13, color: C.dim }}>Choisir un fichier CSV</span>
            </label>
            <div style={{ fontSize: 12, color: C.faint, marginBottom: 8 }}>…ou collez le contenu CSV :</div>
            <textarea value={pasted} onChange={e => setPasted(e.target.value)} placeholder="Société;Contact;Email;Ville;LinkedIn…" style={{ width: "100%", height: 110, padding: 10, borderRadius: 10, border: `1px solid ${C.line}`, fontSize: 12, fontFamily: "ui-monospace,Menlo,monospace", resize: "vertical", outline: "none" }} />
            <div style={{ marginTop: 12, textAlign: "right" }}>
              <button className="btn btn-g" onClick={parsePasted}>Analyser le CSV collé →</button>
            </div>
          </>
        )}

        {step === "map" && (
          <>
            <div style={{ fontSize: 13, color: C.dim, marginBottom: 12 }}>{rows.length} ligne(s) détectée(s). Vérifiez la correspondance des colonnes :</div>
            <div className="grid-2" style={{ gap: "8px 16px", marginBottom: 14 }}>
              {TARGETS.map(([t, label, req]) => (
                <div key={t} style={{ display: "flex", alignItems: "center", gap: 8 }}>
                  <div style={{ fontSize: 12, color: C.faint, width: 124, flex: "none" }}>{label}{req && <span style={{ color: C.rose }}> *</span>}</div>
                  <select value={mapping[t] || ""} onChange={e => setMapping(m => ({ ...m, [t]: e.target.value }))} style={sel}>
                    <option value="">— ignorer —</option>
                    {headers.map(h => <option key={h} value={h}>{h}</option>)}
                  </select>
                </div>
              ))}
            </div>
            {!mapping.name && <div style={{ fontSize: 12.5, color: C.amber, marginBottom: 10 }}>⚠ La colonne « Société » est obligatoire pour importer.</div>}
            <div style={{ fontSize: 12, color: C.faint, marginBottom: 6 }}>Aperçu — <b style={{ color: C.emerald }}>{built.out.length}</b> prêt(s) à importer · {built.dup} doublon(s) ignoré(s) · {built.noName} sans société :</div>
            <div style={{ overflow: "auto", border: `1px solid ${C.line}`, borderRadius: 10, maxHeight: 230 }}>
              <table style={{ width: "100%", borderCollapse: "collapse", fontSize: 11.5 }}>
                <thead><tr>{["Société", "Contact", "Email", "Ville", "LinkedIn"].map(h => <th key={h} style={th}>{h}</th>)}</tr></thead>
                <tbody>
                  {built.out.slice(0, 8).map((inv, idx) => (
                    <tr key={idx} style={{ borderBottom: `1px solid ${C.panel2}` }}>
                      <td style={{ padding: "6px 10px", fontWeight: 600 }}>{inv.name}</td>
                      <td style={{ padding: "6px 10px", color: C.dim }}>{inv.contact || "—"}{inv.role ? " · " + inv.role : ""}</td>
                      <td style={{ padding: "6px 10px", color: C.dim }}>{inv.email || "—"}</td>
                      <td style={{ padding: "6px 10px", color: C.dim }}>{inv.city || "—"}</td>
                      <td style={{ padding: "6px 10px", color: C.dim, maxWidth: 170, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{inv.companyLinkedin || inv.linkedin || "—"}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <div style={{ marginTop: 16, display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
              <button className="btn btn-g" onClick={() => { setStep("up"); setRows([]); setHeaders([]); }}>← Changer de fichier</button>
              <button className="btn btn-p" onClick={doImport} disabled={busy || !mapping.name || !built.out.length}>{busy ? "Import en cours…" : `Importer ${built.out.length} investisseur(s)`}</button>
            </div>
          </>
        )}

        {step === "done" && result && (
          <div style={{ textAlign: "center", padding: "18px 0" }}>
            {result.error
              ? <><div style={{ fontSize: 15, fontWeight: 700, color: C.rose, marginBottom: 6 }}>Échec de l'import</div><div style={{ fontSize: 13, color: C.dim }}>{result.error}</div></>
              : <><div style={{ fontSize: 40, marginBottom: 6 }}>✓</div><div style={{ fontSize: 16, fontWeight: 700, color: C.emerald, marginBottom: 6 }}>{result.inserted} investisseur(s) importé(s)</div><div style={{ fontSize: 12.5, color: C.dim }}>{result.dup} doublon(s) ignoré(s){result.noName ? ` · ${result.noName} ligne(s) sans société` : ""}</div></>}
            <div style={{ marginTop: 18 }}><button className="btn btn-p" onClick={onClose}>Fermer</button></div>
          </div>
        )}

        {err && <div style={{ fontSize: 12.5, color: C.rose, marginTop: 10 }}>⚠ {err}</div>}
      </div>
    </div>
  );
}

function CreateInvestorModal({ onClose, onSave }) {
  const [f, setF] = useState({ ...EMPTY });
  const [zones, setZones] = useState([]);
  const [raw, setRaw] = useState(""); const [parsing, setParsing] = useState(false);
  const [file, setFile] = useState(null); const [fileName, setFileName] = useState(""); const [err, setErr] = useState("");
  const [iaOpen, setIaOpen] = useState(true); const [iaDone, setIaDone] = useState(false);
  const set = (k, v) => setF(s => ({ ...s, [k]: v }));
  const toggle = (k, v) => setF(s => ({ ...s, [k]: (s[k] || []).includes(v) ? s[k].filter(x => x !== v) : [...(s[k] || []), v] }));

  const parseIA = async () => {
    setParsing(true); setErr("");
    const sys = `Tu es un extracteur de critères d'investissement immobilier. Renvoie UNIQUEMENT un JSON valide (sans backticks) :
{"name":string,"type":un parmi ${JSON.stringify(TYPE_OPTIONS)},"contact":string,"role":string,"email":string,"phone":string,"linkedin":string,"website":string,"companyPhone":string,"companyLinkedin":string,"city":string,"country":string,"budgetMin":number,"budgetMax":number,"yieldMin":number,"walbMin":number,"monovalent":"oui"|"non"|"indifférent","typologies":tableau parmi ${JSON.stringify(TYPO_OPTIONS)},"tenants":tableau parmi ${JSON.stringify(TENANT_OPTIONS)},"excluded":tableau,"cities":tableau de villes ciblées (noms),"regions":tableau,"strategies":tableau parmi ${JSON.stringify(STRAT_OPTIONS)},"vacancy":boolean,"works":boolean,"acquisitions":tableau d'objets {asset,city,amount,yield,year,url},"highlights":tableau de courtes phrases d'actualité/stratégie notables (pour enrichissement)}
Champs absents = "" ou []. walbMin = WALB résiduel minimum en années. Bailleur commerce loué = ["core+"] ; sale & leaseback + baux fermes = vacancy false, works false. Prends le directeur des investissements si plusieurs contacts. Pour les acquisitions, source sera "IA".`;
    const content = file
      ? [{ type: "document", source: { type: "base64", media_type: "application/pdf", data: file } }, { type: "text", text: "Extrais les critères de ce cahier des charges." }]
      : [{ type: "text", text: "Document à analyser :\n\n" + raw }];
    try {
      const data = await callClaude({ model: AI_MODELS.standard, max_tokens: 1800, system: sys, messages: [{ role: "user", content }] });
      const txt = data.content.filter(b => b.type === "text").map(b => b.text).join("").replace(/```json|```/g, "").trim();
      const p = JSON.parse(txt.slice(txt.indexOf("{"), txt.lastIndexOf("}") + 1));
      const strs = Array.isArray(p.strategies) ? p.strategies.filter(s => STRAT_OPTIONS.includes(s)) : [];
      const today = new Date().toLocaleDateString("fr-FR");
      const src = file ? (fileName || "Cahier des charges") : "Note / email";
      // enrichissements à partir des acquisitions + highlights extraits
      const enr = [];
      (Array.isArray(p.acquisitions) ? p.acquisitions : []).forEach(a => {
        enr.push({ field: "other", label: "Acquisition", value: `${a.asset || ""}${a.city ? " · " + a.city : ""}${a.amount ? " · " + a.amount : ""}`.trim(), source: src, url: a.url || "", confidence: 90, date: today });
      });
      (Array.isArray(p.highlights) ? p.highlights : []).forEach(h => {
        enr.push({ field: "other", label: "Actualité / stratégie", value: h, source: src, url: "", confidence: 85, date: today });
      });

      // FUSION : on ne remplace un champ que si l'IA a trouvé quelque chose ET que le champ manuel est vide
      setF(prev => {
        const merged = { ...prev };
        const keep = (k, val) => { if (val != null && val !== "" && !(Array.isArray(val) && !val.length)) { if (!merged[k] || (Array.isArray(merged[k]) && !merged[k].length) || merged[k] === EMPTY[k]) merged[k] = val; } };
        keep("name", p.name); keep("contact", p.contact); keep("role", p.role);
        keep("email", p.email); keep("phone", p.phone); keep("linkedin", p.linkedin);
        keep("website", p.website); keep("companyPhone", p.companyPhone); keep("companyLinkedin", p.companyLinkedin);
        keep("city", p.city); keep("country", p.country);
        if (TYPE_OPTIONS.includes(p.type)) merged.type = p.type;
        if (p.budgetMin) merged.budgetMin = p.budgetMin; if (p.budgetMax) merged.budgetMax = p.budgetMax;
        if (p.yieldMin) merged.yieldMin = p.yieldMin; if (p.walbMin) merged.walbMin = p.walbMin;
        if (p.monovalent) merged.monovalent = p.monovalent;
        if (typeof p.vacancy === "boolean") merged.vacancy = p.vacancy;
        if (typeof p.works === "boolean") merged.works = p.works;
        // listes : on fusionne (union)
        const uni = (a, b) => [...new Set([...(a || []), ...(b || [])])];
        merged.typologies = uni(merged.typologies, (p.typologies || []).filter(t => TYPO_OPTIONS.includes(t)));
        merged.tenants = uni(merged.tenants, (p.tenants || []).filter(t => TENANT_OPTIONS.includes(t)));
        merged.excluded = uni(merged.excluded, p.excluded);
        merged.regions = uni(merged.regions, p.regions);
        merged.strategies = strs.length ? uni(merged.strategies, strs) : merged.strategies;
        merged.acquisitions = [...(merged.acquisitions || []), ...((p.acquisitions || []).map(a => ({ ...a, source: "IA" })))];
        merged.enrichments = [...enr, ...(merged.enrichments || [])];
        return merged;
      });
      // zones géocodées (ajout aux zones manuelles existantes)
      const cities = (p.cities || []).slice(0, 6);
      const pts = [];
      for (const c of cities) { const g = await geocode(c + " France"); if (g) pts.push({ name: c, lat: g.lat, lng: g.lng, radius: 30 }); }
      if (pts.length) setZones(z => [...z, ...pts]);
      setIaDone(true); setIaOpen(false);
    } catch (e) { setErr(e.isAuth ? "IA indisponible : secret ANTHROPIC_API_KEY manquant ou invalide côté serveur (Supabase)." : "Extraction impossible. Vérifiez le document ou complétez manuellement."); }
    finally { setParsing(false); }
  };
  const onFile = (fl) => { if (!fl) return; const r = new FileReader(); r.onload = () => { setFile(r.result.split(",")[1]); setFileName(fl.name); }; r.readAsDataURL(fl); };
  const save = () => { if (!f.name.trim()) return; onSave({ ...f, zones, acquisitions: f.acquisitions || [], enrichments: f.enrichments || [] }); };
  const inp = { width: "100%", padding: "10px 13px", borderRadius: 11, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13.5, outline: "none" };
  const lab = { fontSize: 11, color: C.faint, marginBottom: 5, display: "block" };

  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, background: "rgba(28,27,51,.35)", backdropFilter: "blur(3px)", display: "flex", alignItems: "center", justifyContent: "center", padding: 24, zIndex: 80 }}>
      <div onClick={e => e.stopPropagation()} className="rise modal-card" style={{ maxWidth: 680, width: "100%", maxHeight: "92vh", overflowY: "auto", background: C.panel, border: `1px solid ${C.lineStrong}`, borderRadius: 20, padding: 28 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 18 }}>
          <div className="serif" style={{ fontSize: 21, fontWeight: 700 }}>Nouveau contact investisseur</div>
          <span onClick={onClose} style={{ cursor: "pointer", fontSize: 24, color: C.dim }}>×</span>
        </div>

        {/* Bloc IA intégré (complémentaire à la saisie) */}
        <div className="card" style={{ padding: 0, marginBottom: 20, overflow: "hidden", border: `1px solid ${iaDone ? C.emerald + "66" : "#c9cbf5"}` }}>
          <div onClick={() => setIaOpen(o => !o)} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "12px 16px", cursor: "pointer", background: iaDone ? "rgba(16,168,126,.08)" : C.sky }}>
            <div style={{ fontSize: 13.5, fontWeight: 600, color: iaDone ? C.emerald : C.indigo }}>
              {iaDone ? "✓ Champs pré-remplis par l'IA — vérifiez et complétez ci-dessous" : "⟐ Pré-remplir avec un cahier des charges ou une note (optionnel)"}
            </div>
            <span style={{ color: C.dim, fontSize: 13 }}>{iaOpen ? "▲" : "▼"}</span>
          </div>
          {iaOpen && (
            <div style={{ padding: 16 }}>
              {parsing ? (
                <div style={{ textAlign: "center", padding: "20px 0" }}>
                  <div style={{ width: 40, height: 40, margin: "0 auto 14px", borderRadius: "50%", border: `3px solid ${C.line}`, borderTopColor: C.violet, animation: "spin .8s linear infinite" }} />
                  <div style={{ color: C.dim, fontSize: 13 }}>Extraction des critères et géocodage des zones…</div>
                </div>
              ) : (
                <>
                  <label className="card" style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 10, padding: "14px", borderRadius: 11, cursor: "pointer", border: `1.5px dashed ${file ? C.violet : C.lineStrong}`, background: file ? C.sky : C.panel2, marginBottom: 12 }}>
                    <input type="file" accept="application/pdf" style={{ display: "none" }} onChange={e => onFile(e.target.files[0])} />
                    <span style={{ fontSize: 16 }}>{file ? "✓" : "⬆"}</span>
                    <span style={{ fontSize: 12.5, color: file ? C.violet : C.dim }}>{fileName || "PDF (cahier des charges) — cliquez pour choisir"}</span>
                  </label>
                  <textarea value={raw} onChange={e => setRaw(e.target.value)} disabled={!!file} placeholder="…ou collez un email / une note investisseur (ex : terrains en baux à construction, magasins alimentaires spécialisés, animaleries, budget 2 à 15 M€…)" style={{ ...inp, height: 90, lineHeight: 1.5, resize: "vertical", opacity: file ? 0.4 : 1 }} />
                  {err && <div style={{ color: C.rose, fontSize: 12.5, marginTop: 8 }}>{err}</div>}
                  <div style={{ marginTop: 12, display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
                    {file && <button className="btn btn-g" onClick={() => { setFile(null); setFileName(""); }}>Retirer le PDF</button>}
                    <button className="btn btn-p" disabled={!raw.trim() && !file} onClick={parseIA} style={{ opacity: (raw.trim() || file) ? 1 : 0.5 }}>{iaDone ? "Relancer l'extraction" : "Pré-remplir les champs →"}</button>
                    <span style={{ fontSize: 11.5, color: C.faint }}>Les infos extraites complètent les champs et l'enrichissement IA, sans écraser votre saisie.</span>
                  </div>
                </>
              )}
            </div>
          )}
        </div>

        {/* Formulaire (toujours visible) */}
        <>
            <Section title="Interlocuteur">
              <ContactsEditor contacts={(f.contacts && f.contacts.length) ? f.contacts : ((f.contact||f.email||f.phone||f.role||f.linkedin) ? [{name:f.contact||"",role:f.role||"",email:f.email||"",phone:f.phone||"",linkedin:f.linkedin||""}] : [])} setContacts={(cs) => set("contacts", cs)} />
            </Section>
            <Section title="Société">
              <div className="grid-2" style={{ gap: 12 }}>
                <div style={{ gridColumn: "1 / -1" }}><label style={lab}>Raison sociale *</label><input style={inp} value={f.name} onChange={e => set("name", e.target.value)} /></div>
                <div><label style={lab}>Type</label><select style={inp} value={f.type} onChange={e => set("type", e.target.value)}>{TYPE_OPTIONS.map(o => <option key={o}>{o}</option>)}</select></div>
                <div><label style={lab}>Statut</label><select style={inp} value={f.status} onChange={e => set("status", e.target.value)}>{["Actif", "En négociation", "À relancer", "Inactif"].map(o => <option key={o}>{o}</option>)}</select></div>
                <div><label style={lab}>Site internet</label><input style={inp} value={f.website} onChange={e => set("website", e.target.value)} placeholder="societe.fr" /></div>
                <div><label style={lab}>Tél. fixe société</label><input style={inp} value={f.companyPhone} onChange={e => set("companyPhone", e.target.value)} /></div>
                <div style={{ gridColumn: "1 / -1" }}><label style={lab}>LinkedIn société</label><input style={inp} value={f.companyLinkedin} onChange={e => set("companyLinkedin", e.target.value)} placeholder="linkedin.com/company/…" /></div>
                <div><label style={lab}>Ville (siège)</label><input style={inp} value={f.city} onChange={e => set("city", e.target.value)} /></div>
                <div><label style={lab}>Pays</label><input style={inp} value={f.country} onChange={e => set("country", e.target.value)} /></div>
              </div>
            </Section>
            <Section title="Profil d'investissement">
              <div className="grid-2" style={{ gap: 12 }}>
                <div><label style={lab}>Budget min (€)</label><input style={inp} type="number" value={f.budgetMin} onChange={e => set("budgetMin", +e.target.value)} /></div>
                <div><label style={lab}>Budget max (€)</label><input style={inp} type="number" value={f.budgetMax} onChange={e => set("budgetMax", +e.target.value)} /></div>
                <div><label style={lab}>Rendement min (%)</label><input style={inp} type="number" step="0.1" value={f.yieldMin} onChange={e => set("yieldMin", +e.target.value)} /></div>
                <div><label style={lab}>WALB résiduel min (ans)</label><input style={inp} type="number" value={f.walbMin} onChange={e => set("walbMin", +e.target.value)} /></div>
                <div><label style={lab}>Actif monovalent</label><select style={inp} value={f.monovalent || "indifférent"} onChange={e => set("monovalent", e.target.value)}><option value="indifférent">Indifférent</option><option value="oui">Recherché</option><option value="non">Non accepté</option></select></div>
              </div>
              <div style={{ marginTop: 12 }}><label style={lab}>Stratégies (plusieurs possibles)</label><div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{STRAT_OPTIONS.map(o => <span key={o} onClick={() => toggle("strategies", o)} className="chip" style={{ cursor: "pointer", background: f.strategies.includes(o) ? `linear-gradient(100deg,${C.indigo},${C.violet})` : undefined, color: f.strategies.includes(o) ? "#fff" : undefined, border: f.strategies.includes(o) ? "none" : undefined }}>{o}</span>)}</div></div>
              <div style={{ display: "flex", gap: 22, marginTop: 14 }}>
                <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, cursor: "pointer", color: C.dim }}><input type="checkbox" checked={f.vacancy} onChange={e => set("vacancy", e.target.checked)} /> Accepte la vacance</label>
                <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 13, cursor: "pointer", color: C.dim }}><input type="checkbox" checked={f.works} onChange={e => set("works", e.target.checked)} /> Accepte les travaux</label>
              </div>
            </Section>
            <Section title="Zones géographiques de prospection"><ZoneEditor zones={zones} setZones={setZones} regions={f.regions || []} departements={f.departements || []} /></Section>
            <Section title="Régions & départements ciblés">
              <label style={{ fontSize: 11, color: C.faint, marginBottom: 5, display: "block" }}>Régions</label>
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 14 }}>{REGION_OPTIONS.map(o => <span key={o} onClick={() => toggle("regions", o)} className="chip" style={{ cursor: "pointer", background: (f.regions || []).includes(o) ? "rgba(91,99,232,.12)" : undefined, color: (f.regions || []).includes(o) ? C.indigo : undefined, borderColor: (f.regions || []).includes(o) ? `${C.indigo}55` : undefined }}>{o}</span>)}</div>
              <label style={{ fontSize: 11, color: C.faint, marginBottom: 5, display: "block" }}>Départements</label>
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6, maxHeight: 150, overflowY: "auto", padding: 2 }}>{DEPARTEMENT_OPTIONS.map(o => <span key={o} onClick={() => toggle("departements", o)} className="chip" style={{ cursor: "pointer", fontSize: 11.5, background: (f.departements || []).includes(o) ? "rgba(91,99,232,.12)" : undefined, color: (f.departements || []).includes(o) ? C.indigo : undefined, borderColor: (f.departements || []).includes(o) ? `${C.indigo}55` : undefined }}>{o}</span>)}</div>
            </Section>
            <Section title="Typologies recherchées">
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{TYPO_OPTIONS.map(o => <span key={o} onClick={() => toggle("typologies", o)} className="chip" style={{ cursor: "pointer", background: f.typologies.includes(o) ? "rgba(16,168,126,.12)" : undefined, color: f.typologies.includes(o) ? C.emerald : undefined, borderColor: f.typologies.includes(o) ? `${C.emerald}55` : undefined }}>{o}</span>)}</div>
            </Section>
            <Section title="Types de locataires recherchés">
              <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{TENANT_OPTIONS.map(o => <span key={o} onClick={() => toggle("tenants", o)} className="chip" style={{ cursor: "pointer", background: f.tenants.includes(o) ? "rgba(124,92,255,.12)" : undefined, color: f.tenants.includes(o) ? C.violet : undefined, borderColor: f.tenants.includes(o) ? `${C.violet}55` : undefined }}>{o}</span>)}</div>
            </Section>
            <div style={{ marginTop: 24, display: "flex", gap: 9, justifyContent: "flex-end" }}>
              <button className="btn btn-g" onClick={onClose}>Annuler</button>
              <button className="btn btn-p" onClick={save} style={{ opacity: f.name.trim() ? 1 : 0.5 }}>Enregistrer le contact</button>
            </div>
          </>
      </div>
    </div>
  );
}

function EmailModal({ m, deal, onClose }) {
  const prenom = (m.inv.contact || "").split(" ")[0] || "Madame, Monsieur";
  const body = `Objet : Opportunité d'investissement — ${deal.typology.toLowerCase()} à ${deal.city} — rendement ${deal.yield} %

Bonjour ${prenom},

Je me permets de vous adresser cette opportunité car elle correspond à vos critères d'investissement actuels, notamment sur les ${m.inv.typologies[0].toLowerCase()} avec un rendement sécurisé.

L'actif est situé à ${deal.city}, développe ${deal.surface} m² et génère ${eur(deal.rent)} de revenus locatifs annuels, pour un prix de ${eur(deal.price)}, soit un rendement acte en main de ${deal.yield} %.

Au regard de votre dernière acquisition (${(m.inv.acquisitions && m.inv.acquisitions[0]) ? m.inv.acquisitions[0].asset + " à " + m.inv.acquisitions[0].city : "vos opérations récentes"}), ce dossier s'inscrit pleinement dans votre stratégie ${(m.inv.strategies || []).join(" / ")}.

Souhaitez-vous que je vous transmette le dossier complet ?

Bien cordialement,
DORIC GROUPE`;
  const [copied, setCopied] = useState(false);
  return (
    <div onClick={onClose} style={{ position: "fixed", inset: 0, background: "rgba(28,27,51,.35)", backdropFilter: "blur(3px)", display: "flex", alignItems: "center", justifyContent: "center", padding: 30, zIndex: 70 }}>
      <div onClick={e => e.stopPropagation()} className="rise modal-card" style={{ maxWidth: 640, width: "100%", background: C.panel, border: `1px solid ${C.lineStrong}`, borderRadius: 20, padding: 28 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
          <div className="serif" style={{ fontSize: 19, fontWeight: 700 }}>Email d'approche — {m.inv.name}</div>
          <span onClick={onClose} style={{ cursor: "pointer", fontSize: 24, color: C.dim }}>×</span>
        </div>
        <textarea defaultValue={body} style={{ width: "100%", height: 310, padding: 16, borderRadius: 13, border: `1px solid ${C.line}`, background: C.panel2, color: C.text, fontSize: 13, lineHeight: 1.6, resize: "vertical", outline: "none" }} />
        <div style={{ marginTop: 16, textAlign: "right", display: "flex", gap: 9, justifyContent: "flex-end" }}>
          <button className="btn btn-g" onClick={onClose}>Fermer</button>
          <button className="btn btn-p" onClick={() => { setCopied(true); setTimeout(() => setCopied(false), 1600); }}>{copied ? "✓ Copié" : "Copier & ouvrir dans l'email"}</button>
        </div>
      </div>
    </div>
  );
}
