// gp-builder.jsx — Builder visuel de sous-modules d'estimation (admin)
// ───────────────────────────────────────────────────────────────
// Modèle unifié (repart à neuf, indépendant des anciennes RECIPES) :
//
//   Widget (sous-module d'estimation)
//     ├─ driver : area | linear | count | mixte   (ce qu'on mesure)
//     ├─ products[] : catalogue local { code, libelle, unite, prix }
//     ├─ params[]   : schéma de config { key, label, type, options[], default }
//     ├─ rules[]    : param actif → produit → ratio
//     │     { id, productCode, driver, per, base, unit, when:[{param,value}] }
//     └─ recipes[]  : presets de paramètres { id, name, values:{} }
//
// Le relevé = règles dont TOUTES les conditions `when` sont satisfaites par
// les valeurs actives (recette + surcharges), × drivers mesurés.
const { Icon: BIcon, SysHeader } = window;

// ── Modèle ───────────────────────────────────────────────────────
const BUILDER_WIDGETS = []; // on repart à neuf : aucune donnée en dur

const uid = (p) => p + Math.random().toString(36).slice(2, 8);
const slugKey = (s) => (s || '').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '')
  .replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, '') || 'param';

function newWidget() {
  return {
    id: uid('w_'), name: 'Nouveau widget', cat: '', icon: 'box',
    driver: 'area', products: [], params: [], rules: [], recipes: [],
  };
}

// Convertit les modules d'estimation + RECIPES existants vers le nouveau modèle.
// Stratégie : 1 widget par module ; un paramètre « Système / recette » (select)
// dont chaque option active les lignes-produits de la recette/variante
// correspondante. Chaque recette devient aussi un preset. Entièrement éditable.
const DRIVER_FROM_PRIMARY = { area: 'area', perim: 'linear', units: 'count' };
function seedWidgetsFromLegacy() {
  const MODS = window.ESTIMATION_MODULES || [];
  const recipesFor = window.recipesForModule || (() => []);
  const getSpec = window.getSpec || (() => ({}));
  return MODS.map((m) => {
    const recs = recipesFor(m.id) || [];
    const products = {};
    const rules = [];
    const options = [];
    const presets = [];
    recs.forEach((r) => {
      const variants = (r.variants && r.variants.length) ? r.variants : [{ id: r.id, name: null, lines: r.lines }];
      variants.forEach((v) => {
        const key = (r.variants && r.variants.length) ? `${r.id}__${v.id}` : r.id;
        const label = v.name ? `${r.name} — ${v.name}` : r.name;
        options.push({ value: key, label });
        presets.push({ id: uid('rc_'), name: label, values: { systeme: key } });
        (v.lines || []).forEach((l) => {
          const code = l.sku || l.item;
          if (code && !products[code]) products[code] = { code, libelle: l.item, unite: l.unit || 'unité', prix: 0 };
          rules.push({ id: uid('r_'), productCode: code, driver: l.driver, per: l.per, base: l.base, unit: l.unit || '', when: [{ param: 'systeme', value: key }] });
        });
      });
    });
    const params = options.length
      ? [{ key: 'systeme', label: 'Système / recette', type: 'select', options, default: options[0].value }]
      : [];
    const spec = getSpec(m.id) || {};
    return {
      id: m.id, name: m.name, cat: m.cat, icon: m.icon,
      driver: DRIVER_FROM_PRIMARY[spec.primaryDriver] || 'area',
      products: Object.values(products), params, rules, recipes: presets,
      _legacy: true,
    };
  });
}

const DRIVER_OPTS = [
  { value: 'area', label: 'Surface (pi²)' },
  { value: 'linear', label: 'Ligne (pi lin.)' },
  { value: 'count', label: 'Unité (count)' },
  { value: 'mixte', label: 'Mixte' },
];
const RULE_DRIVERS = [
  { value: 'area', label: '/ pi²' },
  { value: 'perim', label: '/ pi lin.' },
  { value: 'units', label: '/ unité' },
  { value: 'prev', label: '/ ligne préc.' },
];
const PARAM_TYPES = [
  { value: 'toggle', label: 'Oui / Non' },
  { value: 'select', label: 'Liste de choix' },
  { value: 'number', label: 'Nombre' },
];

// Valeurs possibles d'un paramètre (pour les conditions et les recettes)
function paramValues(p) {
  if (p.type === 'toggle') return [{ value: 'true', label: 'Oui' }, { value: 'false', label: 'Non' }];
  if (p.type === 'select') return (p.options || []).map((o) => ({ value: o.value, label: o.label || o.value }));
  return null; // number → champ libre
}

// Calcul du BOM (aperçu) : règles actives selon les valeurs courantes × drivers
function builderBom(widget, values, drivers) {
  let prev = 0;
  const active = (widget.rules || []).filter((r) =>
    (r.when || []).every((c) => String(values[c.param] ?? '') === String(c.value)));
  return active.map((r) => {
    const src = r.driver === 'area' ? (drivers.area || 0)
      : r.driver === 'perim' ? (drivers.perim || 0)
      : r.driver === 'units' ? (drivers.units || 0)
      : prev;
    const qty = Math.ceil(src / (Number(r.base) || 1) * (Number(r.per) || 1));
    prev = qty;
    const prod = (widget.products || []).find((p) => p.code === r.productCode);
    return {
      code: r.productCode || '—',
      libelle: prod ? prod.libelle : (r.productCode || 'Produit inconnu'),
      qty, unit: r.unit || (prod && prod.unite) || '',
      prix: prod ? Number(prod.prix) || 0 : 0,
    };
  });
}

// ── Composant principal ──────────────────────────────────────────
function WidgetBuilder({ widgets = [], onChange, onLog, org }) {
  const list = widgets;
  const [selId, setSelId] = React.useState(list[0] ? list[0].id : null);
  const [tab, setTab] = React.useState('identite');

  const sel = list.find((w) => w.id === selId) || null;
  const cats = (org && org.cats && org.cats.length) ? org.cats : [];

  const commit = (next) => onChange(next);
  const patchWidget = (id, patch) =>
    commit(list.map((w) => (w.id === id ? { ...w, ...patch } : w)));

  const addWidget = () => {
    const w = newWidget();
    commit([...list, w]); setSelId(w.id); setTab('identite');
    onLog && onLog('edit', 'a créé un widget (builder)', w.name);
  };
  const delWidget = (id) => {
    const w = list.find((x) => x.id === id);
    commit(list.filter((x) => x.id !== id));
    if (selId === id) setSelId(list.find((x) => x.id !== id) ? list.find((x) => x.id !== id).id : null);
    onLog && onLog('edit', 'a supprimé un widget (builder)', w ? w.name : id);
  };
  const dupWidget = (id) => {
    const w = list.find((x) => x.id === id); if (!w) return;
    const copy = { ...JSON.parse(JSON.stringify(w)), id: uid('w_'), name: w.name + ' (copie)' };
    commit([...list, copy]); setSelId(copy.id);
  };

  // ── import des widgets existants (modules + RECIPES) ──
  const importLegacy = () => {
    const seeded = seedWidgetsFromLegacy();
    const have = new Set(list.map((w) => w.id));
    const merged = [...list, ...seeded.filter((w) => !have.has(w.id))];
    commit(merged);
    const added = merged.length - list.length;
    if (!selId && merged.length) setSelId(merged[0].id);
    onLog && onLog('edit', 'a importé les widgets existants', `${added} ajouté${added > 1 ? 's' : ''}`);
  };

  // ── export JSON ──
  const exportJson = () => {
    const blob = new Blob([JSON.stringify(list, null, 2)], { type: 'application/json' });
    const a = document.createElement('a'); a.href = URL.createObjectURL(blob);
    a.download = 'widgets.json'; a.click();
    onLog && onLog('edit', 'a exporté les widgets (builder)');
  };

  const TABS = [
    { id: 'identite', label: 'Identité' },
    { id: 'produits', label: 'Produits' },
    { id: 'parametres', label: 'Paramètres' },
    { id: 'regles', label: 'Règles & ratios' },
    { id: 'recettes', label: 'Recettes' },
    { id: 'apercu', label: 'Aperçu' },
  ];

  return (
    <div className="fade-in">
      <SysHeader icon="cube" title="Builder de widgets"
        sub="Créez des sous-modules d'estimation : produits, paramètres, règles de quantité et recettes (presets).">
        <button className="btn" onClick={importLegacy}><BIcon n="sync" /> Importer widgets existants</button>
        <button className="btn" onClick={exportJson} disabled={!list.length}><BIcon n="download" /> Exporter JSON</button>
        <button className="btn accent" onClick={addWidget}><BIcon n="plus" /> Nouveau widget</button>
      </SysHeader>

      <div className="bld-layout">
        {/* Liste des widgets construits */}
        <aside className="bld-list">
          {list.length === 0 &&
            <div className="note">Aucun widget. Cliquez « Nouveau widget » pour démarrer.</div>}
          {list.map((w) => (
            <button key={w.id} className={'bld-list-item' + (w.id === selId ? ' on' : '')}
              onClick={() => setSelId(w.id)}>
              <span className="bld-list-ic"><BIcon n={w.icon || 'box'} style={{ width: 15, height: 15 }} /></span>
              <span className="bld-list-tx">
                <span className="bld-list-name">{w.name}</span>
                <span className="bld-list-meta">{w.cat || 'sans catégorie'} · {w.rules.length} règle{w.rules.length > 1 ? 's' : ''}</span>
              </span>
            </button>
          ))}
        </aside>

        {/* Éditeur */}
        <div className="bld-edit">
          {!sel && <div className="empty tickbox" style={{ margin: '40px auto', maxWidth: 420 }}>
            <div className="empty-t">Aucun widget sélectionné</div>
            <div className="empty-s">Créez-en un ou sélectionnez-le dans la liste.</div>
          </div>}

          {sel && <>
            <div className="bld-edit-head">
              <input className="cell-in bld-title" value={sel.name}
                onChange={(e) => patchWidget(sel.id, { name: e.target.value })} />
              <div className="row-flex">
                <button className="row-x" title="Dupliquer" onClick={() => dupWidget(sel.id)}><BIcon n="copy" /></button>
                <button className="row-x" title="Supprimer" onClick={() => delWidget(sel.id)}><BIcon n="trash" /></button>
              </div>
            </div>

            <div className="steps" style={{ marginBottom: 16 }}>
              {TABS.map((t) => (
                <button key={t.id} className={'step' + (tab === t.id ? ' on' : '')} onClick={() => setTab(t.id)}>{t.label}</button>
              ))}
            </div>

            {tab === 'identite'   && <BldIdentite w={sel} cats={cats} onPatch={(p) => patchWidget(sel.id, p)} />}
            {tab === 'produits'   && <BldProduits w={sel} onPatch={(p) => patchWidget(sel.id, p)} />}
            {tab === 'parametres' && <BldParametres w={sel} onPatch={(p) => patchWidget(sel.id, p)} />}
            {tab === 'regles'     && <BldRegles w={sel} onPatch={(p) => patchWidget(sel.id, p)} />}
            {tab === 'recettes'   && <BldRecettes w={sel} onPatch={(p) => patchWidget(sel.id, p)} />}
            {tab === 'apercu'     && <BldApercu w={sel} />}
          </>}
        </div>
      </div>
    </div>
  );
}

// ── Onglet : Identité ────────────────────────────────────────────
function BldIdentite({ w, cats, onPatch }) {
  return (
    <div className="card">
      <div className="fgrid">
        <div className="fcell">
          <label className="lbl">Nom du widget</label>
          <input className="field" value={w.name} onChange={(e) => onPatch({ name: e.target.value })} />
        </div>
        <div className="fcell">
          <label className="lbl">Catégorie d'estimation</label>
          <select className="field" value={w.cat} onChange={(e) => onPatch({ cat: e.target.value })}>
            <option value="">— Choisir —</option>
            {cats.map((c) => <option key={c} value={c}>{c}</option>)}
          </select>
        </div>
        <div className="fcell">
          <label className="lbl">Type de mesure</label>
          <select className="field" value={w.driver} onChange={(e) => onPatch({ driver: e.target.value })}>
            {DRIVER_OPTS.map((d) => <option key={d.value} value={d.value}>{d.label}</option>)}
          </select>
        </div>
        <div className="fcell">
          <label className="lbl">Icône</label>
          <select className="field" value={w.icon} onChange={(e) => onPatch({ icon: e.target.value })}>
            {['box', 'tape', 'wall', 'roof', 'insulation', 'fan', 'duct', 'grille', 'window', 'floor', 'frame', 'layers', 'thermo'].map((i) =>
              <option key={i} value={i}>{i}</option>)}
          </select>
        </div>
      </div>
      <div className="note" style={{ marginTop: 12 }}>
        Le <b>type de mesure</b> détermine ce que l'estimateur trace sur le plan (surface, ligne, ou éléments comptés) et alimente le calcul des quantités.
      </div>
    </div>
  );
}

// ── Onglet : Produits (catalogue local du widget) ────────────────
function BldProduits({ w, onPatch }) {
  const prods = w.products || [];
  const setP = (i, patch) => onPatch({ products: prods.map((p, idx) => idx === i ? { ...p, ...patch } : p) });
  const add = () => onPatch({ products: [...prods, { code: '', libelle: 'Nouveau produit', unite: 'unité', prix: 0 }] });
  const del = (i) => onPatch({ products: prods.filter((_, idx) => idx !== i) });
  return (
    <div className="card">
      <div className="card-h">
        <div className="card-h-l"><span className="badge-n">1</span><span className="card-t">Catalogue de produits</span></div>
        <span className="card-hint">les produits référencés par les règles</span>
      </div>
      <div className="tbl-wrap">
        <table>
          <thead><tr><th style={{ width: 140 }}>Code</th><th>Libellé</th><th style={{ width: 110 }}>Unité</th><th style={{ width: 96 }}>Prix ($)</th><th style={{ width: 40 }}></th></tr></thead>
          <tbody>
            {prods.map((p, i) => (
              <tr key={i}>
                <td><input className="cell-in mono" value={p.code} onChange={(e) => setP(i, { code: e.target.value })} placeholder="SKU" /></td>
                <td><input className="cell-in" value={p.libelle} onChange={(e) => setP(i, { libelle: e.target.value })} /></td>
                <td><input className="cell-in" value={p.unite} onChange={(e) => setP(i, { unite: e.target.value })} /></td>
                <td><input className="cell-in mono" type="number" value={p.prix} onChange={(e) => setP(i, { prix: e.target.value })} /></td>
                <td><button className="row-x" onClick={() => del(i)}><BIcon n="trash" /></button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      {prods.length === 0 && <div className="note" style={{ marginTop: 10 }}>Aucun produit. Ajoutez-en, ou importez votre catalogue (à venir).</div>}
      <button className="addrow" onClick={add}><BIcon n="plus" /> Ajouter un produit</button>
    </div>
  );
}

// ── Onglet : Paramètres (schéma de config) ───────────────────────
function BldParametres({ w, onPatch }) {
  const params = w.params || [];
  const setP = (i, patch) => onPatch({ params: params.map((p, idx) => idx === i ? { ...p, ...patch } : p) });
  const add = () => onPatch({ params: [...params, { key: uid('p_'), label: 'Nouveau paramètre', type: 'toggle', options: [], default: 'false' }] });
  const del = (i) => onPatch({ params: params.filter((_, idx) => idx !== i) });
  const setOpt = (pi, oi, patch) => setP(pi, { options: params[pi].options.map((o, idx) => idx === oi ? { ...o, ...patch } : o) });
  const addOpt = (pi) => setP(pi, { options: [...(params[pi].options || []), { value: uid('o_'), label: 'Option' }] });
  const delOpt = (pi, oi) => setP(pi, { options: params[pi].options.filter((_, idx) => idx !== oi) });

  return (
    <div className="card">
      <div className="card-h">
        <div className="card-h-l"><span className="badge-n">2</span><span className="card-t">Paramètres configurables</span></div>
        <span className="card-hint">les options que l'estimateur voit et règle</span>
      </div>
      {params.length === 0 && <div className="note" style={{ marginBottom: 12 }}>Aucun paramètre. Ex. « Membrane intérieure » (Oui/Non), « Type de ruban » (liste).</div>}
      <div className="bld-params">
        {params.map((p, i) => {
          const vals = paramValues(p);
          return (
            <div className="bld-param" key={p.key}>
              <div className="bld-param-row">
                <input className="cell-in" value={p.label} onChange={(e) => setP(i, { label: e.target.value })} placeholder="Libellé" style={{ flex: 1 }} />
                <select className="cell-in" value={p.type} onChange={(e) => setP(i, { type: e.target.value })} style={{ width: 140 }}>
                  {PARAM_TYPES.map((t) => <option key={t.value} value={t.value}>{t.label}</option>)}
                </select>
                <select className="cell-in" value={p.default ?? ''} onChange={(e) => setP(i, { default: e.target.value })} style={{ width: 130 }} title="Valeur par défaut">
                  {p.type === 'number'
                    ? <option value="">(nombre)</option>
                    : (vals || []).map((v) => <option key={v.value} value={v.value}>{v.label}</option>)}
                </select>
                <button className="row-x" onClick={() => del(i)}><BIcon n="trash" /></button>
              </div>
              {p.type === 'number' &&
                <div className="bld-param-num">
                  <label className="lbl">Défaut</label>
                  <input className="cell-in mono" type="number" value={p.default || ''} onChange={(e) => setP(i, { default: e.target.value })} style={{ width: 100 }} />
                </div>}
              {p.type === 'select' &&
                <div className="bld-opts">
                  {(p.options || []).map((o, oi) => (
                    <div className="bld-opt" key={o.value}>
                      <BIcon n="chevd" style={{ width: 12, height: 12, opacity: .4 }} />
                      <input className="cell-in" value={o.label} onChange={(e) => setOpt(i, oi, { label: e.target.value })} placeholder="Libellé option" />
                      <button className="row-x" onClick={() => delOpt(i, oi)}><BIcon n="trash" /></button>
                    </div>
                  ))}
                  <button className="addrow sm" onClick={() => addOpt(i)}><BIcon n="plus" /> Ajouter une option</button>
                </div>}
            </div>
          );
        })}
      </div>
      <button className="addrow" onClick={add}><BIcon n="plus" /> Ajouter un paramètre</button>
    </div>
  );
}

// ── Onglet : Règles & ratios (param → produit → quantité) ────────
function BldRegles({ w, onPatch }) {
  const rules = w.rules || [];
  const params = w.params || [];
  const prods = w.products || [];
  const setR = (i, patch) => onPatch({ rules: rules.map((r, idx) => idx === i ? { ...r, ...patch } : r) });
  const add = () => onPatch({ rules: [...rules, { id: uid('r_'), productCode: prods[0] ? prods[0].code : '', driver: 'area', per: 1, base: 100, unit: '', when: [] }] });
  const del = (i) => onPatch({ rules: rules.filter((_, idx) => idx !== i) });
  const addCond = (i) => setR(i, { when: [...(rules[i].when || []), { param: params[0] ? params[0].key : '', value: '' }] });
  const setCond = (i, ci, patch) => setR(i, { when: rules[i].when.map((c, idx) => idx === ci ? { ...c, ...patch } : c) });
  const delCond = (i, ci) => setR(i, { when: rules[i].when.filter((_, idx) => idx !== ci) });

  return (
    <div className="card">
      <div className="card-h">
        <div className="card-h-l"><span className="badge-n">3</span><span className="card-t">Règles de quantité</span></div>
        <span className="card-hint">produit déclenché par des paramètres + ratio</span>
      </div>
      {prods.length === 0 && <div className="note" style={{ marginBottom: 12 }}>Ajoutez d'abord des produits (onglet Produits).</div>}
      {rules.length === 0 && <div className="note" style={{ marginBottom: 12 }}>Aucune règle. Ex. « 1 rouleau Intello / 1 614 pi² ».</div>}

      <div className="bld-rules">
        {rules.map((r, i) => {
          const prod = prods.find((p) => p.code === r.productCode);
          return (
            <div className="bld-rule" key={r.id}>
              <div className="bld-rule-main">
                <select className="cell-in" value={r.productCode} onChange={(e) => setR(i, { productCode: e.target.value })} style={{ flex: 1, minWidth: 150 }}>
                  <option value="">— Produit —</option>
                  {prods.map((p) => <option key={p.code} value={p.code}>{p.libelle} ({p.code})</option>)}
                </select>
                <span className="bld-rule-eq">=</span>
                <input className="cell-in mono" type="number" value={r.per} onChange={(e) => setR(i, { per: e.target.value })} style={{ width: 64 }} title="Quantité produite" />
                <span className="bld-rule-sep">par</span>
                <input className="cell-in mono" type="number" value={r.base} onChange={(e) => setR(i, { base: e.target.value })} style={{ width: 72 }} title="Base" />
                <select className="cell-in" value={r.driver} onChange={(e) => setR(i, { driver: e.target.value })} style={{ width: 120 }}>
                  {RULE_DRIVERS.map((d) => <option key={d.value} value={d.value}>{d.label}</option>)}
                </select>
                <input className="cell-in" value={r.unit} onChange={(e) => setR(i, { unit: e.target.value })} placeholder={prod ? prod.unite : 'unité'} style={{ width: 90 }} title="Unité affichée" />
                <button className="row-x" onClick={() => del(i)}><BIcon n="trash" /></button>
              </div>
              <div className="bld-rule-when">
                <span className="bld-when-lbl">Actif si :</span>
                {(r.when || []).length === 0 && <span className="bld-when-always">toujours</span>}
                {(r.when || []).map((c, ci) => {
                  const param = params.find((p) => p.key === c.param);
                  const vals = param ? paramValues(param) : null;
                  return (
                    <span className="bld-cond" key={ci}>
                      <select className="cell-in" value={c.param} onChange={(e) => setCond(i, ci, { param: e.target.value, value: '' })} style={{ width: 150 }}>
                        <option value="">— Paramètre —</option>
                        {params.map((p) => <option key={p.key} value={p.key}>{p.label}</option>)}
                      </select>
                      <span className="bld-cond-eq">=</span>
                      {vals
                        ? <select className="cell-in" value={c.value} onChange={(e) => setCond(i, ci, { value: e.target.value })} style={{ width: 110 }}>
                            <option value="">—</option>
                            {vals.map((v) => <option key={v.value} value={v.value}>{v.label}</option>)}
                          </select>
                        : <input className="cell-in mono" value={c.value} onChange={(e) => setCond(i, ci, { value: e.target.value })} style={{ width: 90 }} placeholder="valeur" />}
                      <button className="row-x sm" onClick={() => delCond(i, ci)}><BIcon n="trash" /></button>
                    </span>
                  );
                })}
                <button className="addrow sm" onClick={() => addCond(i)} disabled={params.length === 0}><BIcon n="plus" /> Condition</button>
              </div>
            </div>
          );
        })}
      </div>
      <button className="addrow" onClick={add} disabled={prods.length === 0}><BIcon n="plus" /> Ajouter une règle</button>
    </div>
  );
}

// ── Onglet : Recettes (presets de paramètres) ────────────────────
function BldRecettes({ w, onPatch }) {
  const recipes = w.recipes || [];
  const params = w.params || [];
  const setRec = (i, patch) => onPatch({ recipes: recipes.map((r, idx) => idx === i ? { ...r, ...patch } : r) });
  const add = () => {
    const values = {};
    params.forEach((p) => { values[p.key] = p.default ?? (p.type === 'toggle' ? 'false' : ''); });
    onPatch({ recipes: [...recipes, { id: uid('rc_'), name: 'Nouvelle recette', values }] });
  };
  const del = (i) => onPatch({ recipes: recipes.filter((_, idx) => idx !== i) });
  const setVal = (i, key, value) => setRec(i, { values: { ...recipes[i].values, [key]: value } });

  return (
    <div className="card">
      <div className="card-h">
        <div className="card-h-l"><span className="badge-n">4</span><span className="card-t">Recettes (presets)</span></div>
        <span className="card-hint">combinaisons de paramètres pré-remplies</span>
      </div>
      {params.length === 0 && <div className="note" style={{ marginBottom: 12 }}>Définissez d'abord des paramètres pour composer des recettes.</div>}
      {recipes.length === 0 && <div className="note" style={{ marginBottom: 12 }}>Aucune recette. Ex. « Pro Clima », « Rothoblaas », « Mixte ».</div>}

      <div className="bld-recipes">
        {recipes.map((rc, i) => (
          <div className="bld-recipe" key={rc.id}>
            <div className="bld-recipe-head">
              <input className="cell-in" value={rc.name} onChange={(e) => setRec(i, { name: e.target.value })} style={{ fontWeight: 600, flex: 1 }} />
              <button className="row-x" onClick={() => del(i)}><BIcon n="trash" /></button>
            </div>
            <div className="bld-recipe-vals">
              {params.map((p) => {
                const vals = paramValues(p);
                return (
                  <div className="bld-recipe-val" key={p.key}>
                    <label className="lbl">{p.label}</label>
                    {vals
                      ? <select className="cell-in" value={rc.values[p.key] ?? ''} onChange={(e) => setVal(i, p.key, e.target.value)}>
                          {vals.map((v) => <option key={v.value} value={v.value}>{v.label}</option>)}
                        </select>
                      : <input className="cell-in mono" type="number" value={rc.values[p.key] ?? ''} onChange={(e) => setVal(i, p.key, e.target.value)} />}
                  </div>
                );
              })}
            </div>
          </div>
        ))}
      </div>
      <button className="addrow" onClick={add} disabled={params.length === 0}><BIcon n="plus" /> Ajouter une recette</button>
    </div>
  );
}

// ── Onglet : Aperçu (simulation du calcul) ───────────────────────
function BldApercu({ w }) {
  const params = w.params || [];
  const recipes = w.recipes || [];
  const [recId, setRecId] = React.useState(recipes[0] ? recipes[0].id : '');
  const [drivers, setDrivers] = React.useState({ area: 1000, perim: 100, units: 10 });
  const [overrides, setOverrides] = React.useState({});

  // valeurs actives = recette choisie + surcharges manuelles
  const rec = recipes.find((r) => r.id === recId);
  const baseVals = {};
  params.forEach((p) => { baseVals[p.key] = (rec && rec.values[p.key] != null) ? rec.values[p.key] : (p.default ?? ''); });
  const values = { ...baseVals, ...overrides };

  const bom = builderBom(w, values, drivers);
  const total = bom.reduce((s, b) => s + b.qty * b.prix, 0);

  const setOv = (key, val) => setOverrides((o) => ({ ...o, [key]: val }));

  return (
    <div className="grid-2">
      <div className="col">
        <div className="card">
          <div className="card-h"><div className="card-h-l"><span className="badge-n">A</span><span className="card-t">Mesures simulées</span></div></div>
          <div className="fgrid">
            <div className="fcell"><label className="lbl">Surface (pi²)</label><input className="field mono" type="number" value={drivers.area} onChange={(e) => setDrivers((d) => ({ ...d, area: Number(e.target.value) }))} /></div>
            <div className="fcell"><label className="lbl">Ligne (pi lin.)</label><input className="field mono" type="number" value={drivers.perim} onChange={(e) => setDrivers((d) => ({ ...d, perim: Number(e.target.value) }))} /></div>
            <div className="fcell"><label className="lbl">Unités</label><input className="field mono" type="number" value={drivers.units} onChange={(e) => setDrivers((d) => ({ ...d, units: Number(e.target.value) }))} /></div>
          </div>
        </div>

        <div className="card">
          <div className="card-h"><div className="card-h-l"><span className="badge-n">B</span><span className="card-t">Paramètres actifs</span></div></div>
          <div className="fcell" style={{ marginBottom: 12 }}>
            <label className="lbl">Recette</label>
            <select className="field" value={recId} onChange={(e) => { setRecId(e.target.value); setOverrides({}); }}>
              <option value="">— Aucune (défauts) —</option>
              {recipes.map((r) => <option key={r.id} value={r.id}>{r.name}</option>)}
            </select>
          </div>
          {params.length === 0 && <div className="note">Aucun paramètre défini.</div>}
          <div className="fgrid">
            {params.map((p) => {
              const vals = paramValues(p);
              return (
                <div className="fcell" key={p.key}>
                  <label className="lbl">{p.label}</label>
                  {vals
                    ? <select className="field" value={values[p.key] ?? ''} onChange={(e) => setOv(p.key, e.target.value)}>
                        {vals.map((v) => <option key={v.value} value={v.value}>{v.label}</option>)}
                      </select>
                    : <input className="field mono" type="number" value={values[p.key] ?? ''} onChange={(e) => setOv(p.key, e.target.value)} />}
                </div>
              );
            })}
          </div>
        </div>
      </div>

      <aside className="aside">
        <div className="card">
          <div className="sum-title">Quantités calculées</div>
          {bom.length === 0 && <div className="note">Aucune règle active pour ces paramètres.</div>}
          {bom.length > 0 &&
            <div className="tbl-wrap">
              <table>
                <thead><tr><th>Produit</th><th className="num">Qté</th><th className="num">Total</th></tr></thead>
                <tbody>
                  {bom.map((b, i) => (
                    <tr key={i}>
                      <td><div className="org-wname"><span className="mono" style={{ fontSize: 11, opacity: .6 }}>{b.code}</span> {b.libelle}</div></td>
                      <td className="num mono">{b.qty} {b.unit}</td>
                      <td className="num mono">{b.prix ? (b.qty * b.prix).toLocaleString('fr-CA', { style: 'currency', currency: 'CAD' }) : '—'}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>}
          {total > 0 &&
            <div className="bld-total"><span>Total matériaux</span><b>{total.toLocaleString('fr-CA', { style: 'currency', currency: 'CAD' })}</b></div>}
          <div className="note" style={{ marginTop: 12 }}>Aperçu du calcul appliqué dans le module utilisateur et la soumission.</div>
        </div>
      </aside>
    </div>
  );
}

Object.assign(window, { WidgetBuilder, BUILDER_WIDGETS, builderBom, newBuilderWidget: newWidget, seedWidgetsFromLegacy });
