// =============================================================
// Ventes Vinted / eBay — list + composer
// =============================================================

const SalesScreen = ({ state, actions, openCompose }) => {
  const { sales, categories, stockSeries, sealed } = state;
  const [compose, setCompose] = useState(openCompose || false);
  const [platformFilter, setPlatformFilter] = useState("all");
  const [search, setSearch] = useState("");
  const [openDetail, setOpenDetail] = useState(null);
  const [vintedSync, setVintedSync] = useState(false);
  const [ebaySync, setEbaySync] = useState(false);

  useEffect(() => { if (openCompose) setCompose(true); }, [openCompose]);

  const filtered = useMemo(() => {
    let r = [...sales];
    if (platformFilter !== "all") r = r.filter(s => s.platform === platformFilter);
    if (search) {
      const q = search.toLowerCase();
      r = r.filter(s => s.title.toLowerCase().includes(q));
    }
    return r.sort((a, b) => b.date.localeCompare(a.date));
  }, [sales, platformFilter, search]);

  // precalcul categorie par vente : "Mix" si plusieurs series distinctes
  const saleCatDisplay = useMemo(() => {
    const map = {};
    for (const s of sales) {
      const lines = (state.saleLines || []).filter(l => l.sale_id === s.id && l.category_id != null);
      const ids = new Set(lines.map(l => l.category_id));
      if (ids.size > 1) {
        map[s.id] = { short: "Mix", isMix: true };
      } else if (ids.size === 1) {
        const catId = [...ids][0];
        const cat = categories.find(c => c.id === catId);
        map[s.id] = { short: cat?.short || "—", isMix: false };
      } else {
        // pas de saleLines avec serie : fallback sur s.cat
        const cat = categories.find(c => c.id === s.cat);
        map[s.id] = { short: cat?.short || "—", isMix: false };
      }
    }
    return map;
  }, [sales, state.saleLines, categories]);

  const totalCA = sales.reduce((a, s) => a + s.eur, 0);
  const totalCost = sales.reduce((a, s) => a + (s.cost || 0), 0);

  return (
    <div className="page">
      <div className="page-head">
        <div>
          <h1 className="page-title">Ventes</h1>
          <div className="page-sub">Vinted · eBay · {sales.length} ventes · CA {fmtEUR(totalCA, { decimals: 0 })} €</div>
        </div>
        <div className="page-actions">
          <button className="btn" onClick={() => setEbaySync(true)}><Icon name="external" /> Sync eBay</button>
          <button className="btn" onClick={() => setVintedSync(true)}><Icon name="external" /> Sync Vinted</button>
          <button className="btn btn-primary" onClick={() => setCompose(true)}>
            <Icon name="plus" /> Nouvelle vente
          </button>
        </div>
      </div>

      <div className="kpi-grid">
        <Kpi label="CA brut" value={totalCA} unit="€" meta="toutes plateformes" />
        <Kpi label="Coût marchandises" value={totalCost} unit="€" meta="COGS cumulé" />
        <Kpi label="Marge nette" value={totalCA - totalCost} unit="€" delta={`${(((totalCA - totalCost) / totalCA) * 100).toFixed(1)} %`} deltaPos meta="ratio marge" />
        <Kpi label="Panier moyen" value={totalCA / sales.length} unit="€" meta={`${sales.length} ventes`} />
      </div>

      <div className="toolbar" style={{ marginTop: 16 }}>
        <Tabs value={platformFilter} onChange={setPlatformFilter} options={[
          { value: "all", label: `Toutes (${sales.length})` },
          { value: "vinted", label: `Vinted (${sales.filter(s => s.platform === "vinted").length})` },
          { value: "ebay", label: `eBay (${sales.filter(s => s.platform === "ebay").length})` },
          { value: "adjustment", label: `Ajust. (${sales.filter(s => s.platform === "adjustment").length})` },
        ]} />
        <div className="search">
          <Icon name="search" />
          <input placeholder="Rechercher..." value={search} onChange={e => setSearch(e.target.value)} />
        </div>
        <div className="toolbar-spacer"></div>
        <button className="btn btn-sm" onClick={() => window.location.href = "/api/sales/export.csv"}><Icon name="download" /> Export CSV</button>
      </div>

      <div className="card">
        <table className="tbl">
          <thead>
            <tr>
              <th style={{ width: 40 }}>#</th>
              <th>Date</th>
              <th>Plateforme</th>
              <th>Titre</th>
              <th>Série</th>
              <th className="right">Prix</th>
              <th className="right">Coût</th>
              <th className="right">Marge</th>
              <th className="right">%</th>
              <th style={{ width: 30 }}></th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(s => {
              const catDisplay = saleCatDisplay[s.id] || { short: "—", isMix: false };
              const m = s.eur - (s.cost || 0);
              const pct = s.eur ? (m / s.eur) * 100 : 0;
              return (
                <tr key={s.id} className="clickable" onClick={() => setOpenDetail(s)}>
                  <td className="mono muted">{s.displayNum}</td>
                  <td className="mono muted">{fmtDate(s.date)}</td>
                  <td>
                    <span className={`tag ${s.platform === "ebay" ? "tag-accent" : s.platform === "adjustment" ? "tag-warn" : "tag-ghost"}`}>
                      {s.platform === "adjustment" ? "ajust." : s.platform}
                    </span>
                  </td>
                  <td><div style={{ maxWidth: 320, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{s.title}</div></td>
                  <td><span className={`tag${catDisplay.isMix ? " tag-warn" : ""}`}>{catDisplay.short}</span></td>
                  <td className="right num"><Money eur={s.eur} /></td>
                  <td className="right num muted">{fmtEUR(s.cost || 0)}</td>
                  <td className="right num" style={{ color: m >= 0 ? "var(--pos)" : "var(--neg)", fontWeight: 500 }}>
                    {m >= 0 ? "+" : ""}{fmtEUR(m)} €
                  </td>
                  <td className="right num" style={{ color: m >= 0 ? "var(--pos)" : "var(--neg)" }}>
                    {pct.toFixed(0)}%
                  </td>
                  <td><Icon name="chev" /></td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>

      {compose && <ComposeSaleDrawer state={state} actions={actions} onClose={() => setCompose(false)} />}
      {openDetail && <SaleDetailDrawer sale={openDetail} state={state} actions={actions} onClose={() => setOpenDetail(null)} />}
      {vintedSync && <VintedSyncDrawer state={state} actions={actions} onClose={() => setVintedSync(false)} />}
      {ebaySync && <EbaySyncDrawer state={state} actions={actions} onClose={() => setEbaySync(false)} />}
    </div>
  );
};

// ---------- Sale detail ----------
const SaleDetailDrawer = ({ sale, state, actions, onClose }) => {
  const cat = state.categories.find(c => c.id === sale.cat);
  const m = sale.eur - (sale.cost || 0);
  const [confirming, setConfirming] = useState(false);
  // saleLines pre-chargees au boot dans /api/state, plus de fetch
  const lines = useMemo(
    () => (state.saleLines || []).filter(l => l.sale_id === sale.id),
    [state.saleLines, sale.id]
  );

  const confirmDelete = () => {
    actions.deleteSale(sale.id);
    onClose();
  };
  return (
    <Drawer open onClose={onClose} title={sale.title} sub={`${fmtDate(sale.date)} · ${sale.platform}`}
      footer={
        confirming ? (
          <React.Fragment>
            <span style={{ color: "var(--neg)", fontSize: 13, marginRight: "auto" }}>
              Supprimer définitivement cette vente ?
            </span>
            <button className="btn" onClick={() => setConfirming(false)}>Annuler</button>
            <button className="btn btn-danger" onClick={confirmDelete}>
              <Icon name="trash" /> Oui, supprimer
            </button>
          </React.Fragment>
        ) : (
          <React.Fragment>
            <button className="btn btn-danger" onClick={() => setConfirming(true)}>
              <Icon name="trash" /> Supprimer la vente
            </button>
            <div style={{ flex: 1 }}></div>
            <button className="btn" onClick={onClose}>Fermer</button>
            <button className="btn btn-primary"><Icon name="edit" /> Modifier</button>
          </React.Fragment>
        )
      }
    >
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 14, marginBottom: 22 }}>
        <div className="card card-pad">
          <div className="kpi-label">Prix de vente</div>
          <div className="kpi-value" style={{ marginTop: 6 }}>{fmtEUR(sale.eur)} <span className="unit">€</span></div>
        </div>
        <div className="card card-pad">
          <div className="kpi-label">Coût</div>
          <div className="kpi-value" style={{ marginTop: 6, color: "var(--ink-3)" }}>{fmtEUR(sale.cost || 0)} <span className="unit">€</span></div>
        </div>
        <div className="card card-pad">
          <div className="kpi-label">Marge</div>
          <div className="kpi-value" style={{ marginTop: 6, color: m >= 0 ? "var(--pos)" : "var(--neg)" }}>
            {m >= 0 ? "+" : ""}{fmtEUR(m)} <span className="unit">€</span>
          </div>
          <div style={{ fontSize: 11, color: "var(--ink-3)", marginTop: 4 }}>
            {sale.eur ? ((m / sale.eur) * 100).toFixed(1) : 0}% du prix
          </div>
        </div>
      </div>

      <dl className="kv">
        <dt>Plateforme</dt><dd>{sale.platform}</dd>
        <dt>Catégorie</dt><dd>{cat?.name}</dd>
        <dt>Date de vente</dt><dd>{fmtDate(sale.date)}</dd>
        <dt>Statut</dt><dd><StatusPill status="finalized" /></dd>
      </dl>

      <div className="subhead">
        <h3>Contenu de la vente</h3>
      </div>
      <div style={{ border: "1px solid var(--line)", borderRadius: 8, padding: 14, background: "var(--bg-sunk)" }}>
        <div style={{ fontSize: 13, marginBottom: lines && lines.length > 0 ? 12 : 0 }}>
          <span style={{ color: "var(--ink-3)", fontSize: 11.5 }}>Titre annonce : </span>{sale.title}
        </div>
        {lines.length === 0 ? (
          <div style={{ fontSize: 11.5, color: "var(--ink-3)", fontStyle: "italic" }}>
            Aucun item du stock rattache (vente importee brute ou donnee historique).
          </div>
        ) : (
          <ul style={{ margin: 0, padding: 0, listStyle: "none" }}>
            {lines.map(l => {
              const label = l.kind === "series"
                ? `${l.category_short} — ${l.category_name} · ${(l.sub || "").toUpperCase()}`
                : `${l.sealed_name}${l.sealed_state ? ` · ${l.sealed_state}` : ""}`;
              return (
                <li key={l.id} style={{ display: "flex", justifyContent: "space-between", padding: "6px 0", borderBottom: "1px dashed var(--line)" }}>
                  <span>
                    <b className="mono" style={{ marginRight: 8 }}>{l.quantity}×</b>
                    {label}
                  </span>
                  <span className="mono" style={{ color: "var(--ink-3)", fontSize: 12 }}>
                    {(l.unit_cost_eur || 0).toFixed(2)} €/u · {((l.unit_cost_eur || 0) * l.quantity).toFixed(2)} €
                  </span>
                </li>
              );
            })}
          </ul>
        )}
      </div>
    </Drawer>
  );
};

// ---------- SaleLinesEditor — picker stock + panier reutilisable ----------
// Utilise par ComposeSaleDrawer ET SaleImportWizard
// basket shape : { id, kind, series?, sealed?, sub?, label, qty, unit_cost }
const SaleLinesEditor = ({ state, basket, setBasket }) => {
  const addSeries = (s, kind) => {
    const id = `series-${s.short}-${kind}`;
    if (basket.find(b => b.id === id)) {
      setBasket(b => b.map(x => x.id === id ? { ...x, qty: x.qty + 1 } : x));
    } else {
      setBasket(b => [...b, { id, kind: "series", series: s, sub: kind, label: `${s.short} · ${kind.toUpperCase()}`, qty: 1, unit_cost: s.unit_cost }]);
    }
  };
  const addSealed = (x) => {
    const id = `sealed-${x.id}`;
    if (basket.find(b => b.id === id)) {
      setBasket(b => b.map(y => y.id === id ? { ...y, qty: y.qty + 1 } : y));
    } else {
      setBasket(b => [...b, { id, kind: "sealed", sealed: x, label: `${x.name} (${x.state})`, qty: 1, unit_cost: x.cost }]);
    }
  };
  const setQty = (id, qty) => setBasket(b => b.map(x => x.id === id ? { ...x, qty: Math.max(0, qty) } : x).filter(x => x.qty > 0));
  const remove = (id) => setBasket(b => b.filter(x => x.id !== id));

  return (
    <React.Fragment>
      <div className="subhead"><h3>Panier ({basket.length})</h3></div>
      {basket.length === 0 ? (
        <div style={{ padding: 24, border: "1px dashed var(--line-strong)", borderRadius: 8, color: "var(--ink-3)", textAlign: "center", fontSize: 12.5 }}>
          Pioche dans le stock ci-dessous pour composer la vente.
        </div>
      ) : (
        <div>
          {basket.map(b => (
            <div key={b.id} className="basket-line">
              <div>
                <div className="desc">{b.label}</div>
                <div className="cost">{b.unit_cost.toFixed(2)} € / u · total {fmtEUR(b.qty * b.unit_cost)} €</div>
              </div>
              <div className="qty">
                <button onClick={() => setQty(b.id, b.qty - 1)}><Icon name="minus" /></button>
                <input type="number" value={b.qty} onChange={e => setQty(b.id, Number(e.target.value))} />
                <button onClick={() => setQty(b.id, b.qty + 1)}><Icon name="plus" /></button>
              </div>
              <button className="btn btn-ghost btn-icon" onClick={() => remove(b.id)}><Icon name="trash" /></button>
            </div>
          ))}
        </div>
      )}
      <div style={{ marginTop: 16, border: "1px solid var(--line)", borderRadius: 8, overflow: "hidden", background: "var(--surface)" }}>
        <div style={{ background: "var(--surface-2)", padding: "8px 12px", fontSize: 11, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: "0.05em", fontWeight: 500, borderBottom: "1px solid var(--line)" }}>
          Boosters par serie
        </div>
        <div>
          {state.stockSeries.map(s => (
            <React.Fragment key={s.short}>
              {s.np > 0 && <PickerRow s={s} kind="np" onAdd={() => addSeries(s, "np")} />}
              {s.nh > 0 && <PickerRow s={s} kind="nh" onAdd={() => addSeries(s, "nh")} />}
              {s.h > 0 && <PickerRow s={s} kind="h" onAdd={() => addSeries(s, "h")} />}
            </React.Fragment>
          ))}
        </div>
        <div style={{ background: "var(--surface-2)", padding: "8px 12px", fontSize: 11, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: "0.05em", fontWeight: 500, borderTop: "1px solid var(--line)", borderBottom: "1px solid var(--line)" }}>
          Scelles
        </div>
        <div>
          {state.sealed.map(x => (
            <div key={x.id} className="stock-picker-row">
              <div>
                <div style={{ fontSize: 13 }}>{x.name}</div>
                <div style={{ fontSize: 11, color: "var(--ink-3)" }}>{x.state} · {x.cost.toFixed(2)} €</div>
              </div>
              <span className="lab-tag">UNIT</span>
              <span className="avail">×{x.qty}</span>
              <button className="add" onClick={() => addSealed(x)}>+ Ajouter</button>
            </div>
          ))}
        </div>
      </div>
    </React.Fragment>
  );
};

// ---------- Compose sale (with live margin) ----------
const ComposeSaleDrawer = ({ state, actions, onClose }) => {
  const [form, setForm] = useState({ platform: "vinted", title: "", date: new Date().toISOString().slice(0, 10), price: "" });
  const [basket, setBasket] = useState([]); // { kind: 'series'|'sealed', ref, label, qty, unit_cost }

  const totalCost = basket.reduce((a, x) => a + x.qty * x.unit_cost, 0);
  const price = Number(form.price) || 0;
  const margin = price - totalCost;
  const marginPct = price ? (margin / price) * 100 : 0;

  const canSave = basket.length > 0 && price > 0 && form.title;

  const submit = () => {
    actions.addSale({
      title: form.title,
      platform: form.platform,
      date: form.date,
      eur: price,
      cost: totalCost,
      cat: basket[0].kind === "series" ? basket[0].series.cat : 25,
      lines: basket.map(b => ({ ...b })),
    });
    onClose();
  };

  return (
    <Drawer open onClose={onClose} wide
      title="Nouvelle vente"
      sub="Compose la vente — la marge est calculée en direct"
      footer={
        <React.Fragment>
          <div style={{ marginRight: "auto", fontSize: 12, color: "var(--ink-3)" }}>
            {basket.length} ligne(s) · {basket.reduce((a, b) => a + b.qty, 0)} unités
          </div>
          <button className="btn" onClick={onClose}>Annuler</button>
          <button className="btn btn-primary" disabled={!canSave} onClick={submit}>
            <Icon name="check" /> Enregistrer · décrémente stock
          </button>
        </React.Fragment>
      }
    >
      <div className="composer-grid">
        {/* Left — sale info + basket */}
        <div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10 }}>
            <div className="field">
              <label>Plateforme</label>
              <select className="select" value={form.platform} onChange={e => setForm({ ...form, platform: e.target.value })}>
                <option value="vinted">Vinted</option>
                <option value="ebay">eBay</option>
              </select>
            </div>
            <div className="field">
              <label>Date</label>
              <input className="input mono" type="date" value={form.date} onChange={e => setForm({ ...form, date: e.target.value })} />
            </div>
          </div>
          <div className="field" style={{ marginTop: 10 }}>
            <label>Titre de l'annonce</label>
            <input className="input" placeholder="Lot 10 boosters M1S + 1 Display SV11W" value={form.title} onChange={e => setForm({ ...form, title: e.target.value })} />
          </div>
          <div className="field" style={{ marginTop: 10 }}>
            <label>Prix de vente</label>
            <div className="input-suffix-wrap">
              <input className="input mono" type="number" placeholder="0.00" value={form.price} onChange={e => setForm({ ...form, price: e.target.value })} />
              <span className="input-suffix">€</span>
            </div>
          </div>

          <div className="subhead"><h3>Panier ({basket.length})</h3></div>
          {basket.length === 0 ? (
            <div style={{ padding: 24, border: "1px dashed var(--line-strong)", borderRadius: 8, color: "var(--ink-3)", textAlign: "center", fontSize: 12.5 }}>
              Pioche dans le stock à droite pour composer la vente.
            </div>
          ) : (
            <div>
              {basket.map(b => (
                <div key={b.id} className="basket-line">
                  <div>
                    <div className="desc">{b.label}</div>
                    <div className="cost">{b.unit_cost.toFixed(2)} € / u · total {fmtEUR(b.qty * b.unit_cost)} €</div>
                  </div>
                  <div className="qty">
                    <button onClick={() => setBasket(prev => prev.map(x => x.id === b.id ? { ...x, qty: Math.max(0, x.qty - 1) } : x).filter(x => x.qty > 0))}><Icon name="minus" /></button>
                    <input type="number" value={b.qty} onChange={e => setBasket(prev => prev.map(x => x.id === b.id ? { ...x, qty: Math.max(0, Number(e.target.value)) } : x).filter(x => x.qty > 0))} />
                    <button onClick={() => setBasket(prev => prev.map(x => x.id === b.id ? { ...x, qty: x.qty + 1 } : x))}><Icon name="plus" /></button>
                  </div>
                  <button className="btn btn-ghost btn-icon" onClick={() => setBasket(prev => prev.filter(x => x.id !== b.id))}><Icon name="trash" /></button>
                </div>
              ))}
            </div>
          )}

          {/* Live margin */}
          <div style={{ marginTop: 18, padding: 14, background: "var(--ink)", color: "var(--bg)", borderRadius: 8 }}>
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 10 }}>
              <div>
                <div style={{ fontSize: 10, textTransform: "uppercase", letterSpacing: "0.07em", opacity: 0.6 }}>Prix</div>
                <div className="mono" style={{ fontSize: 18, marginTop: 4 }}>{fmtEUR(price)} €</div>
              </div>
              <div>
                <div style={{ fontSize: 10, textTransform: "uppercase", letterSpacing: "0.07em", opacity: 0.6 }}>Coût</div>
                <div className="mono" style={{ fontSize: 18, marginTop: 4, opacity: 0.7 }}>{fmtEUR(totalCost)} €</div>
              </div>
              <div>
                <div style={{ fontSize: 10, textTransform: "uppercase", letterSpacing: "0.07em", opacity: 0.6 }}>Marge</div>
                <div className="mono" style={{ fontSize: 18, marginTop: 4, color: margin >= 0 ? "oklch(0.80 0.18 150)" : "oklch(0.80 0.18 25)", fontWeight: 600 }}>
                  {margin >= 0 ? "+" : ""}{fmtEUR(margin)} € · {marginPct.toFixed(0)}%
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Right — stock picker */}
        <div>
          <div className="subhead" style={{ marginTop: 0 }}>
            <h3>Pioche dans le stock</h3>
            <span className="mono" style={{ fontSize: 11, color: "var(--ink-3)" }}>clique pour ajouter</span>
          </div>
          <div style={{ border: "1px solid var(--line)", borderRadius: 8, overflow: "hidden", background: "var(--surface)" }}>
            <div style={{ background: "var(--surface-2)", padding: "8px 12px", fontSize: 11, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: "0.05em", fontWeight: 500, borderBottom: "1px solid var(--line)" }}>
              Boosters par série
            </div>
            <div>
              {state.stockSeries.map(s => (
                <React.Fragment key={s.short}>
                  {s.np > 0 && <PickerRow s={s} kind="np" onAdd={() => setBasket(b => { const id = `series-${s.short}-np`; if (b.find(x => x.id === id)) return b.map(x => x.id === id ? { ...x, qty: x.qty + 1 } : x); return [...b, { id, kind: "series", series: s, sub: "np", label: `${s.short} · NP`, qty: 1, unit_cost: s.unit_cost }]; })} />}
                  {s.nh > 0 && <PickerRow s={s} kind="nh" onAdd={() => setBasket(b => { const id = `series-${s.short}-nh`; if (b.find(x => x.id === id)) return b.map(x => x.id === id ? { ...x, qty: x.qty + 1 } : x); return [...b, { id, kind: "series", series: s, sub: "nh", label: `${s.short} · NH`, qty: 1, unit_cost: s.unit_cost }]; })} />}
                  {s.h > 0 && <PickerRow s={s} kind="h" onAdd={() => setBasket(b => { const id = `series-${s.short}-h`; if (b.find(x => x.id === id)) return b.map(x => x.id === id ? { ...x, qty: x.qty + 1 } : x); return [...b, { id, kind: "series", series: s, sub: "h", label: `${s.short} · H`, qty: 1, unit_cost: s.unit_cost }]; })} />}
                </React.Fragment>
              ))}
            </div>
            <div style={{ background: "var(--surface-2)", padding: "8px 12px", fontSize: 11, color: "var(--ink-3)", textTransform: "uppercase", letterSpacing: "0.05em", fontWeight: 500, borderTop: "1px solid var(--line)", borderBottom: "1px solid var(--line)" }}>
              Scellés
            </div>
            <div>
              {state.sealed.map(x => (
                <div key={x.id} className="stock-picker-row">
                  <div>
                    <div style={{ fontSize: 13 }}>{x.name}</div>
                    <div style={{ fontSize: 11, color: "var(--ink-3)" }}>{x.state} · {x.cost.toFixed(2)} €</div>
                  </div>
                  <span className="lab-tag">UNIT</span>
                  <span className="avail">×{x.qty}</span>
                  <button className="add" onClick={() => setBasket(b => { const id = `sealed-${x.id}`; if (b.find(y => y.id === id)) return b.map(y => y.id === id ? { ...y, qty: y.qty + 1 } : y); return [...b, { id, kind: "sealed", sealed: x, label: `${x.name} (${x.state})`, qty: 1, unit_cost: x.cost }]; })}>+ Ajouter</button>
                </div>
              ))}
            </div>
          </div>
        </div>
      </div>
    </Drawer>
  );
};

const PickerRow = ({ s, kind, onAdd }) => (
  <div className="stock-picker-row">
    <div>
      <div style={{ fontSize: 13 }}>{s.name}</div>
      <div style={{ fontSize: 11, color: "var(--ink-3)" }}>{s.short} · {s.unit_cost.toFixed(2)} €/u</div>
    </div>
    <span className="lab-tag" style={kind === "h" ? { background: "var(--pos-tint)", color: "var(--pos)", borderColor: "oklch(0.85 0.04 150)" } : kind === "nh" ? { background: "var(--accent-tint)", color: "var(--accent)" } : null}>
      {kind.toUpperCase()}
    </span>
    <span className="avail">×{s[kind]}</span>
    <button className="add" onClick={onAdd}>+ Ajouter</button>
  </div>
);

// =============================================================
// VintedSyncDrawer — scan IMAP + review + commit
// =============================================================

const VintedSyncDrawer = ({ state, actions, onClose }) => {
  const [step, setStep] = useState("scanning"); // scanning | review
  const [items, setItems] = useState([]);
  const [checked, setChecked] = useState({});
  const [error, setError] = useState(null);
  const [wizard, setWizard] = useState(null); // null | array d'items a traiter

  // Lance le scan au montage du composant
  useEffect(() => {
    setStep("scanning");
    actions.scanVinted().then(result => {
      setItems(result);
      // tout coche par defaut
      const init = {};
      result.forEach(it => { init[it.uid] = true; });
      setChecked(init);
      setStep("review");
    }).catch(err => {
      setError(err?.message || "Erreur scan IMAP");
      setStep("review");
    });
  }, []);

  const toggle = (uid) => setChecked(prev => ({ ...prev, [uid]: !prev[uid] }));
  const toggleAll = () => {
    const allOn = items.every(it => checked[it.uid]);
    const next = {};
    items.forEach(it => { next[it.uid] = !allOn; });
    setChecked(next);
  };

  const selectedItems = items.filter(it => checked[it.uid]);
  const nSelected = selectedItems.length;

  const openWizard = () => {
    if (!nSelected) return;
    setWizard(selectedItems);
  };

  const footer = step === "review" ? (
    React.createElement(React.Fragment, null,
      React.createElement("button", { className: "btn", onClick: onClose }, "Annuler"),
      React.createElement("div", { style: { flex: 1 } }),
      React.createElement("button", {
        className: "btn btn-primary",
        disabled: nSelected === 0 || items.length === 0,
        onClick: openWizard,
      }, React.createElement(Icon, { name: "check" }), ` Importer (${nSelected}) avec mapping stock`),
    )
  ) : (
    React.createElement(React.Fragment, null,
      React.createElement("div", { style: { flex: 1 } }),
      React.createElement("button", { className: "btn btn-primary", disabled: true }, "Scan..."),
    )
  );

  // quand le wizard se ferme (fin normale OU annule), ferme le drawer
  // pas besoin d'alert : actions.addSale a deja affiche les toasts
  const onWizardClose = (_msg) => {
    setWizard(null);
    onClose();
  };

  return (
    <React.Fragment>
    {wizard && (
      <SaleImportWizard
        platform="vinted"
        items={wizard}
        state={state}
        actions={actions}
        onClose={onWizardClose}
      />
    )}
    <Drawer open={!wizard} onClose={onClose}
      title="Sync Vinted"
      sub="Ventes detectees depuis Gmail IMAP — selectionne celles a importer"
      footer={footer}
    >
      {/* Etat : scan en cours */}
      {step === "scanning" && (
        <div style={{ textAlign: "center", padding: "40px 0", color: "var(--ink-2)", fontSize: 13 }}>
          <div>Connexion IMAP Gmail en cours...</div>
          <div style={{ fontSize: 11.5, color: "var(--ink-3)", marginTop: 6, fontFamily: "var(--font-mono)" }}>
            Lecture des mails Vinted
          </div>
        </div>
      )}

      {/* Etat : erreur */}
      {step === "review" && error && (
        <div style={{
          marginBottom: 16, padding: "10px 14px",
          background: "var(--neg-tint, #ffebee)", border: "1px solid var(--neg, #c62828)",
          borderRadius: 8, fontSize: 12.5, color: "var(--neg, #c62828)",
        }}>
          {error}
        </div>
      )}

      {/* Etat : aucune vente detectee */}
      {step === "review" && !error && items.length === 0 && (
        <div style={{
          textAlign: "center", padding: "32px 0",
          color: "var(--ink-3)", fontSize: 13,
        }}>
          <div style={{ fontSize: 15, marginBottom: 8 }}>Aucune nouvelle vente Vinted detectee</div>
          <div style={{ fontSize: 12 }}>Tous les mails recents ont deja ete importes.</div>
          <button className="btn" style={{ marginTop: 20 }} onClick={onClose}>Fermer</button>
        </div>
      )}

      {/* Etat : liste review */}
      {step === "review" && items.length > 0 && (
        <React.Fragment>
          <div style={{
            display: "flex", alignItems: "center", justifyContent: "space-between",
            marginBottom: 12, fontSize: 13, color: "var(--ink-2)",
          }}>
            <span>
              <strong>{items.length}</strong> vente(s) detectee(s) ·{" "}
              <strong>{nSelected}</strong> selectionnee(s)
            </span>
            <button className="btn btn-sm" onClick={toggleAll}>
              {items.every(it => checked[it.uid]) ? "Tout decocher" : "Tout cocher"}
            </button>
          </div>

          <div className="card" style={{ overflow: "auto" }}>
            <table className="tbl">
              <thead>
                <tr>
                  <th style={{ width: 32 }}></th>
                  <th>Date</th>
                  <th>Titre</th>
                  <th>Acheteur</th>
                  <th className="right">Prix (€)</th>
                  <th className="right">Frais (€)</th>
                </tr>
              </thead>
              <tbody>
                {items.map(it => (
                  <tr key={it.uid} className="clickable" onClick={() => toggle(it.uid)}>
                    <td>
                      <input type="checkbox" checked={!!checked[it.uid]} onChange={() => toggle(it.uid)}
                        onClick={e => e.stopPropagation()} />
                    </td>
                    <td className="mono muted">
                      {it.sold_at ? new Date(it.sold_at).toLocaleDateString("fr-FR") : "—"}
                    </td>
                    <td style={{ maxWidth: 260, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                      {it.title || "—"}
                    </td>
                    <td className="muted">{it.buyer || "—"}</td>
                    <td className="right num">{fmtEUR(it.prix_eur)} €</td>
                    <td className="right num muted">{fmtEUR(it.frais_eur)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </React.Fragment>
      )}

    </Drawer>
    </React.Fragment>
  );
};

// =============================================================
// EbaySyncDrawer — scan IMAP eBay + review + commit
// =============================================================

const EbaySyncDrawer = ({ state, actions, onClose }) => {
  const [step, setStep] = useState("scanning"); // scanning | review
  const [items, setItems] = useState([]);
  const [checked, setChecked] = useState({});
  const [error, setError] = useState(null);
  const [wizard, setWizard] = useState(null); // null | array d'items a traiter

  // Lance le scan au montage du composant
  useEffect(() => {
    setStep("scanning");
    actions.scanEbay().then(result => {
      setItems(result);
      // tout coche par defaut
      const init = {};
      result.forEach(it => { init[it.uid] = true; });
      setChecked(init);
      setStep("review");
    }).catch(err => {
      setError(err?.message || "Erreur scan IMAP");
      setStep("review");
    });
  }, []);

  const toggle = (uid) => setChecked(prev => ({ ...prev, [uid]: !prev[uid] }));
  const toggleAll = () => {
    const allOn = items.every(it => checked[it.uid]);
    const next = {};
    items.forEach(it => { next[it.uid] = !allOn; });
    setChecked(next);
  };

  const selectedItems = items.filter(it => checked[it.uid]);
  const nSelected = selectedItems.length;

  const openWizard = () => {
    if (!nSelected) return;
    setWizard(selectedItems);
  };

  const footer = step === "review" ? (
    React.createElement(React.Fragment, null,
      React.createElement("button", { className: "btn", onClick: onClose }, "Annuler"),
      React.createElement("div", { style: { flex: 1 } }),
      React.createElement("button", {
        className: "btn btn-primary",
        disabled: nSelected === 0 || items.length === 0,
        onClick: openWizard,
      }, React.createElement(Icon, { name: "check" }), ` Importer (${nSelected}) avec mapping stock`),
    )
  ) : (
    React.createElement(React.Fragment, null,
      React.createElement("div", { style: { flex: 1 } }),
      React.createElement("button", { className: "btn btn-primary", disabled: true }, "Scan..."),
    )
  );

  // quand le wizard se ferme (fin normale OU annule), ferme le drawer
  const onWizardClose = (_msg) => {
    setWizard(null);
    onClose();
  };

  return (
    <React.Fragment>
    {wizard && (
      <SaleImportWizard
        platform="ebay"
        items={wizard}
        state={state}
        actions={actions}
        onClose={onWizardClose}
      />
    )}
    <Drawer open={!wizard} onClose={onClose}
      title="Synchroniser eBay"
      sub="Ventes detectees depuis Gmail IMAP — selectionne celles a importer"
      footer={footer}
    >
      {/* Etat : scan en cours */}
      {step === "scanning" && (
        <div style={{ textAlign: "center", padding: "40px 0", color: "var(--ink-2)", fontSize: 13 }}>
          <div>Connexion IMAP Gmail en cours...</div>
          <div style={{ fontSize: 11.5, color: "var(--ink-3)", marginTop: 6, fontFamily: "var(--font-mono)" }}>
            Lecture des mails eBay
          </div>
        </div>
      )}

      {/* Etat : erreur */}
      {step === "review" && error && (
        <div style={{
          marginBottom: 16, padding: "10px 14px",
          background: "var(--neg-tint, #ffebee)", border: "1px solid var(--neg, #c62828)",
          borderRadius: 8, fontSize: 12.5, color: "var(--neg, #c62828)",
        }}>
          {error}
        </div>
      )}

      {/* Etat : aucune vente detectee */}
      {step === "review" && !error && items.length === 0 && (
        <div style={{
          textAlign: "center", padding: "32px 0",
          color: "var(--ink-3)", fontSize: 13,
        }}>
          <div style={{ fontSize: 15, marginBottom: 8 }}>Aucune nouvelle vente eBay detectee</div>
          <div style={{ fontSize: 12 }}>Tous les mails recents ont deja ete importes.</div>
          <button className="btn" style={{ marginTop: 20 }} onClick={onClose}>Fermer</button>
        </div>
      )}

      {/* Etat : liste review */}
      {step === "review" && items.length > 0 && (
        <React.Fragment>
          <div style={{
            display: "flex", alignItems: "center", justifyContent: "space-between",
            marginBottom: 12, fontSize: 13, color: "var(--ink-2)",
          }}>
            <span>
              <strong>{items.length}</strong> vente(s) detectee(s) ·{" "}
              <strong>{nSelected}</strong> selectionnee(s)
            </span>
            <button className="btn btn-sm" onClick={toggleAll}>
              {items.every(it => checked[it.uid]) ? "Tout decocher" : "Tout cocher"}
            </button>
          </div>

          <div className="card" style={{ overflow: "auto" }}>
            <table className="tbl">
              <thead>
                <tr>
                  <th style={{ width: 32 }}></th>
                  <th>Date</th>
                  <th>Titre</th>
                  <th>Acheteur</th>
                  <th className="right">Prix (€)</th>
                  <th className="right">Frais (€)</th>
                </tr>
              </thead>
              <tbody>
                {items.map(it => (
                  <tr key={it.uid} className="clickable" onClick={() => toggle(it.uid)}>
                    <td>
                      <input type="checkbox" checked={!!checked[it.uid]} onChange={() => toggle(it.uid)}
                        onClick={e => e.stopPropagation()} />
                    </td>
                    <td className="mono muted">
                      {it.sold_at ? new Date(it.sold_at).toLocaleDateString("fr-FR") : "—"}
                    </td>
                    <td style={{ maxWidth: 260, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                      {it.title || "—"}
                    </td>
                    <td className="muted">{it.buyer || "—"}</td>
                    <td className="right num">{fmtEUR(it.prix_eur)} €</td>
                    <td className="right num muted">{fmtEUR(it.frais_eur)}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </React.Fragment>
      )}

    </Drawer>
    </React.Fragment>
  );
};

// =============================================================
// SaleImportWizard — wizard 1-vente-a-la-fois pour import mail
// =============================================================

const SaleImportWizard = ({ platform, items, state, actions, onClose }) => {
  const [idx, setIdx] = useState(0);
  const [validated, setValidated] = useState(0);
  const [skipped, setSkipped] = useState(0);
  const [submitting, setSubmitting] = useState(false);
  const [basket, setBasket] = useState([]);

  const current = items[idx];

  // champs pre-remplis du mail courant
  const [date, setDate] = useState(current?.sold_at ? current.sold_at.slice(0, 10) : new Date().toISOString().slice(0, 10));
  const [title, setTitle] = useState(current?.title || "");
  const [price, setPrice] = useState(current?.prix_eur || 0);
  const [buyer, setBuyer] = useState(current?.buyer || "");

  // reset form quand on passe a la vente suivante
  useEffect(() => {
    if (current) {
      setDate(current.sold_at ? current.sold_at.slice(0, 10) : new Date().toISOString().slice(0, 10));
      setTitle(current.title || "");
      setPrice(current.prix_eur || 0);
      setBuyer(current.buyer || "");
      setBasket([]);
    }
  }, [idx]);

  if (!current) return null;

  const totalCost = basket.reduce((a, b) => a + (b.unit_cost || 0) * b.qty, 0);

  const markSeen = () => {
    // tolere l'echec : le mail sera re-vu au prochain scan mais pas critique
    try {
      window._apiFetch("POST", `/api/scrape/${platform}/mark-seen`, { items: [current] });
    } catch (e) {
      console.warn("WIZ: mark-seen erreur ignoree", e);
    }
  };

  const goNext = (newValidated, newSkipped) => {
    if (idx + 1 >= items.length) {
      // fin du wizard — refetch state complet
      const finalValidated = newValidated !== undefined ? newValidated : validated;
      const finalSkipped = newSkipped !== undefined ? newSkipped : skipped;
      try {
        window.loadInitialState && window.loadInitialState().then(seed => {
          // on ne peut pas appeler setState du parent directement, on force un reload de la page
          // ou on passe par actions.reloadState si elle existe
          if (actions.reloadState) {
            actions.reloadState(seed);
          }
        });
      } catch (e) {
        console.warn("WIZ: reload state erreur", e);
      }
      onClose(`Import termine : ${finalValidated} validee(s), ${finalSkipped} passee(s)`);
      return;
    }
    setIdx(idx + 1);
  };

  const onValidate = () => {
    if (basket.length === 0) return;  // bouton deja disabled
    // Reutilise actions.addSale (deja teste : optimistic + POST + toast + stock)
    actions.addSale({
      title,
      platform,
      date,
      eur: Number(price),
      cost: totalCost,
      cat: basket[0].kind === "series" ? basket[0].series.cat : (basket[0].sealed?.cat || 25),
      buyer: buyer || null,
      lines: basket,
    });
    markSeen();
    const nextValidated = validated + 1;
    setValidated(nextValidated);
    goNext(nextValidated, skipped);
  };

  const onSkip = () => {
    markSeen();
    const nextSkipped = skipped + 1;
    setSkipped(nextSkipped);
    goNext(validated, nextSkipped);
  };

  return (
    <Drawer open onClose={submitting ? () => {} : () => onClose(null)}
      title={`Importer vente ${idx + 1} sur ${items.length}`}
      sub={`${platform} · ${validated} validee(s) · ${skipped} passee(s)`}
      footer={
        <React.Fragment>
          <button className="btn" onClick={onSkip} disabled={submitting}>
            <Icon name="x" /> Passer
          </button>
          <div style={{ flex: 1 }}></div>
          <button className="btn" onClick={() => onClose(null)} disabled={submitting}>Annuler</button>
          <button className="btn btn-primary" onClick={onValidate} disabled={submitting || basket.length === 0}>
            <Icon name="check" /> Valider la vente
          </button>
        </React.Fragment>
      }
    >
      {/* champs pre-remplis du mail */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 14 }}>
        <div className="field">
          <label>Date</label>
          <input type="date" className="input" value={date} onChange={e => setDate(e.target.value)} />
        </div>
        <div className="field">
          <label>Plateforme</label>
          <input className="input" value={platform} disabled />
        </div>
      </div>
      <div className="field" style={{ marginBottom: 10 }}>
        <label>Titre de l'annonce</label>
        <input className="input" value={title} onChange={e => setTitle(e.target.value)} />
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12, marginBottom: 18 }}>
        <div className="field">
          <label>Prix vente (€)</label>
          <input type="number" className="input mono" value={price} onChange={e => setPrice(e.target.value)} />
        </div>
        <div className="field">
          <label>Acheteur</label>
          <input className="input" value={buyer} onChange={e => setBuyer(e.target.value)} />
        </div>
      </div>

      {/* picker stock reutilise */}
      <SaleLinesEditor state={state} basket={basket} setBasket={setBasket} />

      <div style={{ marginTop: 14, padding: 10, background: "var(--bg-sunk)", borderRadius: 6, fontSize: 13 }}>
        Cout total : <b className="mono">{totalCost.toFixed(2)} €</b> · Marge estimee : <b className="mono">{(Number(price) - totalCost).toFixed(2)} €</b>
      </div>
    </Drawer>
  );
};

window.SalesScreen = SalesScreen;
