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

function Enseignes({ enseignes, local, onOpen, onCreate, onDelete, onOpenImport, onEnrich, onCriterion, go }) {
  const [q, setQ] = useState(""); const [f, setF] = useState("Tous");
  const [sort, setSort] = useState({ key: "name", dir: 1 });
  const [selected, setSelected] = useState([]);
  // enrichissement IA
  const [running, setRunning] = useState(false);
  const [results, setResults] = useState([]);
  const [err, setErr] = useState("");
  const [progress, setProgress] = useState("");
  const [enrichDone, setEnrichDone] = useState(0);
  const [enrichTotal, setEnrichTotal] = useState(0);
  const [enrichSel, setEnrichSel] = useState([]);
  const toggleEnrich = (id) => setEnrichSel(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
  const allEnrichSelected = enseignes.length > 0 && enrichSel.length === enseignes.length;
  const toggleAllEnrich = () => setEnrichSel(allEnrichSelected ? [] : enseignes.map(e => e.id));

  const sectors = ["Tous", ...new Set(enseignes.map(e => e.sector).filter(Boolean))];
  const filtered = enseignes.filter(e => (f === "Tous" || e.sector === f) &&
    (e.name + (e.sector || "") + (e.city || "") + (e.contact || "") + (e.localTypes || []).join(" ")).toLowerCase().includes(q.toLowerCase()));
  const getVal = (e, k) => {
    if (k === "name") return e.name.toLowerCase();
    if (k === "sector") return e.sector || "";
    if (k === "surface") return e.surfaceMax || 0;
    if (k === "rent") return e.rentMax || 0;
    if (k === "relation") return e.relation || 0;
    if (k === "status") return e.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 });

  const toggleSel = (id) => setSelected(s => s.includes(id) ? s.filter(x => x !== id) : [...s, id]);
  const allVisibleSelected = list.length > 0 && list.every(e => selected.includes(e.id));
  const toggleAll = () => setSelected(allVisibleSelected ? selected.filter(id => !list.some(e => e.id === id)) : [...new Set([...selected, ...list.map(e => e.id)])]);
  const selectedEns = enseignes.filter(e => selected.includes(e.id));

  const surfTxt = (e) => `${e.surfaceMin || 0}–${e.surfaceMax || "∞"} m²`;
  const EXPORT_COLS = [
    ["Enseigne", e => e.name], ["Type", e => e.type], ["Secteur", e => e.sector], ["Contact", e => e.contact],
    ["Fonction", e => e.role], ["Email", e => e.email], ["Mobile", e => e.phone],
    ["LinkedIn contact", e => e.linkedin], ["Site web", e => e.website], ["Tél. société", e => e.companyPhone],
    ["LinkedIn société", e => e.companyLinkedin], ["Ville", e => e.city], ["Pays", e => e.country],
    ["Surface min (m²)", e => e.surfaceMin], ["Surface max (m²)", e => e.surfaceMax], ["Loyer max (€/m²/an)", e => e.rentMax],
    ["Façade min (m)", e => e.frontageMin], ["Flux min", e => e.fluxMin], ["Droit au bail", e => e.droitAuBail],
    ["Types de locaux", e => (e.localTypes || []).join(" / ")], ["Exclus", e => (e.excluded || []).join(" / ")],
    ["Zones", e => (e.zones || []).map(z => `${z.name} (${fmtRadius(z.radius)})`).join(" / ")],
    ["Régions", e => (e.regions || []).join(" / ")], ["Plan de développement", e => e.devPlan], ["Statut", e => e.status],
  ];
  const exportCSV = () => {
    const rows = [EXPORT_COLS.map(c => c[0])];
    selectedEns.forEach(e => rows.push(EXPORT_COLS.map(c => { const v = c[1](e); 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");
    const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
    const a = document.createElement("a"); a.href = URL.createObjectURL(blob);
    a.download = `enseignes_${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 = selectedEns.map(e => `
      <div class="card"><h2>${e.name} <span class="badge">${e.sector || e.type}</span></h2>
        <div class="grid">
          <div><b>Contact</b> ${e.contact || "—"}${e.role ? " · " + e.role : ""}</div>
          <div><b>Email</b> ${e.email || "—"}</div>
          <div><b>Mobile</b> ${e.phone || "—"}</div>
          <div><b>Ville (siège)</b> ${e.city || "—"}, ${e.country || ""}</div>
          <div><b>Surface</b> ${surfTxt(e)}</div>
          <div><b>Loyer max</b> ${e.rentMax || "—"} €/m²/an</div>
          <div><b>Façade min</b> ${e.frontageMin || 0} m</div>
          <div><b>Flux min</b> ${e.fluxMin || "—"}</div>
        </div>
        <div class="row"><b>Types de locaux</b> ${(e.localTypes || []).join(", ") || "—"}</div>
        <div class="row"><b>Zones</b> ${(e.zones || []).map(z => `${z.name} (${fmtRadius(z.radius)})`).join(", ") || "—"}</div>
        <div class="row"><b>Plan de développement</b> ${e.devPlan || "—"}</div>
      </div>`).join("");
    w.document.write(`<!DOCTYPE html><html lang="fr"><head><meta charset="utf-8"><title>Enseignes — 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'enseignes preneuses</h1><div class="sub">DoricMatch AI · ${selectedEns.length} enseigne(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();
  };

  const runEnrichment = async () => {
    const targets = enseignes.filter(e => enrichSel.includes(e.id));
    if (!targets.length) { setErr("Sélectionnez au moins une enseigne à enrichir."); return; }
    if (!confirmCost(`Enrichissement IA de ${targets.length} enseigne(s) (0,20 €/enseigne).`, targets.length * IA_COSTS.enrich)) return;
    setRunning(true); setErr(""); setResults([]); setEnrichDone(0); setEnrichTotal(targets.length);
    const out = [];
    try {
      for (const ens of targets) {
        setProgress(`Recherche sur ${ens.name}…`);
        const sys = `Tu es un analyste en immobilier commercial qui ENRICHIT la fiche d'une ENSEIGNE (preneur à bail) à partir de sources WEB, et en déduit son cahier des charges d'implantation. Pour l'enseigne donnée, recherche en priorité : (1) ses COMMUNIQUÉS DE PRESSE et plan de développement / expansion, (2) sa PAGE LINKEDIN, (3) son SITE WEB officiel (rubrique implantation / franchise / nous rejoindre), (4) la presse spécialisée retail. Concentre-toi sur : nouvelles ouvertures, villes ciblées, surfaces recherchées, types d'emplacements (centre-ville, retail park, centre commercial, bureaux…), budget loyer, nombre d'ouvertures prévues. Renvoie UNIQUEMENT un JSON :
{"found":[{"field":"secteur|emplacement|surface|loyer|zone|other","value":"texte court","source":"Communiqué de presse|Plan de développement|LinkedIn|Site web|Presse spécialisée","url":"lien si dispo sinon vide","confidence":0-100}],
"criteria":[{"field":"localType|sector|region|surfaceMin|surfaceMax|rentMax|frontageMin|fluxMin","value":"valeur précise (ex: 'Retail park', 'Île-de-France', '120', '350', '450')","label":"libellé court","confidence":0-100}]}
"found" = actualités qui enrichissent la fiche. "criteria" = critères d'implantation STRUCTURÉS (localType = un type de local, region = une région, surfaceMin/surfaceMax/rentMax/frontageMin/fluxMin = un nombre). Max 4 found + 4 criteria. N'invente rien : si une info n'est pas trouvée, ne la mets pas.`;
        let data;
        try {
          data = await callClaude({
            model: AI_MODELS.standard, max_tokens: 1100, tools: webTools(6, true), system: sys,
            messages: [{ role: "user", content: `Enseigne à enrichir : ${ens.name} (${ens.sector || ens.type}), siège ${ens.city || "n.c."}.\nSite web : ${ens.website || "n.c."}\nLinkedIn : ${ens.companyLinkedin || "n.c."}\nCommence par ces sources, puis élargis aux communiqués et à la presse retail.\nCritères actuels : surface ${ens.surfaceMin || "?"}–${ens.surfaceMax || "?"} m², loyer max ${ens.rentMax || "?"} €/m²/an, types ${(ens.localTypes || []).join(", ") || "—"}.` }],
          });
        } catch (e) {
          if (e.isAuth) { setErr("IA indisponible : secret ANTHROPIC_API_KEY manquant ou invalide côté serveur (Supabase)."); setRunning(false); return; }
          continue;
        }
        const txt = data.content.filter(b => b.type === "text").map(b => b.text).join("").replace(/```json|```/g, "").trim();
        let parsed = { found: [], criteria: [] };
        try { parsed = JSON.parse(txt.slice(txt.indexOf("{"), txt.lastIndexOf("}") + 1)); } catch (_) {}
        const found = (parsed.found || []).map(x => ({ ...x, applied: false }));
        const criteria = (parsed.criteria || []).map(x => ({ ...x, applied: false }));
        if (found.length || criteria.length) out.push({ ensId: ens.id, ensName: ens.name, found, criteria });
        setEnrichDone(d => d + 1);
      }
      setResults(out);
      if (!out.length) setErr("Aucune actualité fiable trouvée pour le moment.");
    } finally { setRunning(false); setProgress(""); }
  };
  const applyOne = (ri, fi) => {
    setResults(rs => rs.map((r, i) => i === ri ? { ...r, found: r.found.map((x, j) => j === fi ? { ...x, applied: true } : x) } : r));
    const r = results[ri], x = r.found[fi];
    onEnrich(r.ensId, { field: x.field, label: ENS_FIELD_LABELS[x.field] || "Information", value: x.value, source: x.source, url: x.url, confidence: x.confidence, date: new Date().toLocaleDateString("fr-FR") });
  };
  const applyCrit = (ri, ci) => {
    setResults(rs => rs.map((r, i) => i === ri ? { ...r, criteria: r.criteria.map((x, j) => j === ci ? { ...x, applied: true } : x) } : r));
    const r = results[ri], c = r.criteria[ci];
    onCriterion(r.ensId, { field: c.field, label: c.label || ENS_CRIT_LABELS[c.field] || "Critère", value: c.value, source: "Enrichissement IA", confidence: c.confidence });
  };

  const actifs = filtered.filter(e => e.status === "Actif").length;
  const enriched = enseignes.filter(e => (e.enrichments || []).length > 0).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 || 0) * 100)}%</span>; };
  const cols = [["name", "Enseigne", "left"], ["sector", "Secteur", "left"], ["surface", "Surface", "right"], ["rent", "Loyer max", "right"], ["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, flexWrap: "wrap", gap: 12 }}>
        <div>
          <h1 className="serif" style={{ fontSize: 34, margin: 0, fontWeight: 700, letterSpacing: "-.5px" }}>Base enseignes</h1>
          <p style={{ color: C.dim, fontSize: 14, marginTop: 7 }}>Enseignes en recherche de locaux à louer (commerces & bureaux). Cliquez une ligne pour la fiche complète.</p>
        </div>
        <div style={{ display: "flex", gap: 10 }}>
          <button className="btn btn-g" onClick={() => go("uploadLocal")}>▭ Analyser un local</button>
          <button className="btn btn-g" onClick={onOpenImport}>⬆ Importer (CSV)</button>
          <button className="btn btn-p" onClick={onCreate}>+ Nouvelle enseigne</button>
        </div>
      </div>

      <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 }}>Enseignes actives</div>
        </div>
        <div className="card" style={{ padding: "14px 16px" }}>
          <div style={{ fontSize: 18, fontWeight: 700, color: C.cyan }}>{enriched}</div>
          <div style={{ fontSize: 11, color: C.dim, marginTop: 3 }}>Fiches enrichies par IA</div>
        </div>
      </div>

      <div style={{ display: "flex", gap: 10, marginBottom: 14, alignItems: "center", flexWrap: "wrap" }}>
        <input placeholder="Rechercher (enseigne, secteur, ville, contact, type de local)…" 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" }}>
          {sectors.map(s => <option key={s}>{s}</option>)}
        </select>
        <span style={{ fontSize: 12, color: C.faint }}>{list.length} résultat{list.length > 1 ? "s" : ""}</span>
      </div>

      <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} enseigne(s) sélectionnée(s)` : "Cochez des enseignes 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>

      <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((ens) => {
                const sel = selected.includes(ens.id);
                return (
                  <tr key={ens.id} onClick={() => onOpen(ens.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(ens.id)} style={{ cursor: "pointer" }} />
                    </td>
                    <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}` }}>
                      <div style={{ fontWeight: 600 }}>{ens.name}</div>
                      <div style={{ fontSize: 11.5, color: C.faint, marginTop: 2 }}>{ens.contact || <span style={{ color: C.amber }}>contact manquant</span>}{ens.city ? " · " + ens.city : ""}</div>
                      <div style={{ marginTop: 5, display: "flex", gap: 4, flexWrap: "wrap" }}>
                        {(ens.localTypes || []).slice(0, 3).map(t => <span key={t} style={{ fontSize: 10, padding: "2px 6px", borderRadius: 5, background: C.panel2, color: C.dim }}>{t}</span>)}
                        {(ens.localTypes || []).length > 3 && <span style={{ fontSize: 10, color: C.faint }}>+{ens.localTypes.length - 3}</span>}
                      </div>
                    </td>
                    <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, color: C.dim }}>{ens.sector || "—"}</td>
                    <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, textAlign: "right", whiteSpace: "nowrap" }}>{surfTxt(ens)}</td>
                    <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, textAlign: "right", fontWeight: 600, color: C.cyan }}>{ens.rentMax ? ens.rentMax + " €/m²" : "—"}</td>
                    <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}`, fontSize: 12 }}>{dot(ens.relation)}</td>
                    <td style={{ padding: "12px 14px", borderBottom: `1px solid ${C.line}` }}>
                      <span style={{ fontSize: 11, color: STATUS_C[ens.status], border: `1px solid ${STATUS_C[ens.status]}55`, padding: "2px 9px", borderRadius: 7, whiteSpace: "nowrap" }}>{ens.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 l'enseigne « ${ens.name} » ?`)) onDelete(ens.id); }}
                        title="Supprimer" 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>
                );
              })}
              {list.length === 0 && <tr><td colSpan={8} style={{ padding: "30px 14px", textAlign: "center", color: C.faint, fontSize: 13 }}>Aucune enseigne. Créez-en une ou importez un fichier CSV.</td></tr>}
            </tbody>
          </table>
        </div>
      </div>

      {/* Enrichissement IA des enseignes */}
      <div className="card rise" style={{ padding: 24, marginTop: 22 }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 12 }}>
          <div>
            <div className="serif" style={{ fontSize: 19, fontWeight: 700 }}>Enrichissement IA des enseignes</div>
            <div style={{ fontSize: 13, color: C.dim, marginTop: 4 }}>L'IA recherche le plan de développement de vos enseignes (presse retail, communiqués, LinkedIn) et propose des critères d'implantation à ajouter à leurs fiches.</div>
          </div>
          <button className="btn btn-p" onClick={runEnrichment} disabled={running || enrichSel.length === 0} style={{ opacity: (running || enrichSel.length === 0) ? .55 : 1 }}>
            {running ? "Recherche en cours…" : `⟐ Enrichir ${enrichSel.length || ""} enseigne${enrichSel.length > 1 ? "s" : ""}`.trim()}</button>
        </div>
        <div style={{ marginTop: 16, padding: 14, borderRadius: 12, background: C.panel2, border: `1px solid ${C.line}` }}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 10, flexWrap: "wrap", gap: 8 }}>
            <label style={{ display: "inline-flex", alignItems: "center", gap: 8, cursor: "pointer", fontSize: 13, fontWeight: 600 }}>
              <input type="checkbox" checked={allEnrichSelected} onChange={toggleAllEnrich} style={{ cursor: "pointer" }} /> Tout sélectionner
            </label>
            <span style={{ fontSize: 12, color: C.faint }}>{enrichSel.length} / {enseignes.length} sélectionnée(s) · 1 recherche IA par enseigne</span>
          </div>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 8, maxHeight: 180, overflowY: "auto" }}>
            {enseignes.length === 0 ? <span style={{ fontSize: 13, color: C.faint }}>Aucune enseigne dans la base.</span>
              : enseignes.map(e => {
                const on = enrichSel.includes(e.id);
                const never = !(e.enrichments && e.enrichments.length);
                return (
                  <span key={e.id} onClick={() => toggleEnrich(e.id)} className="chip" title={never ? "Jamais enrichie" : "Déjà enrichie"} style={{ cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 6, background: on ? `linear-gradient(100deg,${C.indigo},${C.violet})` : undefined, color: on ? "#fff" : undefined, border: on ? "none" : undefined }}>
                    {never && <span style={{ width: 7, height: 7, borderRadius: "50%", background: on ? "#fff" : C.amber, flex: "none" }} />}
                    <span style={{ fontSize: 11 }}>{on ? "✓" : "+"}</span>{e.name}
                  </span>
                );
              })}
          </div>
        </div>
        {running && (
          <div style={{ marginTop: 16 }}>
            <div style={{ display: "flex", justifyContent: "space-between", fontSize: 12.5, color: C.dim, marginBottom: 6 }}><span>{progress || "Recherche en cours…"}</span><span>{enrichDone}/{enrichTotal}</span></div>
            <div style={{ height: 8, background: C.panel2, borderRadius: 6, overflow: "hidden" }}><div style={{ height: "100%", width: (enrichTotal ? Math.round(enrichDone / enrichTotal * 100) : 0) + "%", background: `linear-gradient(90deg,${C.indigo},${C.violet})`, borderRadius: 6, transition: "width .4s" }} /></div>
          </div>
        )}
        {err && <div style={{ marginTop: 14, fontSize: 13, color: C.amber }}>{err}</div>}
      </div>

      {results.length > 0 && (
        <div className="rise" style={{ marginTop: 22 }}>
          <div style={{ fontSize: 12, textTransform: "uppercase", letterSpacing: "1.4px", color: C.faint, marginBottom: 14 }}>Informations trouvées — à valider et ajouter aux fiches</div>
          {results.map((r, ri) => (
            <div key={ri} className="card" style={{ padding: 20, marginBottom: 12 }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 12 }}>
                <span className="serif" style={{ fontSize: 17, fontWeight: 600, cursor: "pointer" }} onClick={() => onOpen(r.ensId)}>{r.ensName}</span>
                <span style={{ fontSize: 12, color: C.indigo, cursor: "pointer" }} onClick={() => onOpen(r.ensId)}>Voir la fiche →</span>
              </div>
              {r.found.map((x, fi) => (
                <div key={fi} style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 12, padding: "10px 0", borderTop: fi ? `1px solid ${C.line}` : "none" }}>
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 13.5 }}><b style={{ color: C.violet }}>{ENS_FIELD_LABELS[x.field] || "Info"}</b> · {x.value}</div>
                    <div style={{ fontSize: 11.5, color: C.faint, marginTop: 3, display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
                      <span className="chip" style={{ padding: "1px 7px" }}>{x.source}</span><span>fiabilité {x.confidence} %</span>{x.url && <a href={x.url} target="_blank" rel="noreferrer">↗ source</a>}
                    </div>
                  </div>
                  {x.applied ? <span style={{ fontSize: 12, color: C.emerald, fontWeight: 600, whiteSpace: "nowrap" }}>✓ Ajouté</span>
                    : <button className="btn btn-g" style={{ padding: "7px 13px", whiteSpace: "nowrap" }} onClick={() => applyOne(ri, fi)}>+ Ajouter à la fiche</button>}
                </div>
              ))}
              {r.criteria && r.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: 8 }}>Critères d'implantation à affiner (impactent le matching)</div>
                  {r.criteria.map((c, ci) => (
                    <div key={ci} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12, padding: "8px 0", borderTop: ci ? `1px solid ${C.line}` : "none" }}>
                      <div style={{ fontSize: 13 }}><b style={{ color: C.indigo }}>{ENS_CRIT_LABELS[c.field] || c.label || "Critère"}</b> · {c.value}<span style={{ fontSize: 11, color: C.faint, marginLeft: 6 }}>({c.confidence} %)</span></div>
                      {c.applied ? <span style={{ fontSize: 12, color: C.emerald, fontWeight: 600, whiteSpace: "nowrap" }}>✓ Critère ajouté</span>
                        : <button className="btn btn-p" style={{ padding: "7px 13px", whiteSpace: "nowrap" }} onClick={() => applyCrit(ri, ci)}>+ Affiner le matching</button>}
                    </div>
                  ))}
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </>
  );
}

function EnseigneDrawer({ ens, local, onClose, onSave, onDelete }) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState(ens);
  useEffect(() => { setDraft(ens); setEditing(false); }, [ens.id]);
  const m = local ? scoreEnseigne(ens, local) : null;
  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 }}>{ens.name}</div>
            <div style={{ fontSize: 13, color: C.dim, marginTop: 4 }}>{ens.sector || ens.type}{ens.city ? " · " + ens.city : ""}{ens.country ? ", " + ens.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 l'enseigne « ${ens.name} » ?`)) onDelete(ens.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[ens.status], border: `1px solid ${STATUS_C[ens.status]}55`, padding: "3px 11px", borderRadius: 8 }}>{ens.status}</span>
        {editing ? <EnseigneEdit draft={draft} setDraft={setDraft} onCancel={() => { setDraft(ens); setEditing(false); }} onSave={save} />
          : <EnseigneRead ens={ens} m={m} onSave={onSave} />}
      </div>
    </div>
  );
}

function EnseigneRead({ ens, m, onSave }) {
  const ia = (k) => (ens.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 ENS_NOTE_FIELD_KEY = { localType: "localTypes", sector: "sector", region: "regions", departement: "departements", surfaceMin: "surfaceMin", surfaceMax: "surfaceMax", rentMax: "rentMax", frontageMin: "frontageMin", fluxMin: "fluxMin" };
  const [fbText, setFbText] = useState("");
  const [fbLocal, setFbLocal] = useState("");
  const [suggesting, setSuggesting] = useState(false);
  const [suggestion, setSuggestion] = useState(null);
  const [sugErr, setSugErr] = useState("");
  const locaux = ens.locaux || [];
  const LOCAL_STATUSES = ["Proposé", "Envoyé", "Relancé", "Intéressé", "Visite", "Refusé", "En négociation", "Signé", "Archivé"];
  const STATUS_COLORS = { "Proposé": C.cyan, "Envoyé": C.indigo, "Relancé": C.amber, "Intéressé": C.emerald, "Visite": C.violet, "Refusé": C.rose, "En négociation": C.violet, "Signé": C.emerald, "Archivé": C.faint };
  const setLocalStatus = (lid, status) => onSave({ ...ens, locaux: locaux.map(x => x.id === lid ? { ...x, status } : x) });

  const addFeedback = () => {
    if (!fbText.trim()) return;
    const loc = locaux.find(x => x.id === fbLocal);
    const entry = { text: fbText.trim(), localId: fbLocal || null, localTitle: loc ? loc.title : "", date: new Date().toLocaleDateString("fr-FR") };
    const updated = loc ? locaux.map(x => x.id === fbLocal ? { ...x, feedback: fbText.trim() } : x) : locaux;
    onSave({ ...ens, feedback: [entry, ...(ens.feedback || [])], locaux: updated });
    setFbText("");
  };
  const completeCriteria = async () => {
    setSuggesting(true); setSugErr(""); setSuggestion(null);
    const fbBlocks = (ens.feedback || []).map(f => {
      const loc = locaux.find(x => x.id === f.localId);
      const recap = loc ? `Local proposé : ${loc.title} — ${loc.type || "?"}, ${loc.localisation || "?"}, ${loc.surface || "?"}, loyer ${loc.loyer || "?"}.` : "Local : (non précisé).";
      return `${recap}\nRetour de l'enseigne : ${f.text}`;
    }).join("\n\n");
    const sys = `Tu es analyste en immobilier commercial. On te donne, pour une ENSEIGNE preneuse, les LOCAUX qu'on lui a proposés et son RETOUR sur chacun. Déduis comment affiner son cahier des charges. Renvoie UNIQUEMENT un JSON : {"criteria":[{"label":"libellé court","value":"précision chiffrée si possible"}],"note":"synthèse en 1 phrase"}. Exemples : refus pour surface trop petite → relever surface min ; refus loyer → baisser loyer max ; intérêt centre-ville → ajouter ce type. Max 5 critères.`;
    try {
      const data = await callClaude({ model: AI_MODELS.standard, max_tokens: 800, system: sys,
        messages: [{ role: "user", content: `Enseigne : ${ens.name} (${ens.sector || ens.type}). Critères actuels : surface ${ens.surfaceMin || "?"}–${ens.surfaceMax || "?"} m², loyer max ${ens.rentMax || "?"} €/m²/an, types ${(ens.localTypes || []).join(", ") || "—"}, régions ${(ens.regions || []).join(", ") || "—"}.\n\nLocaux proposé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 local", url: "", confidence: 90, date: new Date().toLocaleDateString("fr-FR") };
    onSave({ ...ens, enrichments: [entry, ...(ens.enrichments || [])] });
    setSuggestion(s => ({ ...s, criteria: s.criteria.filter(x => x !== c) }));
  };
  const dab = ens.droitAuBail === "oui" ? "Accepté" : ens.droitAuBail === "non" ? "Refusé" : "Indifférent";

  // Enrichir la fiche enseigne avec une note ou un document (cahier des charges, mail, PDF…)
  const [noteText, setNoteText] = useState("");
  const [noteDocs, setNoteDocs] = useState([]);
  const [noteBusy, setNoteBusy] = useState(false);
  const [noteErr, setNoteErr] = useState("");
  const [noteOut, setNoteOut] = useState(null);
  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 commercial. À partir d'une NOTE et/ou de DOCUMENTS (cahier des charges, mail, PDF) concernant une ENSEIGNE preneuse, tu extrais (1) des informations utiles pour sa fiche et (2) des CRITÈRES D'IMPLANTATION STRUCTURÉS qui affineront le matching. Réponds UNIQUEMENT en JSON :
{"found":[{"label":"libellé court","value":"texte court","confidence":0-100}],
"criteria":[{"field":"localType|sector|region|departement|surfaceMin|surfaceMax|rentMax|frontageMin|fluxMin","value":"valeur précise (ex: 'Retail park','Restauration rapide','Normandie','14 — Calvados','120','350','450')","label":"libellé court","confidence":0-100}]}
Pour les listes (localType/region/departement) une valeur = un élément (répète l'objet si plusieurs). region = une région française, departement = 'code — nom' (ex: '14 — Calvados'). surfaceMin/surfaceMax/rentMax/frontageMin/fluxMin = nombre. Si rien de fiable, listes vides.`;
    const content = [{ type: "text", text: `Enseigne : ${ens.name} (${ens.sector || ens.type}). Critères actuels : surface ${ens.surfaceMin || "?"}–${ens.surfaceMax || "?"} m², loyer max ${ens.rentMax || "?"} €/m²/an, façade ${ens.frontageMin || 0} m, flux ${ens.fluxMin || "?"}, types ${(ens.localTypes || []).join(", ") || "—"}, régions ${(ens.regions || []).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 (une seule écriture) : les champs se remplissent seuls.
      const uni = (arr, v) => [...new Set([...(arr || []), v])];
      const num = (v) => { const n = parseFloat(String(v).replace(",", ".").replace(/[^0-9.]/g, "")); return isNaN(n) ? null : n; };
      const next = { ...ens };
      const aiKeys = new Set(ens.aiFields || []);
      criteria.forEach(c => {
        switch (c.field) {
          case "localType": next.localTypes = uni(next.localTypes, c.value); break;
          case "sector": next.sector = c.value; break;
          case "region": next.regions = uni(next.regions, c.value); break;
          case "departement": next.departements = uni(next.departements, c.value); break;
          case "surfaceMin": { const n = num(c.value); if (n != null) next.surfaceMin = n; break; }
          case "surfaceMax": { const n = num(c.value); if (n != null) next.surfaceMax = n; break; }
          case "rentMax": { const n = num(c.value); if (n != null) next.rentMax = n; break; }
          case "frontageMin": { const n = num(c.value); if (n != null) next.frontageMin = n; break; }
          case "fluxMin": { const n = num(c.value); if (n != null) next.fluxMin = n; break; }
          default: break;
        }
        const k = ENS_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 || ENS_CRIT_LABELS[c.field] || "Critère") + " : " + c.value, source: "Note / document", url: "", confidence: c.confidence || 88, date: now })),
      ];
      next.enrichments = [...entries, ...(ens.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({ ...ens, enrichments: [entry, ...(ens.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 = { ...ens };
    const uni = (arr, v) => [...new Set([...(arr || []), v])];
    const num = (v) => { const n = parseFloat(String(v).replace(",", ".").replace(/[^0-9.]/g, "")); return isNaN(n) ? null : n; };
    switch (c.field) {
      case "localType": next.localTypes = uni(ens.localTypes, c.value); break;
      case "sector": next.sector = c.value; break;
      case "region": next.regions = uni(ens.regions, c.value); break;
      case "departement": next.departements = uni(ens.departements, c.value); break;
      case "surfaceMin": { const n = num(c.value); if (n != null) next.surfaceMin = n; break; }
      case "surfaceMax": { const n = num(c.value); if (n != null) next.surfaceMax = n; break; }
      case "rentMax": { const n = num(c.value); if (n != null) next.rentMax = n; break; }
      case "frontageMin": { const n = num(c.value); if (n != null) next.frontageMin = n; break; }
      case "fluxMin": { const n = num(c.value); if (n != null) next.fluxMin = n; break; }
      default: break;
    }
    const nk = ENS_NOTE_FIELD_KEY[c.field]; if (nk) next.aiFields = [...new Set([...(ens.aiFields || []), nk])];
    next.enrichments = [{ field: "other", label: "Critère affiné", value: (c.label || ENS_CRIT_LABELS[c.field] || "Critère") + " : " + c.value, source: "Note / document", url: "", confidence: c.confidence || 88, date: new Date().toLocaleDateString("fr-FR") }, ...(ens.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} />
        <Section title="Interlocuteur">
          <ContactsView contacts={ens.contacts} />
        </Section>
        <Section title="Enseigne / société">
          <div className="grid-2" style={{ gap: "0 30px" }}>
            <Row k="Raison sociale" v={ens.name} /><Row k="Type" v={ens.type} /><Row k="Secteur" v={ens.sector || "—"} />
            {ens.website && <Row k="Site internet" v={<a href={`https://${ens.website.replace(/^https?:\/\//, "")}`} target="_blank" rel="noreferrer">{ens.website}</a>} />}
            {ens.companyPhone && <Row k="Tél. société" v={<a href={`tel:${ens.companyPhone.replace(/\s/g, "")}`}>{ens.companyPhone}</a>} />}
            {ens.companyLinkedin && <Row k="LinkedIn société" v={<a href={`https://${ens.companyLinkedin.replace(/^https?:\/\//, "")}`} target="_blank" rel="noreferrer">{ens.companyLinkedin}</a>} />}
          </div>
        </Section>
        {m && <Section title="Matching avec le local 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="Cahier des charges preneur" color={C.emerald} />
        <Section title="Critères d'implantation">
          <div className="grid-2" style={{ gap: "0 30px" }}>
            <Row k="Surface recherchée" v={withIa(`${ens.surfaceMin || 0} – ${ens.surfaceMax || "∞"} m²`, ia("surfaceMax") ? "surfaceMax" : "surfaceMin")} />
            <Row k="Loyer max" v={withIa(ens.rentMax ? ens.rentMax + " €/m²/an" : "—", "rentMax")} />
            <Row k="Façade min" v={withIa((ens.frontageMin || 0) + " m", "frontageMin")} />
            <Row k="Flux min" v={withIa(ens.fluxMin ? ens.fluxMin.toLocaleString("fr-FR") : "—", "fluxMin")} />
            <Row k="Droit au bail / pas-de-porte" v={dab} />
            <Row k="Plan de développement" v={ens.devPlan || "—"} />
          </div>
        </Section>
        <Section title="Zones de développement">
          <ZoneMap zones={ens.zones || []} regions={ens.regions || []} departements={ens.departements || []} activeIdx={-1} editable={false} height={210} />
          <div style={{ marginTop: 10, display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" }}>
            {(ens.zones || []).map((z, i) => <span key={i} className="chip" style={{ color: C.indigo, borderColor: `${C.indigo}44` }}>{z.name} · {fmtRadius(z.radius)}</span>)}
            {(ens.regions || []).map(r => <span key={r} className="chip">{r}</span>)}
            {ia("regions") && <IaTag />}
            {!(ens.zones || []).length && !(ens.regions || []).length && <span style={{ fontSize: 13, color: C.faint }}>—</span>}
          </div>
          {(ens.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>
            {(ens.departements || []).map(d => <span key={d} className="chip" style={{ fontSize: 11 }}>{d}</span>)}
            {ia("departements") && <IaTag />}
          </div>}
        </Section>
        <Section title="Types de locaux recherchés">
          <div style={{ display: "flex", flexWrap: "wrap", gap: 6, alignItems: "center" }}>{(ens.localTypes || []).map(t => <span key={t} className="chip" style={{ color: C.emerald, borderColor: `${C.emerald}44` }}>{t}</span>)}{ia("localTypes") && <IaTag />}{!(ens.localTypes || []).length && <span style={{ fontSize: 13, color: C.faint }}>—</span>}</div>
          {(ens.excluded || []).length > 0 && <div style={{ marginTop: 10, display: "flex", flexWrap: "wrap", gap: 6 }}>{ens.excluded.map(t => <span key={t} className="chip" style={{ color: C.rose, borderColor: `${C.rose}44` }}>⊘ {t}</span>)}</div>}
        </Section>
      </div>

      <div>
        <Block title="Données enrichies par IA" color={C.violet} />
        <Section title="Implantations existantes">
          {(ens.implantations || []).length === 0 && <div style={{ fontSize: 13, color: C.faint }}>Aucune implantation enregistrée.</div>}
          <div style={{ maxHeight: (ens.implantations || []).length > 4 ? 280 : "none", overflowY: (ens.implantations || []).length > 4 ? "auto" : "visible", paddingRight: (ens.implantations || []).length > 4 ? 6 : 0 }}>
            {(ens.implantations || []).map((a, i) => (
              <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", padding: "10px 0", borderBottom: i < ens.implantations.length - 1 ? `1px solid ${C.line}` : "none", fontSize: 13 }}>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 500 }}>{a.site}{a.city ? " · " + a.city : ""}</div>
                  <div style={{ color: C.faint, fontSize: 12, marginTop: 2, display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
                    {a.year && <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 }}>↗ lien</a>}
                  </div>
                </div>
                {a.surface && <div style={{ textAlign: "right", color: C.cyan, marginLeft: 12 }}>{a.surface}</div>}
              </div>
            ))}
          </div>
        </Section>
        <Section title="Enrichissement IA">
          {(ens.enrichments || []).length === 0
            ? <div style={{ fontSize: 13, color: C.faint }}>Aucun enrichissement. Lancez la recherche IA depuis la base enseignes.</div>
            : <div style={{ maxHeight: (ens.enrichments || []).length > 4 ? 280 : "none", overflowY: (ens.enrichments || []).length > 4 ? "auto" : "visible", paddingRight: (ens.enrichments || []).length > 4 ? 6 : 0 }}>
              {(ens.enrichments || []).map((e, i) => (
                <div key={i} style={{ padding: "10px 0", borderBottom: i < ens.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>}
        </Section>
        <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'implantation, ajoutables d'un clic. Les critères affinent le matching.</div>
          <textarea value={noteText} onChange={e => setNoteText(e.target.value)} placeholder="Ex : cherche désormais 200–350 m² en retail park sur la Normandie, loyer max 300 €/m²/an, façade > 10 m…"
            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'implantation (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 }}>{ENS_CRIT_LABELS[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 locaux" color={C.cyan} />
        <Section title="Historique des locaux proposés">
          {locaux.length === 0 && <div style={{ fontSize: 13, color: C.faint }}>Aucun local proposé. Depuis « Analyser un local », envoyez le local aux enseignes ciblées.</div>}
          {locaux.map((l) => (
            <div key={l.id} className="card" style={{ padding: "12px 14px", marginBottom: 8 }}>
              <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 10 }}>
                <div><div style={{ fontWeight: 600, fontSize: 13.5 }}>{l.title}</div><div style={{ fontSize: 12, color: C.faint, marginTop: 2 }}>{l.type || ""}{l.localisation ? " · " + l.localisation : ""}{l.surface ? " · " + l.surface : ""}{l.loyer ? " · " + l.loyer : ""}</div></div>
                <select value={l.status || "Proposé"} onChange={e => setLocalStatus(l.id, e.target.value)} style={{ padding: "5px 8px", borderRadius: 8, border: `1px solid ${STATUS_COLORS[l.status] || C.line}`, color: STATUS_COLORS[l.status] || C.dim, fontSize: 12, background: C.panel, outline: "none" }}>
                  {LOCAL_STATUSES.map(s => <option key={s}>{s}</option>)}
                </select>
              </div>
              {l.feedback && <div style={{ fontSize: 12, color: C.dim, marginTop: 6, fontStyle: "italic" }}>Retour : {l.feedback}</div>}
            </div>
          ))}
        </Section>
        <Section title="Retours & affinage du cahier des charges">
          <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 8 }}>
            {locaux.length > 0 && (
              <select value={fbLocal} onChange={e => setFbLocal(e.target.value)} style={{ padding: "9px 11px", borderRadius: 10, border: `1px solid ${C.line}`, fontSize: 12.5, background: C.panel, color: C.text, outline: "none" }}>
                <option value="">Retour général (sans local)</option>
                {locaux.map(l => <option key={l.id} value={l.id}>{l.title}</option>)}
              </select>
            )}
          </div>
          <textarea value={fbText} onChange={e => setFbText(e.target.value)} placeholder="Ex : surface trop petite, cherche plutôt 250 m² ; loyer trop élevé pour la zone…" style={{ width: "100%", height: 70, padding: 10, borderRadius: 10, border: `1px solid ${C.line}`, background: C.panel, color: C.text, fontSize: 13, resize: "vertical", outline: "none" }} />
          <div style={{ marginTop: 8, display: "flex", gap: 8, flexWrap: "wrap" }}>
            <button className="btn btn-g" onClick={addFeedback} disabled={!fbText.trim()} style={{ opacity: fbText.trim() ? 1 : .5 }}>+ Ajouter le retour</button>
            <button className="btn btn-p" onClick={completeCriteria} disabled={suggesting || !(ens.feedback || []).length} style={{ opacity: (suggesting || !(ens.feedback || []).length) ? .5 : 1 }}>{suggesting ? "Analyse IA…" : "✦ Affiner les critères (IA)"}</button>
          </div>
          {(ens.feedback || []).length > 0 && (
            <div style={{ marginTop: 12 }}>
              {(ens.feedback || []).map((f, i) => (
                <div key={i} style={{ padding: "8px 0", borderTop: i ? `1px solid ${C.line}` : "none", fontSize: 13 }}>
                  <div>{f.text}</div>
                  <div style={{ fontSize: 11, color: C.faint, marginTop: 2 }}>{f.localTitle ? f.localTitle + " · " : ""}{f.date}</div>
                </div>
              ))}
            </div>
          )}
          {sugErr && <div style={{ marginTop: 10, fontSize: 12.5, color: C.amber }}>{sugErr}</div>}
          {suggestion && (
            <div style={{ marginTop: 12, padding: 14, borderRadius: 12, background: C.panel2, border: `1px solid ${C.line}` }}>
              {suggestion.note && <div style={{ fontSize: 12.5, color: C.dim, marginBottom: 8 }}>{suggestion.note}</div>}
              {(suggestion.criteria || []).map((c, i) => (
                <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 10, padding: "6px 0", borderTop: i ? `1px solid ${C.line}` : "none" }}>
                  <div style={{ fontSize: 13 }}><b style={{ color: C.indigo }}>{c.label}</b>{c.value ? " · " + c.value : ""}</div>
                  <button className="btn btn-g" style={{ padding: "6px 11px" }} onClick={() => addCriterion(c)}>+ Ajouter</button>
                </div>
              ))}
            </div>
          )}
        </Section>
      </div>
    </div>
  );
}

function EnseigneEdit({ 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" };
  const setImp = (i, key, val) => setDraft(s => ({ ...s, implantations: s.implantations.map((a, j) => j === i ? { ...a, [key]: val } : a) }));
  const addImp = () => setDraft(s => ({ ...s, implantations: [...(s.implantations || []), { site: "", city: "", surface: "", year: "", source: "Manuel", url: "" }] }));
  const delImp = (i) => setDraft(s => ({ ...s, implantations: s.implantations.filter((_, j) => j !== i) }));
  return (
    <div style={{ marginTop: 20 }}>
      <Section title="Interlocuteur">
        <ContactsEditor accent={C.emerald} 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="Enseigne / 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)}>{ENS_TYPE_OPTIONS.map(o => <option key={o}>{o}</option>)}</select></div>
          <div><label style={lab}>Secteur / activité</label><select style={inp} value={draft.sector} onChange={e => set("sector", e.target.value)}>{SECTOR_OPTIONS.map(o => <option key={o}>{o}</option>)}</select></div>
          <div><label style={lab}>Statut</label><select style={inp} value={draft.status} onChange={e => set("status", e.target.value)}>{ENS_STATUS_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="enseigne.fr" /></div>
          <div><label style={lab}>Tél. 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 (siège)</label><input style={inp} value={draft.city} onChange={e => set("city", e.target.value)} /></div>
          <div><label style={lab}>Pays</label><input style={inp} value={draft.country} onChange={e => set("country", e.target.value)} /></div>
        </div>
      </Section>
      <Section title="Cahier des charges preneur">
        <div className="grid-2" style={{ gap: 12 }}>
          <div><label style={lab}>Surface min (m²)</label><input style={inp} type="number" value={draft.surfaceMin || 0} onChange={e => set("surfaceMin", +e.target.value)} /></div>
          <div><label style={lab}>Surface max (m²)</label><input style={inp} type="number" value={draft.surfaceMax || 0} onChange={e => set("surfaceMax", +e.target.value)} /></div>
          <div><label style={lab}>Loyer max (€/m²/an)</label><input style={inp} type="number" value={draft.rentMax || 0} onChange={e => set("rentMax", +e.target.value)} /></div>
          <div><label style={lab}>Façade min (m linéaire)</label><input style={inp} type="number" value={draft.frontageMin || 0} onChange={e => set("frontageMin", +e.target.value)} /></div>
          <div><label style={lab}>Flux min (passages/jour)</label><input style={inp} type="number" value={draft.fluxMin || 0} onChange={e => set("fluxMin", +e.target.value)} /></div>
          <div><label style={lab}>Droit au bail / pas-de-porte</label><select style={inp} value={draft.droitAuBail || "indifférent"} onChange={e => set("droitAuBail", e.target.value)}><option value="indifférent">Indifférent</option><option value="oui">Accepté</option><option value="non">Refusé</option></select></div>
          <div style={{ gridColumn: "1 / -1" }}><label style={lab}>Plan de développement (nb d'ouvertures prévues, échéance…)</label><input style={inp} value={draft.devPlan || ""} onChange={e => set("devPlan", e.target.value)} placeholder="Ex : 8 ouvertures / an, priorité Grand Ouest" /></div>
        </div>
      </Section>
      <Section title="Zones de développement"><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="Types de locaux recherchés">
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{LOCAL_TYPE_OPTIONS.map(o => <span key={o} onClick={() => toggle("localTypes", o)} className="chip" style={{ cursor: "pointer", background: (draft.localTypes || []).includes(o) ? "rgba(16,168,126,.12)" : undefined, color: (draft.localTypes || []).includes(o) ? C.emerald : undefined, borderColor: (draft.localTypes || []).includes(o) ? `${C.emerald}55` : undefined }}>{o}</span>)}</div>
      </Section>
      <Section title="Types de locaux exclus">
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{LOCAL_TYPE_OPTIONS.map(o => <span key={o} onClick={() => toggle("excluded", o)} className="chip" style={{ cursor: "pointer", background: (draft.excluded || []).includes(o) ? "rgba(226,72,107,.1)" : undefined, color: (draft.excluded || []).includes(o) ? C.rose : undefined, borderColor: (draft.excluded || []).includes(o) ? `${C.rose}55` : undefined }}>{o}</span>)}</div>
      </Section>
      <Section title="Implantations existantes">
        {(draft.implantations || []).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="Site / magasin" value={a.site} onChange={e => setImp(i, "site", e.target.value)} />
              <input style={inp} placeholder="Ville" value={a.city} onChange={e => setImp(i, "city", e.target.value)} />
              <input style={inp} placeholder="Surface (ex: 220 m²)" value={a.surface} onChange={e => setImp(i, "surface", e.target.value)} />
              <input style={inp} placeholder="Année" value={a.year} onChange={e => setImp(i, "year", e.target.value)} />
              <select style={inp} value={a.source} onChange={e => setImp(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 (URL)" value={a.url} onChange={e => setImp(i, "url", e.target.value)} />
              <button className="btn btn-g" style={{ padding: "6px 12px", color: C.rose }} onClick={() => delImp(i)}>Suppr.</button>
            </div>
          </div>
        ))}
        <button className="btn btn-g" onClick={addImp}>+ Ajouter une implantation</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 CreateEnseigneModal({ onClose, onSave }) {
  const [f, setF] = useState({ ...EMPTY_ENS });
  const [zones, setZones] = useState([]);
  const [raw, setRaw] = useState(""); const [file, setFile] = useState(null); const [fileName, setFileName] = useState("");
  const [parsing, setParsing] = useState(false); 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 onFile = (fl) => { if (!fl) return; const r = new FileReader(); r.onload = () => { setFile(r.result.split(",")[1]); setFileName(fl.name); }; r.readAsDataURL(fl); };
  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" };

  const parseIA = async () => {
    setParsing(true); setErr("");
    const sys = `Tu es un extracteur de cahier des charges d'IMPLANTATION pour une ENSEIGNE preneuse à bail. Renvoie UNIQUEMENT un JSON valide (sans backticks) :
{"name":string,"type":un parmi ${JSON.stringify(ENS_TYPE_OPTIONS)},"sector":un parmi ${JSON.stringify(SECTOR_OPTIONS)},"contact":string,"role":string,"email":string,"phone":string,"linkedin":string,"website":string,"companyPhone":string,"companyLinkedin":string,"city":string,"country":string,"surfaceMin":number,"surfaceMax":number,"rentMax":number,"frontageMin":number,"fluxMin":number,"droitAuBail":"oui"|"non"|"indifférent","localTypes":tableau parmi ${JSON.stringify(LOCAL_TYPE_OPTIONS)},"excluded":tableau parmi ${JSON.stringify(LOCAL_TYPE_OPTIONS)},"cities":tableau de villes ciblées,"regions":tableau,"devPlan":string,"implantations":tableau d'objets {site,city,surface,year,url},"highlights":tableau de phrases d'actualité notables}
Champs absents = "" ou [] ou 0. rentMax = loyer max en €/m²/an. Prends le responsable développement/expansion si plusieurs contacts.`;
    const content = file
      ? [{ type: "document", source: { type: "base64", media_type: "application/pdf", data: file } }, { type: "text", text: "Extrais le cahier des charges de cette enseigne." }]
      : [{ 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 today = new Date().toLocaleDateString("fr-FR");
      const src = file ? (fileName || "Cahier des charges") : "Note / email";
      const enr = [];
      (Array.isArray(p.highlights) ? p.highlights : []).forEach(h => enr.push({ field: "other", label: "Actualité / développement", value: h, source: src, url: "", confidence: 85, date: today }));
      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_ENS[k]) merged[k] = val; } };
        ["name", "contact", "role", "email", "phone", "linkedin", "website", "companyPhone", "companyLinkedin", "city", "country", "devPlan"].forEach(k => keep(k, p[k]));
        if (ENS_TYPE_OPTIONS.includes(p.type)) merged.type = p.type;
        if (SECTOR_OPTIONS.includes(p.sector)) merged.sector = p.sector;
        if (p.surfaceMin) merged.surfaceMin = p.surfaceMin; if (p.surfaceMax) merged.surfaceMax = p.surfaceMax;
        if (p.rentMax) merged.rentMax = p.rentMax; if (p.frontageMin) merged.frontageMin = p.frontageMin; if (p.fluxMin) merged.fluxMin = p.fluxMin;
        if (p.droitAuBail) merged.droitAuBail = p.droitAuBail;
        const uni = (a, b) => [...new Set([...(a || []), ...(b || [])])];
        merged.localTypes = uni(merged.localTypes, (p.localTypes || []).filter(t => LOCAL_TYPE_OPTIONS.includes(t)));
        merged.excluded = uni(merged.excluded, (p.excluded || []).filter(t => LOCAL_TYPE_OPTIONS.includes(t)));
        merged.regions = uni(merged.regions, p.regions);
        merged.implantations = [...(merged.implantations || []), ...((p.implantations || []).map(a => ({ ...a, source: "IA" })))];
        merged.enrichments = [...enr, ...(merged.enrichments || [])];
        return merged;
      });
      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 save = () => { if (!f.name.trim()) return; onSave({ ...f, zones, implantations: f.implantations || [], enrichments: f.enrichments || [] }); };

  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 }}>Nouvelle enseigne</div>
          <span onClick={onClose} style={{ cursor: "pointer", fontSize: 24, color: C.dim }}>×</span>
        </div>
        <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 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 du cahier des charges 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 (ex : enseigne restauration rapide, cherche 150–250 m² en centre-ville et retail park, loyer max 350 €/m²/an, 10 ouvertures prévues sur le Grand Ouest…)" 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>
                  </div>
                </>
              )}
            </div>
          )}
        </div>

        <Section title="Interlocuteur">
          <ContactsEditor accent={C.emerald} 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="Enseigne / société">
          <div className="grid-2" style={{ gap: 12 }}>
            <div style={{ gridColumn: "1 / -1" }}><label style={lab}>Raison sociale / enseigne *</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)}>{ENS_TYPE_OPTIONS.map(o => <option key={o}>{o}</option>)}</select></div>
            <div><label style={lab}>Secteur / activité</label><select style={inp} value={f.sector} onChange={e => set("sector", e.target.value)}>{SECTOR_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)}>{ENS_STATUS_OPTIONS.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="enseigne.fr" /></div>
            <div><label style={lab}>Tél. 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="Cahier des charges preneur">
          <div className="grid-2" style={{ gap: 12 }}>
            <div><label style={lab}>Surface min (m²)</label><input style={inp} type="number" value={f.surfaceMin} onChange={e => set("surfaceMin", +e.target.value)} /></div>
            <div><label style={lab}>Surface max (m²)</label><input style={inp} type="number" value={f.surfaceMax} onChange={e => set("surfaceMax", +e.target.value)} /></div>
            <div><label style={lab}>Loyer max (€/m²/an)</label><input style={inp} type="number" value={f.rentMax} onChange={e => set("rentMax", +e.target.value)} /></div>
            <div><label style={lab}>Façade min (m)</label><input style={inp} type="number" value={f.frontageMin} onChange={e => set("frontageMin", +e.target.value)} /></div>
            <div><label style={lab}>Flux min (passages/jour)</label><input style={inp} type="number" value={f.fluxMin} onChange={e => set("fluxMin", +e.target.value)} /></div>
            <div><label style={lab}>Droit au bail / pas-de-porte</label><select style={inp} value={f.droitAuBail} onChange={e => set("droitAuBail", e.target.value)}><option value="indifférent">Indifférent</option><option value="oui">Accepté</option><option value="non">Refusé</option></select></div>
            <div style={{ gridColumn: "1 / -1" }}><label style={lab}>Plan de développement</label><input style={inp} value={f.devPlan} onChange={e => set("devPlan", e.target.value)} placeholder="Ex : 8 ouvertures / an, priorité Grand Ouest" /></div>
          </div>
        </Section>
        <Section title="Zones géographiques de développement"><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="Types de locaux recherchés">
          <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>{LOCAL_TYPE_OPTIONS.map(o => <span key={o} onClick={() => toggle("localTypes", o)} className="chip" style={{ cursor: "pointer", background: f.localTypes.includes(o) ? "rgba(16,168,126,.12)" : undefined, color: f.localTypes.includes(o) ? C.emerald : undefined, borderColor: f.localTypes.includes(o) ? `${C.emerald}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 l'enseigne</button>
        </div>
      </div>
    </div>
  );
}

function ImportEnseignesModal({ existing, onClose, onImport }) {
  const norm = (s) => String(s || "").toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/[^a-z0-9]/g, "");
  const TARGETS = [
    ["name", "Enseigne", true], ["sector", "Secteur / activité", false], ["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'enseigne", false],
  ];
  const SYN = {
    name: ["enseigne", "societe", "company", "companyname", "entreprise", "raisonsociale", "nomsociete", "organization", "accountname", "currentcompany", "marque", "brand"],
    sector: ["secteur", "activite", "sector", "industry", "domaine", "categorie"],
    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", "typeenseigne"],
  };
  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();
    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); } }
    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."); 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(e => ((e.email || "").toLowerCase().trim()) || norm(e.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_ENS, name, type: get(r, "type") || "Enseigne nationale", sector: get(r, "sector") || "Autre",
        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 enseignes (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 ; vous pourrez les ajuster.</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="Enseigne;Secteur;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 « Enseigne » 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ête(s) · {built.dup} doublon(s) · {built.noName} sans enseigne :</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>{["Enseigne", "Secteur", "Contact", "Email", "Ville"].map(h => <th key={h} style={th}>{h}</th>)}</tr></thead>
                <tbody>
                  {built.out.slice(0, 8).map((e, idx) => (
                    <tr key={idx} style={{ borderBottom: `1px solid ${C.panel2}` }}>
                      <td style={{ padding: "6px 10px", fontWeight: 600 }}>{e.name}</td>
                      <td style={{ padding: "6px 10px", color: C.dim }}>{e.sector || "—"}</td>
                      <td style={{ padding: "6px 10px", color: C.dim }}>{e.contact || "—"}{e.role ? " · " + e.role : ""}</td>
                      <td style={{ padding: "6px 10px", color: C.dim }}>{e.email || "—"}</td>
                      <td style={{ padding: "6px 10px", color: C.dim }}>{e.city || "—"}</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} enseigne(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} enseigne(s) importée(s)</div><div style={{ fontSize: 12.5, color: C.dim }}>{result.dup} doublon(s) ignoré(s){result.noName ? ` · ${result.noName} ligne(s) sans enseigne` : ""}</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 UploadLocal({ 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 du local…", "Géocodage & analyse…", "Matching enseignes…"];
  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 local.">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 l'annonce d'un local à louer (commerce ou bureaux) ET/OU ajoutez une description. L'IA combine les deux, extrait le local, le géocode, puis lance le matching sur vos enseignes.">Analyser un local à louer</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 l'annonce du local 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 la description du local :"}</div>
        <textarea value={text} onChange={e => setText(e.target.value)} placeholder="Collez ici (surface, loyer €/m²/an, ville, type d'emplacement, linéaire de façade, flux, droit au bail…)"
          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 local + la description" : fileData ? "le local" : "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 (local exemple)</button>
        </div>
      </div>
    </>
  );
}

function EnseigneResults({ local, matches, onEmail, onOpen, onAttach, history, onRecordRun, goOpenInv, go }) {
  const [subtab, setSubtab] = useState("current");
  const [sent, setSent] = useState([]);
  const [selected, setSelected] = useState([]);
  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);
  const rs = local ? (local.rentSqm || (local.surface ? Math.round((local.rentAnnual || 0) / local.surface) : 0)) : 0;
  const localRecap = () => local ? ({
    title: local.name, type: local.localType || "", localisation: [local.city, local.region].filter(Boolean).join(", "),
    surface: local.surface ? local.surface + " m²" : "", loyer: rs ? rs + " €/m²/an" : "", facade: local.frontage ? local.frontage + " m" : "",
    flux: local.flux || "", dab: local.droitAuBail || 0, date: new Date().toLocaleDateString("fr-FR"), status: "Envoyé", feedback: "",
  }) : {};
  const sendLocal = (id) => { if (!onAttach || sent.includes(id)) return; onAttach([id], localRecap()); setSent(s => [...s, id]); };
  const VERDICT = { fort: C.emerald, moyen: C.amber, faible: C.rose };
  // ── Historique : instantané + enregistrement du run ──
  const snapshot = () => matches.slice(0, 25).map(m => ({ id: m.ens.id, name: m.ens.name, sub: [m.ens.sector || m.ens.type, m.ens.city].filter(Boolean).join(" · "), global: m.global, matched: m.matched || [], blocking: m.blocking || [], confidence: m.confidence }));
  useEffect(() => {
    if (!local || !local.runId || !onRecordRun) return;
    onRecordRun({ runId: local.runId, kind: "enseignes", subject: localRecap(), matches: snapshot(), sent, ai: null });
  }, [local && local.runId]);

  const aiRerank = async () => {
    if (!selected.length) return;
    if (!confirmCost(`Affinage IA de ${selected.length} enseigne(s) (0,05 €/enseigne).`, selected.length * IA_COSTS.rerank)) return;
    setAiRunning(true); setAiErr(""); setAiResults(null);
    const chosen = matches.filter(m => selected.includes(m.ens.id));
    const sys = "Tu es un analyste senior en immobilier commercial. On te donne un LOCAL à louer et une liste d'enseignes pré-sélectionnées par un algorithme, avec leur pré-score et leur cahier des charges. Challenge ce pré-classement sur la pertinence qualitative (adéquation enseigne/emplacement, zone de chalandise, image). Renvoie UNIQUEMENT un JSON valide, sans backticks.";
    const localTxt = `LOCAL : ${local.name} | type ${local.localType} | ${[local.city, local.region].filter(Boolean).join(", ")} | surface ${local.surface || "?"} m² | loyer ${rs || "?"} €/m²/an | façade ${local.frontage || "?"} m | flux ${local.flux || "?"} | droit au bail ${local.droitAuBail || 0} €`;
    const ensTxt = chosen.map(m => {
      const e = m.ens;
      return `- id:${e.id} | ${e.name} (${e.sector || e.type}) | types: ${(e.localTypes || []).join(", ") || "—"} | surface ${e.surfaceMin || "?"}-${e.surfaceMax || "?"} m² | loyer max ${e.rentMax || "?"} €/m²/an | zones/régions: ${(e.regions || []).join(", ") || (e.zones || []).map(z => z.name).join(", ") || "—"} | PRÉ-SCORE: ${m.global}/100 | forts: ${(m.matched || []).join(", ") || "—"} | bloquants: ${(m.blocking || []).join(", ") || "—"}`;
    }).join("\n");
    const fmt = '{"ranking":[{"ensId":"id","aiScore":0,"verdict":"fort|moyen|faible","rationale":"2-3 phrases d\'argumentaire","edge":"ce que l\'algo a pu rater, sinon vide","flag":"réserve, sinon vide"}]}';
    try {
      const data = await callClaude({ model: AI_MODELS.standard, max_tokens: 1200, system: sys,
        messages: [{ role: "user", content: `${localTxt}\n\nENSEIGNES PRÉ-SÉLECTIONNÉES :\n${ensTxt}\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.ensId != null) map[r.ensId] = r; }); setAiResults(map);
      if (onRecordRun && local && local.runId) onRecordRun({ runId: local.runId, kind: "enseignes", subject: localRecap(), 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); }
  };
  const ordered = aiResults
    ? [...matches].sort((a, b) => { const A = aiResults[a.ens.id], B = aiResults[b.ens.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;

  if (subtab === "history") {
    return (
      <>
        <H sub="Résumé du local, puis classement des enseignes par pertinence. Proposez le local aux enseignes ciblées.">Résultats du matching</H>
        <ResultTabs tab={subtab} setTab={setSubtab} count={(history || []).length} />
        <MatchHistory history={history} onOpenInv={goOpenInv} onOpenEns={onOpen} />
      </>
    );
  }
  if (!local) {
    return (
      <>
        <H sub="Résumé du local, puis classement des enseignes par pertinence. Proposez le local aux enseignes ciblées.">Résultats du matching</H>
        <ResultTabs tab={subtab} setTab={setSubtab} count={(history || []).length} />
        <EnseigneEmpty go={go} />
      </>
    );
  }

  return (
    <>
      <H sub="Résumé du local, puis classement des enseignes par pertinence. Proposez le local aux enseignes ciblées.">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 }}>{local.name}</div>
        <div style={{ display: "flex", gap: 26, marginTop: 14, flexWrap: "wrap", fontSize: 13.5 }}>
          <Stat label="Type" v={local.localType || "—"} /><Stat label="Surface" v={(local.surface || "—") + " m²"} /><Stat label="Loyer" v={(rs || "—") + " €/m²/an"} c={C.emerald} />
          <Stat label="Façade" v={(local.frontage || "—") + " m"} /><Stat label="Flux" v={local.flux ? local.flux.toLocaleString("fr-FR") : "—"} /><Stat label="Droit au bail" v={local.droitAuBail ? eur(local.droitAuBail) : "—"} />
        </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 }}>Atouts</div>{(local.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 }}>Points de vigilance</div>{(local.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} enseignes classées{selected.length ? ` · ${selected.length} sélectionnée(s)` : ""}</span>
        <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>
      </div>
      {!selected.length && <div style={{ fontSize: 12.5, color: C.faint, marginBottom: 14 }}>Cochez des enseignes, puis « Affiner avec l'IA » pour un re-classement qualitatif.</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>}

      {ordered.map((m, i) => {
        const t = tier(m.global);
        const isSent = sent.includes(m.ens.id); const sel = selected.includes(m.ens.id);
        const ai = aiResults && aiResults[m.ens.id]; const vColor = ai ? (VERDICT[(ai.verdict || "").toLowerCase()] || C.dim) : null;
        return (
          <div key={m.ens.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.ens.id)} style={{ cursor: "pointer", marginTop: 5 }} />
                <div>
                  <div className="serif" style={{ fontSize: 18, fontWeight: 600, cursor: "pointer" }} onClick={() => onOpen(m.ens.id)}>{m.ens.name}</div>
                  <div style={{ fontSize: 12.5, color: C.dim, marginTop: 3 }}>{m.ens.sector || m.ens.type}{m.ens.city ? " · " + m.ens.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(ENS_PART_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` }}>✓ Local proposé</button>
                : <button className="btn btn-p" onClick={() => sendLocal(m.ens.id)}>✉ Proposer le local</button>}
              <button className="btn btn-g" onClick={() => onEmail(m)}>Email d'approche</button>
              <button className="btn btn-g" onClick={() => onOpen(m.ens.id)}>Voir la fiche</button>
            </div>
          </div>
        );
      })}
    </>
  );
}

function EnseigneEmailModal({ m, local, settings, onClose }) {
  const ens = m.ens;
  const rs = local.rentSqm || (local.surface ? Math.round((local.rentAnnual || 0) / local.surface) : 0);
  const broker = (settings && settings.broker) || "Eric THYBERT";
  const company = (settings && settings.company) || "DORIC GROUPE";
  const phone = (settings && settings.phone) || "";
  const greet = ens.contact ? `Bonjour ${ens.contact},` : "Bonjour,";
  const body = `${greet}

Je me permets de vous adresser une opportunité d'implantation qui correspond au cahier des charges de ${ens.name}.

• Local : ${local.name}
• Emplacement : ${local.localType || "—"}${local.city ? " — " + local.city : ""}
• Surface : ${local.surface || "—"} m²
• Loyer : ${rs || "—"} €/m²/an${local.frontage ? `\n• Linéaire de façade : ${local.frontage} m` : ""}${local.flux ? `\n• Flux estimé : ${Number(local.flux).toLocaleString("fr-FR")} passages/jour` : ""}${local.droitAuBail ? `\n• Droit au bail : ${eur(local.droitAuBail)}` : ""}

Au regard de vos critères (${(ens.localTypes || []).slice(0, 3).join(", ") || "implantation"}), ce local me semble pertinent. Je reste à votre disposition pour vous transmettre le dossier complet et organiser une visite.

Bien cordialement,
${broker}
${company}${phone ? "\n" + phone : ""}`;
  const subject = `Opportunité d'implantation — ${local.city || local.name} (${local.surface || "?"} m²)`;
  const [copied, setCopied] = useState(false);
  const copy = () => { navigator.clipboard.writeText(body).then(() => { setCopied(true); setTimeout(() => setCopied(false), 1800); }); };
  const mailto = `mailto:${ens.email || ""}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
  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: 90 }}>
      <div onClick={e => e.stopPropagation()} className="rise modal-card" style={{ maxWidth: 620, width: "100%", maxHeight: "90vh", overflowY: "auto", 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: 20, fontWeight: 700 }}>Email d'approche · {ens.name}</div>
          <span onClick={onClose} style={{ cursor: "pointer", fontSize: 24, color: C.dim }}>×</span>
        </div>
        <div style={{ fontSize: 12, color: C.faint, marginBottom: 6 }}>Objet</div>
        <div style={{ fontSize: 13.5, fontWeight: 600, padding: "9px 12px", borderRadius: 10, background: C.panel2, border: `1px solid ${C.line}`, marginBottom: 14 }}>{subject}</div>
        <div style={{ fontSize: 12, color: C.faint, marginBottom: 6 }}>Message</div>
        <textarea readOnly value={body} style={{ width: "100%", height: 300, padding: 14, borderRadius: 12, border: `1px solid ${C.line}`, background: C.panel2, color: C.text, fontSize: 13, lineHeight: 1.55, resize: "vertical", outline: "none" }} />
        <div style={{ marginTop: 16, display: "flex", gap: 9, justifyContent: "flex-end", flexWrap: "wrap" }}>
          <button className="btn btn-g" onClick={copy}>{copied ? "✓ Copié" : "Copier le texte"}</button>
          <a className="btn btn-p" href={mailto} style={{ textDecoration: "none" }}>Ouvrir dans la messagerie →</a>
        </div>
      </div>
    </div>
  );
}
