/* global React, Icon, Button, Badge, Card, brl,
          PageHead, Toolbar, FooterPager, KpiMini,
          ProdutoForm, LinhaForm, CategoriaForm, TabelaPrecoForm, MovEstoqueForm */

const { useState: useProdState } = React;

// ============================================================
// SEED DATA — cleared, DB is source of truth
// ============================================================
const PRODUTOS_SEED  = [];
const LINHAS_SEED    = [];
const CATS_SEED      = [];
const TABELAS_SEED   = [];
const ESTOQUE_SEED   = [];

// ============================================================
// Shared list-state hook
// ============================================================
function useProdListState(seed) {
  const [rows, setRows] = useProdState(seed);
  const [edit, setEdit] = useProdState(null);

  const open  = (mode, idx, blank) => setEdit({ mode, idx, draft: { ...(idx != null ? rows[idx] : blank) } });
  const close = () => setEdit(null);
  const save  = () => {
    if (edit.mode === "new") setRows([{ ...edit.draft }, ...rows]);
    else setRows(rows.map((r, i) => i === edit.idx ? edit.draft : r));
    setEdit(null);
  };
  const remove = (idx) => {
    const nameKey = rows[idx].nome || rows[idx].name || rows[idx].motivo || "este item";
    if (!confirm(`Excluir "${nameKey}"? Esta ação não pode ser desfeita.`)) return;
    setRows(rows.filter((_, i) => i !== idx));
    if (edit && edit.idx === idx) setEdit(null);
  };
  const set = (k, v) => setEdit({ ...edit, draft: { ...edit.draft, [k]: v } });

  return { rows, edit, open, close, save, remove, set };
}

// ============================================================
// EDIÇÃO EM MASSA
// ============================================================
const BULK_FIELDS = [
  { key: "custo",          col: "custo",           label: "Preço de custo",      group: "Preços",      type: "num" },
  { key: "venda",          col: "preco_venda",     label: "Preço de venda",      group: "Preços",      type: "num" },
  { key: "precoDiv",       col: "preco_dist",      label: "Preço distribuidor",  group: "Preços",      type: "num" },
  { key: "precoSalao",     col: "preco_salao",     label: "Preço salão",         group: "Preços",      type: "num" },
  { key: "precoPromo",     col: "preco_promo",     label: "Preço promocional",   group: "Preços",      type: "num" },
  { key: "est",            col: "estoque",         label: "Estoque atual",       group: "Estoque",     type: "int" },
  { key: "min",            col: "estoque_minimo",  label: "Estoque mínimo",      group: "Estoque",     type: "int" },
  { key: "linha",          col: "linha",           label: "Linha",               group: "Organização", type: "select" },
  { key: "cat",            col: "categoria",       label: "Categoria",           group: "Organização", type: "select" },
  { key: "marca",          col: "marca",           label: "Marca / empresa",     group: "Organização", type: "select" },
  { key: "unidade",        col: "unidade",         label: "Unidade",             group: "Organização", type: "select" },
  { key: "statusCadastro", col: "status_cadastro", label: "Status do produto",   group: "Status",      type: "select" },
  { key: "descricao",      col: "descricao",       label: "Descrição",           group: "Conteúdo",    type: "text" },
];

const BULK_OPS = [
  { v: "set",    label: "Definir valor" },
  { v: "incPct", label: "Aumentar %" },
  { v: "decPct", label: "Reduzir %" },
  { v: "add",    label: "Somar valor" },
  { v: "sub",    label: "Subtrair valor" },
];

function bulkOptionsFor(field, ctx) {
  if (field.key === "linha")          return ctx.linhas || [];
  if (field.key === "cat")            return ctx.categorias || [];
  if (field.key === "marca")          return ctx.marcas || [];
  if (field.key === "unidade")        return ["UN", "CX", "KG", "G", "L", "ML", "PCT"];
  if (field.key === "statusCadastro") return ["Ativo", "Inativo", "Descontinuado", "Em lançamento"];
  return [];
}

function bulkChangeText(field, ch) {
  if (field.type === "num" || field.type === "int") {
    const v = (ch.value === "" || ch.value == null) ? "—" : ch.value;
    if (ch.op === "incPct") return `aumentar ${v}%`;
    if (ch.op === "decPct") return `reduzir ${v}%`;
    if (ch.op === "add")    return `somar ${v}`;
    if (ch.op === "sub")    return `subtrair ${v}`;
    return `definir como ${v}`;
  }
  return `definir como "${ch.value || "—"}"`;
}

function BulkEditModal({ count, ctx, onClose, onApply }) {
  const [changes, setChanges] = useProdState({});
  const [step, setStep]       = useProdState("edit");
  const [busy, setBusy]       = useProdState(false);

  const toggle = (f) => setChanges(prev => {
    const next = { ...prev };
    if (next[f.key]) delete next[f.key];
    else next[f.key] = { op: "set", value: "" };
    return next;
  });
  const upd = (key, patch) => setChanges(prev => ({ ...prev, [key]: { ...prev[key], ...patch } }));

  const active = BULK_FIELDS.filter(f => changes[f.key]);
  const canReview = active.length > 0 && active.every(f => {
    const ch = changes[f.key];
    return ch.value !== "" && ch.value != null;
  });

  const groups = [];
  BULK_FIELDS.forEach(f => { if (!groups.includes(f.group)) groups.push(f.group); });

  const apply = async () => {
    setBusy(true);
    await onApply(changes);
    setBusy(false);
  };

  const overlay = { position: "fixed", inset: 0, zIndex: 320, background: "rgba(0,0,0,0.65)",
    display: "flex", alignItems: "center", justifyContent: "center" };
  const panel = { background: "var(--tm-bg-1)", borderRadius: 14, width: 580, maxHeight: "84vh",
    border: "1px solid var(--tm-line-1)", boxShadow: "0 24px 64px rgba(0,0,0,0.5)",
    display: "flex", flexDirection: "column" };

  return (
    <div style={overlay} onClick={() => !busy && onClose()}>
      <div style={panel} onClick={(e) => e.stopPropagation()}>
        <div style={{ padding: "18px 22px", borderBottom: "1px solid var(--tm-line-1)", display: "flex", alignItems: "flex-start", justifyContent: "space-between" }}>
          <div>
            <div style={{ fontFamily: "var(--tm-font-display)", fontSize: 18 }}>Editar em massa</div>
            <div className="muted" style={{ fontSize: 12.5, marginTop: 2 }}>
              {count} produto{count !== 1 ? "s" : ""} selecionado{count !== 1 ? "s" : ""}
            </div>
          </div>
          <button className="icon-btn" onClick={() => !busy && onClose()}><Icon name="x" size={16} /></button>
        </div>

        <div style={{ padding: "16px 22px", overflow: "auto" }}>
          {step === "edit" ? (
            <>
              <div className="muted" style={{ fontSize: 12.5 }}>
                Marque os campos que deseja alterar. Os campos não marcados permanecem intocados.
              </div>
              {groups.map(g => (
                <div key={g} style={{ marginTop: 14 }}>
                  <div style={{ fontSize: 10.5, fontWeight: 600, letterSpacing: "0.09em", textTransform: "uppercase", color: "var(--tm-fg-3)", marginBottom: 4 }}>{g}</div>
                  {BULK_FIELDS.filter(f => f.group === g).map(f => {
                    const ch = changes[f.key];
                    const on = !!ch;
                    const numeric = f.type === "num" || f.type === "int";
                    return (
                      <div key={f.key} style={{ padding: "8px 0", borderBottom: "1px solid var(--tm-line-0)" }}>
                        <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                          <label style={{ display: "flex", alignItems: "center", gap: 8, cursor: "pointer", minWidth: 188 }}>
                            <input type="checkbox" checked={on} onChange={() => toggle(f)} style={{ accentColor: "var(--tm-brand-champagne)" }} />
                            <span style={{ fontSize: 13, color: on ? "var(--tm-fg-1)" : "var(--tm-fg-2)" }}>{f.label}</span>
                          </label>
                          {on && numeric && (
                            <>
                              <select className="input" style={{ height: 34, width: 150 }}
                                value={ch.op} onChange={(e) => upd(f.key, { op: e.target.value })}>
                                {BULK_OPS.map(o => <option key={o.v} value={o.v}>{o.label}</option>)}
                              </select>
                              <input className="input" type="number" style={{ height: 34, flex: 1 }}
                                placeholder={(ch.op === "incPct" || ch.op === "decPct") ? "%" : "valor"}
                                value={ch.value} onChange={(e) => upd(f.key, { value: e.target.value })} />
                            </>
                          )}
                          {on && f.type === "select" && (
                            <select className="input" style={{ height: 34, flex: 1 }}
                              value={ch.value} onChange={(e) => upd(f.key, { value: e.target.value })}>
                              <option value="" disabled>selecione</option>
                              {bulkOptionsFor(f, ctx).map(o => <option key={o} value={o}>{o}</option>)}
                            </select>
                          )}
                        </div>
                        {on && f.type === "text" && (
                          <textarea className="input" rows={2} style={{ marginTop: 8, width: "100%", resize: "vertical" }}
                            placeholder="Novo texto para todos os selecionados"
                            value={ch.value} onChange={(e) => upd(f.key, { value: e.target.value })} />
                        )}
                      </div>
                    );
                  })}
                </div>
              ))}
            </>
          ) : (
            <>
              <div style={{ fontSize: 13, marginBottom: 10 }}>
                As alterações abaixo serão aplicadas a <b>{count} produto{count !== 1 ? "s" : ""}</b>:
              </div>
              {active.map(f => (
                <div key={f.key} style={{ display: "flex", gap: 8, padding: "7px 0", borderBottom: "1px solid var(--tm-line-0)", fontSize: 13 }}>
                  <Icon name="chevron-right" size={13} className="muted" style={{ marginTop: 2 }} />
                  <span><b>{f.label}</b> — {bulkChangeText(f, changes[f.key])}</span>
                </div>
              ))}
              <div style={{ marginTop: 12, padding: "10px 12px", borderRadius: 8,
                background: "rgba(245,158,11,0.1)", border: "1px solid rgba(245,158,11,0.3)",
                fontSize: 12, color: "var(--tm-fg-2)", display: "flex", gap: 8 }}>
                <Icon name="alert-triangle" size={13} style={{ color: "var(--tm-warning)", flexShrink: 0, marginTop: 1 }} />
                <span>Esta ação altera vários produtos de uma vez e não pode ser desfeita automaticamente.</span>
              </div>
            </>
          )}
        </div>

        <div style={{ padding: "13px 22px", borderTop: "1px solid var(--tm-line-1)", display: "flex", justifyContent: "flex-end", gap: 10 }}>
          {step === "edit" ? (
            <>
              <Button variant="secondary" onClick={onClose}>Cancelar</Button>
              <Button variant="primary" icon="arrow-right" disabled={!canReview} onClick={() => setStep("review")}>
                Revisar alterações
              </Button>
            </>
          ) : (
            <>
              <Button variant="secondary" onClick={() => setStep("edit")} disabled={busy}>Voltar</Button>
              <Button variant="primary" icon="check" disabled={busy} onClick={apply}>
                {busy ? "Aplicando…" : `Aplicar a ${count} produto${count !== 1 ? "s" : ""}`}
              </Button>
            </>
          )}
        </div>
      </div>
    </div>
  );
}

// ============================================================
// PRÉ-VISUALIZAÇÃO DE IMAGEM DO PRODUTO
// ============================================================
function ImagemPreview({ imagens, nome, onClose }) {
  const lista = imagens || [];
  const [idx, setIdx] = useProdState(0);
  if (lista.length === 0) return null;
  const cur = Math.min(idx, lista.length - 1);
  const go = (d) => setIdx((cur + d + lista.length) % lista.length);
  const navBtn = {
    width: 40, height: 40, borderRadius: "50%", border: "none", cursor: "pointer",
    background: "rgba(255,255,255,0.12)", color: "#fff",
    display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
  };
  return (
    <div onClick={onClose}
      style={{ position: "fixed", inset: 0, zIndex: 340, background: "rgba(0,0,0,0.82)",
        display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", gap: 14, padding: 24 }}>
      <button onClick={onClose} title="Fechar"
        style={{ position: "fixed", top: 20, right: 24, ...navBtn }}>
        <Icon name="x" size={20} />
      </button>
      <div onClick={(e) => e.stopPropagation()}
        style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }}>
        <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
          {lista.length > 1 && <button onClick={() => go(-1)} style={navBtn}><Icon name="chevron-left" size={20} /></button>}
          <img src={lista[cur]} alt={nome}
            style={{ maxWidth: "72vw", maxHeight: "70vh", borderRadius: 12, objectFit: "contain",
              background: "var(--tm-bg-2)", boxShadow: "0 24px 64px rgba(0,0,0,0.6)" }} />
          {lista.length > 1 && <button onClick={() => go(1)} style={navBtn}><Icon name="chevron-right" size={20} /></button>}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 10, color: "#fff" }}>
          <span style={{ fontSize: 13 }}>{nome}</span>
          {lista.length > 1 && <span style={{ fontSize: 12, color: "rgba(255,255,255,0.6)" }}>{cur + 1} / {lista.length}</span>}
        </div>
        {lista.length > 1 && (
          <div style={{ display: "flex", gap: 8, flexWrap: "wrap", justifyContent: "center", maxWidth: "72vw" }}>
            {lista.map((u, i) => (
              <img key={u + i} src={u} alt="" onClick={() => setIdx(i)}
                style={{ width: 54, height: 54, borderRadius: 8, objectFit: "cover", cursor: "pointer",
                  border: i === cur ? "2px solid var(--tm-brand-champagne)" : "2px solid transparent",
                  opacity: i === cur ? 1 : 0.55 }} />
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ============================================================
// PRODUTOS — LISTA
// ============================================================
function ProdutosLista({ onNav, empresaAtual }) {
  const s = useProdutosList(PRODUTOS_SEED);

  const linhasOpts    = useLinhasList([]);
  const catsOpts      = useCategoriasList([]);
  const empresasOpts  = useEmpresasList([]);

  const [search, setSearch]         = React.useState("");
  const [filterVals, setFilterVals] = React.useState({ linha: "", cat: "", status: "" });

  // Se uma empresa não-principal está selecionada, filtra por marca
  const empresaFiltroNome = (empresaAtual && !empresaAtual.principal)
    ? (empresaAtual.nome_fantasia || empresaAtual.razao_social || null)
    : null;

  // Novo produto já nasce vinculado à empresa em foco (evita marca em branco)
  const blank = { name: "", sku: "", linha: "", cat: "", ncm: "", custo: 0, venda: 0, est: 0, min: 0, status: "OK", unidade: "UN", statusCadastro: "Ativo", marca: empresaFiltroNome || "", variacoes: [] };

  // Produtos da empresa selecionada — base para KPIs, contagens e alertas
  const empresaRows = empresaFiltroNome
    ? s.rows.filter(r => r.marca === empresaFiltroNome)
    : s.rows;

  const filteredRows = s.rows
    .map((r, origIdx) => ({ ...r, _origIdx: origIdx }))
    .filter(r => {
      const q = search.toLowerCase();
      const ok = !q
        || (r.name  || "").toLowerCase().includes(q)
        || (r.sku   || "").toLowerCase().includes(q)
        || (r.ean   || "").toLowerCase().includes(q);
      return ok
        && (!filterVals.linha  || r.linha  === filterVals.linha)
        && (!filterVals.cat    || r.cat    === filterVals.cat)
        && (!filterVals.status || r.status === filterVals.status)
        && (!empresaFiltroNome || r.marca  === empresaFiltroNome);
    });

  const filterOpts = [
    { label: "Linha",         key: "linha",  options: linhasOpts.rows.map(l => l.nome) },
    { label: "Categoria",     key: "cat",    options: catsOpts.rows.map(c => c.nome)   },
    { label: "Status estoque",key: "status", options: ["OK", "Baixo", "Zerado"]        },
  ];

  // ── Modo de visualização: tabela | grade ───────────────────
  const [viewMode, setViewMode] = React.useState("tabela");

  // ── Ordenação da tabela ──────────────────────────────────────
  const [sortKey, setSortKey] = React.useState("");
  const [sortDir, setSortDir] = React.useState("asc");
  const toggleSort = (key) => {
    if (sortKey === key) {
      if (sortDir === "asc") setSortDir("desc");
      else { setSortKey(""); setSortDir("asc"); }
    } else {
      setSortKey(key);
      setSortDir("asc");
    }
  };

  // ── Seleção múltipla / edição em massa ──────────────────────
  const [selected, setSelected] = React.useState(() => new Set());
  const [bulkOpen, setBulkOpen] = React.useState(false);
  const [preview, setPreview]   = React.useState(null);

  // ── Variações de produto ────────────────────────────────────
  const [variacoes, setVariacoes]       = React.useState([]);
  const [expandedRows, setExpandedRows] = React.useState(() => new Set());

  React.useEffect(() => {
    if (window.tmDb) window.tmDb.loadVariacoes().then(setVariacoes);
  }, []);
  const reloadVariacoes = () => {
    if (window.tmDb) window.tmDb.loadVariacoes().then(setVariacoes);
  };

  const varPorProduto = {};
  variacoes.forEach(v => {
    (varPorProduto[v.produtoId] = varPorProduto[v.produtoId] || []).push(v);
  });
  const variacoesDe = (p) => varPorProduto[p.id] || [];
  const estoqueDe   = (p) => {
    const vs = variacoesDe(p);
    return vs.length ? vs.reduce((a, v) => a + (Number(v.est) || 0), 0) : (Number(p.est) || 0);
  };

  const sortedRows = sortKey ? [...filteredRows].sort((a, b) => {
    let av, bv;
    if (sortKey === "markup") {
      av = a.custo > 0 ? a.venda / a.custo : 0;
      bv = b.custo > 0 ? b.venda / b.custo : 0;
    } else if (sortKey === "estoque") {
      av = estoqueDe(a);
      bv = estoqueDe(b);
    } else {
      av = a[sortKey] ?? "";
      bv = b[sortKey] ?? "";
    }
    if (typeof av === "number" && typeof bv === "number") {
      return sortDir === "asc" ? av - bv : bv - av;
    }
    return sortDir === "asc"
      ? String(av).localeCompare(String(bv), "pt-BR")
      : String(bv).localeCompare(String(av), "pt-BR");
  }) : filteredRows;

  const SortTh = ({ k, children, className }) => {
    const active = sortKey === k;
    return (
      <th className={className} onClick={() => toggleSort(k)} style={{ cursor: "pointer", userSelect: "none", whiteSpace: "nowrap" }}>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 4 }}>
          {children}
          <span style={{ fontSize: 9, lineHeight: 1, opacity: active ? 1 : 0.25, color: active ? "var(--tm-brand-champagne)" : "inherit" }}>
            {active && sortDir === "desc" ? "▼" : "▲"}
          </span>
        </span>
      </th>
    );
  };

  const toggleExpand = (id) => setExpandedRows(prev => {
    const n = new Set(prev);
    if (n.has(id)) n.delete(id); else n.add(id);
    return n;
  });

  // Carrega as variações do produto em edição para dentro do rascunho
  React.useEffect(() => {
    const ed = s.edit;
    if (!ed || ed.mode !== "edit") return;
    if (ed.draft.variacoes !== undefined) return;
    if (!ed.draft.id) { s.set("variacoes", []); return; }
    let cancel = false;
    window.tmDb.loadVariacoes(ed.draft.id).then(vs => { if (!cancel) s.set("variacoes", vs); });
    return () => { cancel = true; };
  // eslint-disable-next-line
  }, [s.edit && s.edit.draft && s.edit.draft.id, s.edit && s.edit.draft && s.edit.draft.variacoes !== undefined]);

  const saveProduto = async () => {
    const draft = s.edit.draft;
    const vs = Array.isArray(draft.variacoes) ? draft.variacoes : [];
    // Aviso de SKU duplicado entre as variações — não bloqueia
    const skus = vs.map(v => (v.sku || "").trim()).filter(Boolean);
    const dup  = [...new Set(skus.filter((sk, i) => skus.indexOf(sk) !== i))];
    if (dup.length && !confirm(`Há SKUs repetidos entre as variações: ${dup.join(", ")}.\nSalvar mesmo assim?`)) return;
    const { error } = await window.tmDb.saveProdutoComVariacoes(draft);
    if (error) { alert("Erro ao salvar produto: " + (error.message || error)); return; }
    await s.reload();
    reloadVariacoes();
    s.close();
  };

  const visibleIds = filteredRows.map(r => r.id).filter(Boolean);
  const allSelected = visibleIds.length > 0 && visibleIds.every(id => selected.has(id));
  const toggleOne = (id) => setSelected(prev => {
    const n = new Set(prev);
    if (n.has(id)) n.delete(id); else n.add(id);
    return n;
  });
  const toggleAll = () => setSelected(prev => {
    const n = new Set(prev);
    if (allSelected) visibleIds.forEach(id => n.delete(id));
    else visibleIds.forEach(id => n.add(id));
    return n;
  });

  const applyBulk = async (changes) => {
    if (!window.tmSupabase) { alert("Supabase indisponível — não foi possível salvar."); return; }
    const targets = s.rows.filter(r => r.id && selected.has(r.id));
    const calc = (cur, op, v) => {
      cur = Number(cur) || 0; v = Number(v) || 0;
      if (op === "incPct") return cur * (1 + v / 100);
      if (op === "decPct") return cur * (1 - v / 100);
      if (op === "add")    return cur + v;
      if (op === "sub")    return cur - v;
      return v;
    };
    let erros = 0;
    await Promise.all(targets.map(async (row) => {
      const patch = {};
      BULK_FIELDS.forEach(f => {
        const ch = changes[f.key];
        if (!ch) return;
        if (f.type === "num")
          patch[f.col] = Math.max(0, Math.round(calc(row[f.key], ch.op, ch.value) * 100) / 100);
        else if (f.type === "int")
          patch[f.col] = Math.max(0, Math.round(calc(row[f.key], ch.op, ch.value)));
        else
          patch[f.col] = ch.value;
      });
      const { error } = await window.tmSupabase.from("produtos").update(patch).eq("id", row.id);
      if (error) erros++;
    }));
    await s.reload();
    setSelected(new Set());
    setBulkOpen(false);
    if (erros > 0) alert(`${erros} produto(s) não puderam ser atualizados.`);
  };

  if (s.edit) {
    return (
      <ProdutoForm
        state={s.edit}
        set={s.set}
        onCancel={s.close}
        onSave={saveProduto}
        onDelete={() => s.remove(s.edit.idx)}
        linhas={linhasOpts.rows.map(l => l.nome)}
        categorias={catsOpts.rows.map(c => c.nome)}
        marcas={empresasOpts.rows.map(e => e.nome)}
      />
    );
  }

  const alertas = empresaRows.filter(p => p.status === "Crítico" || p.status === "Baixo");
  const criticos = empresaRows.filter(p => p.status === "Crítico");
  const baixos   = empresaRows.filter(p => p.status === "Baixo");
  const alertaSub = empresaRows.length === 0 ? "sem produtos cadastrados"
    : (criticos.length > 0 || baixos.length > 0)
      ? `${criticos.length} crítico${criticos.length !== 1 ? "s" : ""} · ${baixos.length} baixo${baixos.length !== 1 ? "s" : ""}`
      : "estoque OK";

  return (
    <div className="canvas">
      <PageHead title="Produtos"
        sub={empresaRows.length > 0 ? `${empresaRows.length} SKU${empresaRows.length !== 1 ? "s" : ""} cadastrado${empresaRows.length !== 1 ? "s" : ""}` : "Nenhum produto cadastrado"}
        right={<><Button variant="secondary" icon="download" size="sm">Exportar</Button>
                  <Button variant="secondary" icon="upload" size="sm">Importar XML</Button>
                  <Button variant="primary" icon="plus" size="sm" onClick={() => s.open("new", null, blank)}>Novo produto</Button></>}/>
      <ProdutosTabs active="lista" onNav={onNav} rows={empresaRows} linhasRows={linhasOpts.rows} catsRows={catsOpts.rows} />

      <div className="grid-4" style={{ marginBottom: 16 }}>
        <KpiMini lbl="SKUs ativos" v={String(empresaRows.length)} sub={empresaRows.length === 0 ? "adicione produtos" : "cadastrados"} />
        <KpiMini lbl="Estoque total" v={empresaRows.length > 0 ? `${empresaRows.reduce((a, p) => a + estoqueDe(p), 0)} un` : "—"} sub={empresaRows.length > 0 ? "unidades em estoque" : "sem dados"} />
        <KpiMini lbl="Markup médio" v={empresaRows.length > 0 ? `${(empresaRows.reduce((a, p) => a + (p.custo > 0 ? p.venda / p.custo : 0), 0) / empresaRows.length).toFixed(2)}×` : "—"} sub={empresaRows.length > 0 ? "média dos produtos" : "sem dados"} />
        <KpiMini lbl="Alertas de estoque" v={String(alertas.length)} sub={alertaSub} />
      </div>

      <Card>
        <Toolbar
          search="SKU, EAN, nome do produto…"
          onSearch={setSearch}
          filterOpts={filterOpts}
          filterValues={filterVals}
          onFilter={(k, v) => setFilterVals(prev => ({ ...prev, [k]: prev[k] === v ? "" : v }))}
          viewMode={viewMode}
          onViewMode={setViewMode}
        />
        {selected.size > 0 && (
          <div style={{
            display: "flex", alignItems: "center", gap: 12, padding: "10px 14px", marginBottom: 8,
            background: "color-mix(in srgb, var(--tm-brand-champagne) 12%, transparent)",
            border: "1px solid color-mix(in srgb, var(--tm-brand-champagne) 35%, transparent)",
            borderRadius: 8,
          }}>
            <Icon name="check-square" size={15} style={{ color: "var(--tm-brand-champagne)" }} />
            <span style={{ fontSize: 13, fontWeight: 500 }}>
              {selected.size} produto{selected.size !== 1 ? "s" : ""} selecionado{selected.size !== 1 ? "s" : ""}
            </span>
            <div style={{ flex: 1 }} />
            <Button variant="secondary" size="sm" onClick={() => setSelected(new Set())}>Limpar seleção</Button>
            <Button variant="primary" size="sm" icon="pencil" onClick={() => setBulkOpen(true)}>Editar em massa</Button>
          </div>
        )}
        {s.rows.length === 0 ? (
          <div style={{ padding: "48px 0", textAlign: "center", color: "var(--tm-fg-3)" }}>
            <Icon name="package" size={36} style={{ opacity: 0.3, marginBottom: 12 }} />
            <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhum produto cadastrado</div>
            <div style={{ fontSize: 12 }}>Clique em "Novo produto" para começar</div>
          </div>
        ) : filteredRows.length === 0 ? (
          <div style={{ padding: "48px 0", textAlign: "center", color: "var(--tm-fg-3)" }}>
            <Icon name="search" size={36} style={{ opacity: 0.3, marginBottom: 12 }} />
            {empresaRows.length === 0 && empresaFiltroNome ? (
              <>
                <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhum produto de {empresaFiltroNome}</div>
                <div style={{ fontSize: 12 }}>Cadastre produtos ou ajuste a marca / empresa no cadastro do produto</div>
              </>
            ) : (
              <>
                <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhum produto encontrado</div>
                <div style={{ fontSize: 12 }}>Tente outro termo ou remova os filtros ativos</div>
              </>
            )}
          </div>
        ) : viewMode === "grade" ? (
          <>
            <div style={{
              display: "grid",
              gridTemplateColumns: "repeat(auto-fill, minmax(190px, 1fr))",
              gap: 12, padding: "4px 2px 8px",
            }}>
              {sortedRows.map((p) => {
                const vs = variacoesDe(p);
                const temVar = vs.length > 0;
                const est = estoqueDe(p);
                const isSel = p.id && selected.has(p.id);
                return (
                  <div key={p._origIdx}
                    onClick={() => s.open("edit", p._origIdx)}
                    style={{
                      background: isSel
                        ? "color-mix(in srgb, var(--tm-brand-champagne) 8%, var(--tm-bg-2))"
                        : "var(--tm-bg-2)",
                      border: isSel
                        ? "1px solid color-mix(in srgb, var(--tm-brand-champagne) 40%, transparent)"
                        : "1px solid var(--tm-line-1)",
                      borderRadius: 10, overflow: "hidden", cursor: "pointer",
                      transition: "border-color 0.15s, box-shadow 0.15s",
                      display: "flex", flexDirection: "column",
                    }}
                    onMouseEnter={(e) => { e.currentTarget.style.boxShadow = "0 4px 16px rgba(0,0,0,0.22)"; e.currentTarget.style.borderColor = "var(--tm-line-2)"; }}
                    onMouseLeave={(e) => { e.currentTarget.style.boxShadow = "none"; e.currentTarget.style.borderColor = isSel ? "color-mix(in srgb, var(--tm-brand-champagne) 40%, transparent)" : "var(--tm-line-1)"; }}
                  >
                    {/* Imagem */}
                    <div style={{
                      height: 120, background: "var(--tm-bg-3)", position: "relative",
                      display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0,
                    }}>
                      {p.imagens && p.imagens[0]
                        ? <img src={p.imagens[0]} alt={p.name}
                            onClick={(e) => { e.stopPropagation(); setPreview(p); }}
                            style={{ width: "100%", height: "100%", objectFit: "cover", cursor: "zoom-in" }} />
                        : <Icon name="package" size={28} style={{ color: "var(--tm-fg-3)", opacity: 0.4 }} />
                      }
                      {/* Checkbox seleção */}
                      <div style={{ position: "absolute", top: 7, left: 7 }} onClick={(e) => e.stopPropagation()}>
                        <input type="checkbox" checked={!!isSel} disabled={!p.id}
                          onChange={() => toggleOne(p.id)}
                          style={{ accentColor: "var(--tm-brand-champagne)", cursor: "pointer", width: 14, height: 14 }} />
                      </div>
                      {/* Badge status */}
                      <div style={{ position: "absolute", top: 6, right: 6 }}>
                        <Badge tone={p.status === "Crítico" ? "danger" : p.status === "Baixo" ? "warning" : "success"}>
                          {p.status}
                        </Badge>
                      </div>
                    </div>

                    {/* Corpo */}
                    <div style={{ padding: "10px 11px", display: "flex", flexDirection: "column", gap: 4, flex: 1 }}>
                      <div style={{ fontSize: 12.5, fontWeight: 500, lineHeight: 1.35, color: "var(--tm-fg-1)" }}>
                        {p.name}
                      </div>
                      <div style={{ display: "flex", alignItems: "center", gap: 6, marginTop: 1 }}>
                        <span style={{
                          fontSize: 10.5, fontFamily: "monospace", letterSpacing: "0.02em",
                          color: "var(--tm-brand-champagne)", background: "rgba(201,163,107,0.1)",
                          padding: "1px 6px", borderRadius: 4,
                        }}>{p.sku || "—"}</span>
                        {p.linha && <span className="muted" style={{ fontSize: 10.5, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{p.linha}</span>}
                      </div>
                      {temVar && (
                        <span style={{ fontSize: 10, padding: "1px 7px", borderRadius: 10, alignSelf: "flex-start", marginTop: 1,
                          background: "color-mix(in srgb, var(--tm-brand-champagne) 16%, transparent)",
                          color: "var(--tm-brand-champagne)" }}>
                          {vs.length} variaç{vs.length === 1 ? "ão" : "ões"}
                        </span>
                      )}

                      {/* Preços */}
                      <div style={{ marginTop: "auto", paddingTop: 8, borderTop: "1px solid var(--tm-line-0)", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
                        <div>
                          {!temVar && (
                            <div style={{ fontSize: 13.5, fontWeight: 600, color: "var(--tm-brand-champagne)", fontVariantNumeric: "tabular-nums" }}>
                              R$ {brl(p.venda)}
                            </div>
                          )}
                          <div className="muted" style={{ fontSize: 10.5 }}>
                            {est} un{!temVar && p.min > 0 ? ` / mín ${p.min}` : ""}
                          </div>
                        </div>
                        {!temVar && p.custo > 0 && (
                          <span style={{ fontSize: 11, fontWeight: 600, color: "var(--tm-fg-2)" }}>
                            {(p.venda / p.custo).toFixed(2)}×
                          </span>
                        )}
                      </div>
                    </div>
                  </div>
                );
              })}
            </div>
            <FooterPager total={filteredRows.length} from={1} to={filteredRows.length} />
          </>
        ) : (
          <>
            <table className="tbl">
              <thead><tr>
                <th style={{ width: 34 }}>
                  <input type="checkbox" checked={allSelected} onChange={toggleAll}
                    title="Selecionar todos" style={{ accentColor: "var(--tm-brand-champagne)", cursor: "pointer" }} />
                </th>
                <SortTh k="name">Produto</SortTh>
                <SortTh k="sku">SKU</SortTh>
                <SortTh k="linha">Linha</SortTh>
                <SortTh k="ncm">NCM</SortTh>
                <SortTh k="custo" className="num right">Custo</SortTh>
                <SortTh k="venda" className="num right">Venda</SortTh>
                <SortTh k="markup" className="num right">Markup</SortTh>
                <SortTh k="estoque" className="num right">Estoque</SortTh>
                <SortTh k="status">Status</SortTh>
                <th></th>
              </tr></thead>
              <tbody>
                {sortedRows.map((p) => {
                  const vs = variacoesDe(p);
                  const temVar = vs.length > 0;
                  const aberta = p.id && expandedRows.has(p.id);
                  return (
                  <React.Fragment key={p._origIdx}>
                  <tr className="clickable"
                      style={p.id && selected.has(p.id) ? { background: "color-mix(in srgb, var(--tm-brand-champagne) 7%, transparent)" } : null}
                      onClick={() => s.open("edit", p._origIdx)}>
                    <td onClick={(e) => e.stopPropagation()}>
                      <input type="checkbox" checked={p.id ? selected.has(p.id) : false}
                        disabled={!p.id} onChange={() => toggleOne(p.id)}
                        style={{ accentColor: "var(--tm-brand-champagne)", cursor: "pointer" }} />
                    </td>
                    <td>
                      <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                        {temVar ? (
                          <button className="icon-btn" title={aberta ? "Recolher variações" : "Ver variações"}
                            style={{ flexShrink: 0 }}
                            onClick={(e) => { e.stopPropagation(); toggleExpand(p.id); }}>
                            <Icon name={aberta ? "chevron-down" : "chevron-right"} size={14} />
                          </button>
                        ) : <span style={{ width: 24, flexShrink: 0 }} />}
                        <div className="prod-image"
                          style={{ width: 36, height: 36, overflow: "hidden", flexShrink: 0, cursor: (p.imagens && p.imagens[0]) ? "zoom-in" : "default" }}
                          title={(p.imagens && p.imagens[0]) ? "Ver imagem" : undefined}
                          onClick={(p.imagens && p.imagens[0]) ? (e) => { e.stopPropagation(); setPreview(p); } : undefined}>
                          {p.imagens && p.imagens[0]
                            ? <img src={p.imagens[0]} alt="" style={{ width: "100%", height: "100%", objectFit: "cover" }} />
                            : <Icon name="package" size={14} />}
                        </div>
                        <span style={{ fontSize: 13 }}>{p.name}</span>
                        {temVar && (
                          <span style={{ fontSize: 10, padding: "1px 7px", borderRadius: 10, flexShrink: 0,
                            background: "color-mix(in srgb, var(--tm-brand-champagne) 16%, transparent)",
                            color: "var(--tm-brand-champagne)" }}>
                            {vs.length} variaç{vs.length === 1 ? "ão" : "ões"}
                          </span>
                        )}
                      </div>
                    </td>
                    <td><span className="ref-mono">{p.sku}</span></td>
                    <td>{p.linha}</td>
                    <td><span className="ref-mono">{p.ncm}</span></td>
                    <td className="num right">{temVar ? "—" : `R$ ${brl(p.custo)}`}</td>
                    <td className="num right">{temVar ? "—" : `R$ ${brl(p.venda)}`}</td>
                    <td className="num right gold">{temVar ? "—" : `${p.custo > 0 ? (p.venda / p.custo).toFixed(2) : "—"}×`}</td>
                    <td className="num right">
                      {estoqueDe(p)}
                      <span className="muted" style={{ fontSize: 10.5 }}>{temVar ? " un" : ` / ${p.min}`}</span>
                    </td>
                    <td><Badge tone={p.status === "Crítico" ? "danger" : p.status === "Baixo" ? "warning" : "success"}>{p.status}</Badge></td>
                    <td><RowActions onEdit={() => s.open("edit", p._origIdx)} onDelete={() => s.remove(p._origIdx)} /></td>
                  </tr>
                  {temVar && aberta && vs.map((v, vi) => (
                    <tr key={p._origIdx + "-v" + vi} style={{ background: "var(--tm-bg-2)" }}>
                      <td />
                      <td style={{ paddingLeft: 48 }}>
                        <span style={{ fontSize: 12.5 }}>{v.nome || `Variação ${vi + 1}`}</span>
                        {v.tipo && <span className="muted" style={{ fontSize: 10.5, marginLeft: 6 }}>{v.tipo}</span>}
                      </td>
                      <td><span className="ref-mono">{v.sku || "—"}</span></td>
                      <td className="muted">{p.linha}</td>
                      <td />
                      <td className="num right">R$ {brl(v.custo || 0)}</td>
                      <td className="num right">R$ {brl(v.venda || 0)}</td>
                      <td className="num right gold">{v.custo > 0 ? (v.venda / v.custo).toFixed(2) : "—"}×</td>
                      <td className="num right">{Number(v.est) || 0} <span className="muted" style={{ fontSize: 10.5 }}>/ {Number(v.min) || 0}</span></td>
                      <td /><td />
                    </tr>
                  ))}
                  </React.Fragment>
                  );
                })}
              </tbody>
            </table>
            <FooterPager total={filteredRows.length} from={1} to={Math.min(filteredRows.length, 8)} />
          </>
        )}
      </Card>

      {bulkOpen && (
        <BulkEditModal
          count={selected.size}
          ctx={{
            linhas:     linhasOpts.rows.map(l => l.nome),
            categorias: catsOpts.rows.map(c => c.nome),
            marcas:     empresasOpts.rows.map(e => e.nome),
          }}
          onClose={() => setBulkOpen(false)}
          onApply={applyBulk}
        />
      )}

      {preview && (
        <ImagemPreview
          imagens={preview.imagens}
          nome={preview.name}
          onClose={() => setPreview(null)}
        />
      )}
    </div>
  );
}

// ============================================================
// LINHAS
// ============================================================
function ProdutosLinhas({ onNav }) {
  const s = useLinhasList([]);
  const blank = { nome: "", tagline: "", skus: 0, vendaMes: 0, color: "#C9A36B", status: "Ativa", posicionamento: "Premium" };

  if (s.edit) {
    return (
      <LinhaForm state={s.edit} set={s.set}
        onCancel={s.close} onSave={s.save} onDelete={() => s.remove(s.edit.idx)} />
    );
  }

  return (
    <div className="canvas">
      <PageHead title="Linhas de Produto" sub="Agrupamento estratégico por categoria comercial"
        right={<Button variant="primary" icon="plus" size="sm" onClick={() => s.open("new", null, blank)}>Nova linha</Button>}/>
      <ProdutosTabs active="linhas" onNav={onNav} />
      {s.rows.length === 0 && (
        <div style={{ padding: "48px 0", textAlign: "center", color: "var(--tm-fg-3)" }}>
          <Icon name="layers" size={36} style={{ opacity: 0.3, marginBottom: 12 }} />
          <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhuma linha cadastrada</div>
          <div style={{ fontSize: 12 }}>Clique em "Nova linha" para começar</div>
        </div>
      )}
      <div className="grid-3">
        {s.rows.map((l, i) => (
          <div key={i} className="card rep-card" style={{ padding: 0, overflow: "hidden" }} onClick={() => s.open("edit", i)}>
            <div style={{ height: 6, background: l.color }} />
            <div style={{ padding: 18 }}>
              <div className="row between">
                <div style={{ fontFamily: "var(--tm-font-display)", fontSize: 20 }}>{l.nome}</div>
                <span className="row-actions" style={{ opacity: 1 }} onClick={(e) => e.stopPropagation()}>
                  <button className="icon-btn" title="Editar" onClick={() => s.open("edit", i)}><Icon name="pencil" size={14} /></button>
                  <button className="icon-btn danger" title="Excluir" onClick={() => s.remove(i)}><Icon name="trash-2" size={14} /></button>
                </span>
              </div>
              <div className="muted" style={{ fontSize: 12, marginTop: 2 }}>{l.tagline}</div>
              <div style={{ display: "flex", gap: 18, marginTop: 14, paddingTop: 14, borderTop: "1px solid var(--tm-line-1)" }}>
                <div><div className="muted" style={{ fontSize: 10.5, letterSpacing: "0.1em", textTransform: "uppercase" }}>SKUs</div><div style={{ fontSize: 18, fontWeight: 600 }}>{l.skus}</div></div>
                <div><div className="muted" style={{ fontSize: 10.5, letterSpacing: "0.1em", textTransform: "uppercase" }}>Vendas mês</div><div style={{ fontSize: 18, fontWeight: 600 }}>R$ {brl(l.vendaMes).split(",")[0]}</div></div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ============================================================
// CATEGORIAS
// ============================================================
function ProdutosCategorias({ onNav }) {
  const s = useCategoriasList([]);
  const blank = { nome: "", skus: 0, fat: 0, ncmPadrao: "", cfopPadrao: "5102", status: "Ativa", color: "#C9A36B" };

  if (s.edit) {
    return (
      <CategoriaForm state={s.edit} set={s.set}
        onCancel={s.close} onSave={s.save} onDelete={() => s.remove(s.edit.idx)}
        categoriasPai={s.rows.map(c => c.nome)} />
    );
  }

  return (
    <div className="canvas">
      <PageHead title="Categorias" sub="Hierarquia fiscal e merchandising"
        right={<Button variant="primary" icon="plus" size="sm" onClick={() => s.open("new", null, blank)}>Nova categoria</Button>}/>
      <ProdutosTabs active="categorias" onNav={onNav} />
      <Card>
        {s.rows.length === 0 ? (
          <div style={{ padding: "48px 0", textAlign: "center", color: "var(--tm-fg-3)" }}>
            <Icon name="tag" size={36} style={{ opacity: 0.3, marginBottom: 12 }} />
            <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhuma categoria cadastrada</div>
            <div style={{ fontSize: 12 }}>Clique em "Nova categoria" para começar</div>
          </div>
        ) : (
        <table className="tbl">
          <thead><tr><th>Categoria</th><th className="num right">SKUs</th><th className="num right">Faturamento mês</th><th>NCM padrão</th><th>CFOP padrão</th><th></th></tr></thead>
          <tbody>
            {s.rows.map((c, i) => (
              <tr key={i} className="clickable" onClick={() => s.open("edit", i)}>
                <td>
                  <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                    <div style={{ width: 28, height: 28, borderRadius: 6, background: c.color || "var(--tm-bg-3)", display: "flex", alignItems: "center", justifyContent: "center" }}>
                      <Icon name="tag" size={13} style={{ color: "#0B0B0D" }} />
                    </div>
                    {c.nome}
                  </div>
                </td>
                <td className="num right">{c.skus}</td>
                <td className="num right">R$ {brl(c.fat)}</td>
                <td><span className="ref-mono">{c.ncmPadrao}</span></td>
                <td><span className="ref-mono">{c.cfopPadrao}</span></td>
                <td><RowActions onEdit={() => s.open("edit", i)} onDelete={() => s.remove(i)} /></td>
              </tr>
            ))}
          </tbody>
        </table>
        )}
      </Card>
    </div>
  );
}

// ============================================================
// TABELAS DE PREÇO
// ============================================================
function ProdutosTabelasPreco({ onNav }) {
  const s = useTabelasPrecoList([]);
  const blank = { nome: "", desc: "", prods: 0, desconto: "0%", color: "var(--tm-brand-champagne)", canal: "B2B", status: "Ativa", recorrencia: "Permanente" };

  if (s.edit) {
    return (
      <TabelaPrecoForm state={s.edit} set={s.set}
        onCancel={s.close} onSave={s.save} onDelete={() => s.remove(s.edit.idx)} />
    );
  }

  return (
    <div className="canvas">
      <PageHead title="Tabelas de Preço" sub={s.rows.length > 0 ? `${s.rows.length} tabela${s.rows.length !== 1 ? "s" : ""} cadastrada${s.rows.length !== 1 ? "s" : ""}` : "Nenhuma tabela cadastrada"}
        right={<><Button variant="secondary" icon="copy" size="sm">Duplicar</Button>
                  <Button variant="primary" icon="plus" size="sm" onClick={() => s.open("new", null, blank)}>Nova tabela</Button></>}/>
      <ProdutosTabs active="tabelas-preco" onNav={onNav} />
      {s.rows.length === 0 && (
        <div style={{ padding: "48px 0", textAlign: "center", color: "var(--tm-fg-3)" }}>
          <Icon name="percent" size={36} style={{ opacity: 0.3, marginBottom: 12 }} />
          <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhuma tabela de preço cadastrada</div>
          <div style={{ fontSize: 12 }}>Clique em "Nova tabela" para começar</div>
        </div>
      )}
      <div className="grid-3">
        {s.rows.map((t, i) => (
          <div key={i} className="card rep-card" style={{ padding: 0, overflow: "hidden" }} onClick={() => s.open("edit", i)}>
            <div style={{ padding: 18, display: "flex", flexDirection: "column", gap: 6 }}>
              <div className="row between">
                <span className="badge brand" style={{ background: t.color + "22", color: t.color }}>
                  <span className="dot" style={{ background: t.color }} />
                  {t.desconto} OFF
                </span>
                <span className="row-actions" style={{ opacity: 1 }} onClick={(e) => e.stopPropagation()}>
                  <button className="icon-btn" title="Editar" onClick={() => s.open("edit", i)}><Icon name="pencil" size={14} /></button>
                  <button className="icon-btn danger" title="Excluir" onClick={() => s.remove(i)}><Icon name="trash-2" size={14} /></button>
                </span>
              </div>
              <div style={{ fontFamily: "var(--tm-font-display)", fontSize: 20, marginTop: 6 }}>{t.nome}</div>
              <div className="muted" style={{ fontSize: 12 }}>{t.desc}</div>
              <div style={{ display: "flex", gap: 18, marginTop: 14, paddingTop: 14, borderTop: "1px solid var(--tm-line-1)" }}>
                <div><div className="muted" style={{ fontSize: 10.5, letterSpacing: "0.1em", textTransform: "uppercase" }}>Produtos</div><div style={{ fontSize: 16, fontWeight: 600 }}>{t.prods}</div></div>
                <div><div className="muted" style={{ fontSize: 10.5, letterSpacing: "0.1em", textTransform: "uppercase" }}>Canal</div><div style={{ fontSize: 14, fontWeight: 500 }}>{t.canal}</div></div>
              </div>
            </div>
          </div>
        ))}
      </div>
    </div>
  );
}

// ============================================================
// ESTOQUE — MOVIMENTAÇÕES
// ============================================================
function ProdutosEstoque({ onNav }) {
  const s    = useMovEstoqueList([]);
  const prod = useProdutosList([]);
  const blank = { tipo: "Entrada", motivo: "", sku: "", produtoId: "", variacaoId: null, qty: 0, saldo: 0, when: "", who: "", custoUn: 0 };

  const [variacoesEst, setVariacoesEst] = useProdState([]);
  React.useEffect(() => {
    if (window.tmDb) window.tmDb.loadVariacoes().then(setVariacoesEst);
  }, []);

  const salvarMov = async () => {
    const r = await window.tmDb.salvarMovimentacao(s.edit.draft, s.edit.mode === "new");
    if (r && r.error) { alert("Erro ao salvar movimentação: " + (r.error.message || r.error)); return; }
    await s.reload();
    if (window.tmDb) window.tmDb.loadVariacoes().then(setVariacoesEst);
    s.close();
  };

  if (s.edit) {
    return (
      <MovEstoqueForm state={s.edit} set={s.set}
        onCancel={s.close} onSave={salvarMov} onDelete={() => s.remove(s.edit.idx)}
        produtos={prod.rows.map(p => ({ value: p.id, label: `${p.sku} · ${p.name}`, sku: p.sku, temVariacoes: p.temVariacoes === true }))}
        variacoes={variacoesEst} />
    );
  }

  const totalUn = prod.rows.reduce((a, p) => a + (Number(p.est) || 0), 0);

  return (
    <div className="canvas">
      <PageHead title="Estoque" sub="Movimentações, lotes e alerta de estoque mínimo"
        right={<><Button variant="secondary" icon="upload" size="sm">Importar XML</Button>
                  <Button variant="primary" icon="plus" size="sm" onClick={() => s.open("new", null, blank)}>Nova movimentação</Button></>}/>
      <ProdutosTabs active="estoque" onNav={onNav} />

      <div className="grid-4" style={{ marginBottom: 16 }}>
        <KpiMini lbl="Total de unidades" v={totalUn > 0 ? String(totalUn) : "—"} sub={prod.rows.length > 0 ? `${prod.rows.length} SKUs` : "sem produtos"} />
        <KpiMini lbl="Valor em estoque" v="—" sub="registre movimentações" />
        <KpiMini lbl="Giro médio (90 dias)" v="—" sub="sem dados suficientes" />
        <KpiMini lbl="Alertas" v={String(prod.rows.filter(p => p.status === "Crítico" || p.status === "Baixo").length)} sub={prod.rows.length > 0 ? "verificar estoque" : "sem produtos"} />
      </div>

      <Card title="Movimentações recentes"
            action={<div style={{ display: "flex", gap: 6 }}>
              <span className="chip">Hoje</span>
              <span className="chip active">Últimos 7 dias</span>
              <span className="chip">Custom</span>
            </div>}>
        {s.rows.length === 0 ? (
          <div style={{ padding: "48px 0", textAlign: "center", color: "var(--tm-fg-3)" }}>
            <Icon name="inbox" size={36} style={{ opacity: 0.3, marginBottom: 12 }} />
            <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhuma movimentação registrada</div>
            <div style={{ fontSize: 12 }}>Clique em "Nova movimentação" para começar</div>
          </div>
        ) : (
          <table className="tbl">
            <thead><tr><th>Tipo</th><th>Motivo</th><th>SKU</th><th className="num right">Qtd</th><th className="num right">Saldo</th><th>Quando</th><th>Responsável</th><th></th></tr></thead>
            <tbody>
              {s.rows.map((m, i) => (
                <tr key={i} className="clickable" onClick={() => s.open("edit", i)}>
                  <td><Badge tone={m.tipo === "Entrada" ? "success" : m.tipo === "Saída" ? "danger" : "warning"}>{m.tipo}</Badge></td>
                  <td>{m.motivo}</td>
                  <td><span className="ref-mono">{m.sku}</span></td>
                  <td className="num right" style={{ color: m.qty > 0 ? "var(--tm-success)" : "var(--tm-danger)" }}>{m.qty > 0 ? "+" : ""}{m.qty}</td>
                  <td className="num right">{m.saldo}</td>
                  <td className="muted">{m.when}</td>
                  <td>{m.who}</td>
                  <td><RowActions onEdit={() => s.open("edit", i)} onDelete={() => s.remove(i)} /></td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </Card>
    </div>
  );
}

// ============================================================
// Row actions (local to Produtos — same look as CRM)
// ============================================================
function RowActions({ onEdit, onDelete }) {
  return (
    <span className="row-actions" onClick={(e) => e.stopPropagation()}>
      <button className="icon-btn" title="Editar" onClick={onEdit}>
        <Icon name="pencil" size={14} />
      </button>
      <button className="icon-btn danger" title="Excluir" onClick={onDelete}>
        <Icon name="trash-2" size={14} />
      </button>
    </span>
  );
}

function ProdutosTabs({ active, onNav, rows, linhasRows, catsRows }) {
  const tabs = [
    { id: "lista",        label: "Lista",           count: rows       ? rows.length       : undefined },
    { id: "linhas",       label: "Linhas",           count: linhasRows ? linhasRows.length : undefined },
    { id: "categorias",   label: "Categorias",       count: catsRows   ? catsRows.length   : undefined },
    { id: "tabelas-preco",label: "Tabelas de Preço", count: undefined },
    { id: "estoque",      label: "Estoque",          count: undefined },
  ];
  return (
    <div className="tabs">
      {tabs.map(t => (
        <div key={t.id} className={`tab ${active === t.id ? "active" : ""}`} onClick={() => onNav(`produtos/${t.id}`)}>
          {t.label}{t.count !== undefined && t.count > 0 && <span className="muted" style={{ marginLeft: 4 }}>({t.count})</span>}
        </div>
      ))}
    </div>
  );
}

// Expose to other modules (e.g. PDV) — empty until loaded from DB
const PRODUTOS = [];

Object.assign(window, { ProdutosLista, ProdutosLinhas, ProdutosCategorias, ProdutosTabelasPreco, ProdutosEstoque, PRODUTOS });
