/* Fabricação — Insumos, Receitas, Produção */

function Fabricacao({ ctx }) {
  const [sub, setSub] = useState("insumos");
  const [editingInput, setEditingInput] = useState(null);
  const [editingRecipe, setEditingRecipe] = useState(null);
  const [producing, setProducing] = useState(null);
  const [purchasing, setPurchasing] = useState(false);
  const [payTarget, setPayTarget] = useState(null);
  const [expensing, setExpensing] = useState(false);
  const [payExpenseTarget, setPayExpenseTarget] = useState(null);

  const pendingPurchases = (ctx.state.inputPurchases || []).filter(p => p.paid < p.total).length;
  const pendingExpenses  = (ctx.state.expenses || []).filter(e => e.paid < e.total).length;

  return (
    <>
      <div className="page-head">
        <div>
          <h1>Fabricação</h1>
          <p>Insumos, receitas, produção e gastos da fábrica</p>
        </div>
        <div className="page-head__actions">
          {sub === "insumos" && (
            <>
              <BuyInputButton ctx={ctx} onBuy={() => setPurchasing(true)} />
              <Button variant="secondary" icon={<Icons.Plus size={14} strokeWidth={2.2}/>} onClick={() => setEditingInput("new")}>Novo insumo</Button>
            </>
          )}
          {sub === "receitas" && <Button variant="primary" icon={<Icons.Plus size={14} strokeWidth={2.2}/>} onClick={() => setEditingRecipe("new")} disabled={ctx.state.products.length === 0 || ctx.state.inputs.length === 0}>Nova receita</Button>}
          {sub === "producao" && <Button variant="primary" icon={<Icons.Factory size={14}/>} onClick={() => setProducing(ctx.state.recipes[0])} disabled={ctx.state.recipes.length === 0}>Registrar produção</Button>}
          {sub === "gastos" && <Button variant="primary" icon={<Icons.Plus size={14}/>} onClick={() => setExpensing(true)}>Novo gasto</Button>}
        </div>
      </div>

      <Tabs
        items={[
          { value:"insumos",     label:`Insumos · ${ctx.state.inputs.length}` },
          { value:"receitas",    label:`Receitas · ${ctx.state.recipes.length}` },
          { value:"producao",    label:"Produção" },
          { value:"gastos",      label:`Gastos extras${(ctx.state.expenses||[]).length ? " · "+(ctx.state.expenses||[]).length : ""}` },
          { value:"pendencias",  label:`Pendências${(pendingPurchases + pendingExpenses) ? " · "+(pendingPurchases + pendingExpenses) : ""}` },
        ]}
        value={sub}
        onChange={setSub}
      />

      {sub === "insumos"    && <InsumosTab ctx={ctx} onEdit={setEditingInput} onBuy={() => setPurchasing(true)} />}
      {sub === "receitas"   && <ReceitasTab ctx={ctx} onEdit={setEditingRecipe} onProduce={setProducing} />}
      {sub === "producao"   && <ProducaoTab ctx={ctx} />}
      {sub === "gastos"     && <GastosTab ctx={ctx} onNewExpense={() => setExpensing(true)} />}
      {sub === "pendencias" && <PendenciasInsumos ctx={ctx} onPay={setPayTarget} onPayExpense={setPayExpenseTarget} />}

      {editingInput && (
        <InsumoModal
          initial={editingInput === "new" ? null : editingInput}
          onClose={() => setEditingInput(null)}
          onSave={(v) => {
            if (editingInput === "new") ctx.actions.addInput(v);
            else ctx.actions.updateInput(editingInput.id, v);
            setEditingInput(null);
          }}
        />
      )}
      {editingRecipe && (
        <ReceitaModal
          ctx={ctx}
          initial={editingRecipe === "new" ? null : editingRecipe}
          onClose={() => setEditingRecipe(null)}
          onSave={(v) => {
            if (editingRecipe === "new") ctx.actions.addRecipe(v);
            else ctx.actions.updateRecipe(editingRecipe.id, v);
            setEditingRecipe(null);
          }}
        />
      )}
      {producing && (
        <ProduzirModal
          ctx={ctx}
          recipe={producing}
          onClose={() => setProducing(null)}
          onConfirm={(batches, warehouseId) => { ctx.actions.recordProduction({ recipeId: producing.id, batches, warehouseId }); setProducing(null); }}
        />
      )}

      {purchasing && (
        <ComprarInsumoModal
          ctx={ctx}
          onClose={() => setPurchasing(false)}
          onConfirm={(payload) => { ctx.actions.recordInputPurchase(payload); setPurchasing(false); }}
        />
      )}

      {payTarget && (
        <PayPurchaseModal
          purchase={payTarget}
          methods={ctx.state.settings.methods}
          onClose={() => setPayTarget(null)}
          onConfirm={(payload) => { ctx.actions.payInputPurchase({ purchaseId: payTarget.id, ...payload }); setPayTarget(null); }}
        />
      )}

      {expensing && (
        <NovoGastoModal
          onClose={() => setExpensing(false)}
          onConfirm={(payload) => { ctx.actions.recordExpense(payload); setExpensing(false); }}
        />
      )}

      {payExpenseTarget && (
        <PayExpenseModal
          expense={payExpenseTarget}
          methods={ctx.state.settings.methods}
          onClose={() => setPayExpenseTarget(null)}
          onConfirm={(payload) => { ctx.actions.payExpense({ expenseId: payExpenseTarget.id, ...payload }); setPayExpenseTarget(null); }}
        />
      )}
    </>
  );
}

/* CTA destacado: "Comprar insumo" — mais visível que um botão neutro,
   mostra também pendências de compras a pagar para incentivar o reabastecimento. */
function BuyInputButton({ ctx, onBuy }) {
  const inputs = ctx.state.inputs || [];
  const critical = inputs.filter(i => i.stock < i.min).length;
  const pendingPurchases = (ctx.state.inputPurchases || []).filter(p => p.paid < p.total).length;
  const disabled = inputs.length === 0;
  return (
    <button
      onClick={onBuy}
      disabled={disabled}
      className="buy-input-cta"
      title="Registrar uma compra de insumos com forma de pagamento"
      style={{
        display:"inline-flex", alignItems:"center", gap:10,
        padding:"8px 14px 8px 10px",
        border:"1px solid var(--brand-600)",
        background: disabled ? "var(--ink-100)" : "linear-gradient(135deg, var(--brand-600) 0%, var(--brand-700, #B3270A) 100%)",
        color: disabled ? "var(--ink-400)" : "white",
        borderRadius: 10,
        fontWeight: 700,
        fontSize: 13,
        cursor: disabled ? "not-allowed" : "pointer",
        boxShadow: disabled ? "none" : "0 2px 8px rgba(212, 49, 11, 0.25)",
        transition: "transform .1s, box-shadow .15s",
        fontFamily: "inherit",
      }}
      onMouseEnter={e => { if (!disabled) e.currentTarget.style.transform = "translateY(-1px)"; }}
      onMouseLeave={e => { e.currentTarget.style.transform = "translateY(0)"; }}
    >
      <span style={{
        width: 28, height: 28, borderRadius: 7,
        background: disabled ? "transparent" : "rgba(255,255,255,0.18)",
        display:"flex", alignItems:"center", justifyContent:"center",
      }}>
        <Icons.Receipt size={15} strokeWidth={2.4} />
      </span>
      <span style={{ display:"flex", flexDirection:"column", alignItems:"flex-start", lineHeight: 1.15 }}>
        <span>Comprar insumo</span>
        <span style={{ fontSize: 10.5, fontWeight: 500, opacity: 0.9, letterSpacing: ".02em" }}>
          {critical > 0
            ? `${critical} item(s) abaixo do mínimo`
            : pendingPurchases > 0
              ? `${pendingPurchases} compra(s) a pagar`
              : "À vista, parcelado ou fiado"}
        </span>
      </span>
    </button>
  );
}

function InsumosTab({ ctx, onEdit, onBuy }) {
  const inputs = ctx.state.inputs;
  const total = inputs.reduce((s, i) => s + i.stock * i.unitCost, 0);
  const critical = inputs.filter(i => i.stock < i.min).length;

  const onDelete = (i) => ctx.askConfirm({
    title: "Excluir insumo?",
    message: `Excluir "${i.name}"?`,
    detail: "Receitas que usam este insumo precisarão ser ajustadas.",
    danger: true,
    onConfirm: () => ctx.actions.deleteInput(i.id),
  });

  return (
    <>
      <div className="grid-3" style={{ marginBottom: 14 }}>
        <KPI tone="info" medal={<Icons.Box size={18} strokeWidth={2}/>} label="Itens em estoque" value={fmtInt(inputs.length)} sub="Em diferentes unidades" />
        <KPI tone="success" medal={<Icons.Wallet size={18} strokeWidth={2}/>} label="Valor estocado" value={fmtBRL(total)} sub="Custo a preços atuais" />
        <KPI tone="danger" medal={<Icons.AlertTriangle size={18} strokeWidth={2}/>} label="Itens críticos" value={critical + ""} sub="abaixo do mínimo" />
      </div>

      <Card title="Insumos cadastrados" subtitle={`${inputs.length} itens · use "Comprar insumo" para reabastecer com forma de pagamento`} flush
        action={inputs.length > 0 ? <BuyInputButton ctx={ctx} onBuy={onBuy} /> : null}
      >
        {inputs.length === 0 ? (
          <div className="empty">
            <Icons.Box size={26} color="var(--ink-300)"/>
            <h4>Nenhum insumo cadastrado</h4>
            <p>Cadastre matérias-primas para criar receitas e registrar produção.</p>
          </div>
        ) : (
        <table className="tbl">
          <thead>
            <tr>
              <th>Insumo</th>
              <th>Unidade</th>
              <th className="num">Estoque</th>
              <th>Margem</th>
              <th className="num">Custo unit.</th>
              <th className="num">Valor estoque</th>
              <th>Última compra</th>
              <th>Validade</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {inputs.map(i => {
              const ratio = i.min > 0 ? i.stock / i.min : 2;
              const tone = ratio < 1 ? "danger" : (ratio < 1.5 ? "warning" : "ok");
              const lastPurchase = (ctx.state.inputPurchases || [])
                .filter(p => p.items.some(it => it.inputId === i.id))
                .sort((a,b) => b.date.localeCompare(a.date))[0];
              return (
                <tr key={i.id}>
                  <td className="strong">{i.name}</td>
                  <td className="muted">{i.unit}</td>
                  <td className="num strong numeric">{fmtInt(i.stock)} {i.unit}</td>
                  <td style={{ width:160 }}>
                    <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                      <ProgressBar value={Math.min(i.stock, (i.min||1)*2)} max={(i.min||1)*2} tone={tone} />
                      <span className="subtle numeric" style={{ minWidth:46, textAlign:"right" }}>min. {i.min}</span>
                    </div>
                  </td>
                  <td className="num numeric">{fmtBRL(i.unitCost)}</td>
                  <td className="num strong numeric">{fmtBRL(i.unitCost * i.stock)}</td>
                  <td className="muted" style={{ fontSize:12 }}>
                    {lastPurchase ? (
                      <div style={{ display:"flex", flexDirection:"column", gap:1 }}>
                        <span>{fmtDate(lastPurchase.date)}</span>
                        <span style={{ display:"flex", gap:4, alignItems:"center", fontSize:10.5 }}>
                          {paymentChip(lastPurchase.payment)}
                          {lastPurchase.paid < lastPurchase.total && <Chip tone="warning" dot>pendente</Chip>}
                        </span>
                      </div>
                    ) : <span className="subtle">—</span>}
                  </td>
                  <td className="muted">{i.expires ? fmtDate(i.expires) : "—"}</td>
                  <td>
                    <div style={{ display:"flex", gap:2 }}>
                      <button className="icon-btn" title="Editar" onClick={() => onEdit(i)}><Icons.Edit /></button>
                      <button className="icon-btn" title="Excluir" onClick={() => onDelete(i)}><Icons.Trash /></button>
                    </div>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
        )}
      </Card>
    </>
  );
}

function ReceitasTab({ ctx, onEdit, onProduce }) {
  const onDelete = (r) => ctx.askConfirm({
    title: "Excluir receita?",
    message: `Excluir "${r.name}"?`,
    danger: true,
    onConfirm: () => ctx.actions.deleteRecipe(r.id),
  });

  if (ctx.state.recipes.length === 0) {
    return (
      <Card>
        <div className="empty">
          <Icons.Receipt size={26} color="var(--ink-300)"/>
          <h4>Nenhuma receita cadastrada</h4>
          <p>{ctx.state.inputs.length === 0 ? "Cadastre insumos primeiro, depois crie receitas." : "Crie a primeira receita para começar a produzir."}</p>
        </div>
      </Card>
    );
  }

  return (
    <div className="grid-2" style={{ gap: 14 }}>
      {ctx.state.recipes.map(r => {
        const product = ctx.state.products.find(p => p.id === r.productId);
        if (!product) return null;
        const cost = r.items.reduce((s, it) => {
          const inp = ctx.state.inputs.find(x => x.id === it.inputId);
          return s + (inp?.unitCost || 0) * it.qty;
        }, 0);
        const costPerUnit = r.yield > 0 ? cost / r.yield : 0;
        const margin = product.price > 0 ? ((product.price - costPerUnit) / product.price) * 100 : 0;
        return (
          <Card key={r.id} title={r.name} subtitle={`Rendimento ${r.yield} unidades · ${product.line}`}
            action={<Chip tone="brand" dot>{product.flavor}</Chip>}
          >
            <div style={{ display:"flex", flexDirection:"column", gap:8, marginBottom:14 }}>
              {r.items.map(it => {
                const inp = ctx.state.inputs.find(x => x.id === it.inputId);
                const subtotal = (inp?.unitCost || 0) * it.qty;
                return (
                  <div key={it.inputId} style={{ display:"flex", justifyContent:"space-between", padding:"6px 0", borderBottom:"1px dashed var(--line)" }}>
                    <span style={{ fontSize:13 }}>{inp?.name || <em className="muted">insumo removido</em>}</span>
                    <span style={{ display:"flex", gap:18, alignItems:"baseline" }}>
                      <span className="muted numeric">{it.qty} {inp?.unit || ""}</span>
                      <strong className="numeric" style={{ fontSize:12.5, minWidth: 75, textAlign:"right" }}>{fmtBRL(subtotal)}</strong>
                    </span>
                  </div>
                );
              })}
            </div>
            <div className="pill-row" style={{ paddingTop:8, borderTop:"1px solid var(--line)" }}>
              <div className="pm"><strong>{fmtBRL(cost)}</strong><span>Custo da batelada</span></div>
              <div className="pm"><strong>{fmtBRL(costPerUnit)}</strong><span>Custo por unidade</span></div>
              <div className="pm"><strong style={{ color: margin > 50 ? "var(--success)" : "var(--warning)" }}>{margin.toFixed(0)}%</strong><span>Margem bruta</span></div>
            </div>
            <div style={{ display:"flex", gap:8, marginTop:14 }}>
              <Button variant="primary" icon={<Icons.Factory size={14}/>} onClick={() => onProduce(r)}>Produzir</Button>
              <Button variant="secondary" icon={<Icons.Edit size={14}/>} onClick={() => onEdit(r)}>Editar</Button>
              <Button variant="danger" icon={<Icons.Trash size={14}/>} onClick={() => onDelete(r)} />
            </div>
          </Card>
        );
      })}
    </div>
  );
}

function ProducaoTab({ ctx }) {
  // Build history from finance ("Produção" category)
  const history = ctx.state.finance.filter(f => f.cat === "Produção").map((f, i) => ({
    id: f.id, date: f.date, ref: f.ref, value: f.value
  }));

  const today = new Date().toISOString().slice(0,10);
  const todayCost = ctx.state.finance.filter(f => f.cat === "Produção" && f.date === today).reduce((s,x) => s+x.value, 0);

  // Estoque de produtos fabricados (somado em todos os armazéns)
  const stockByProduct = ctx.state.products.map(p => {
    const rows = ctx.state.stock.filter(s => s.productId === p.id);
    return {
      product: p,
      units:   rows.reduce((sm, r) => sm + r.units, 0),
      minUnits: rows.reduce((sm, r) => sm + r.minUnits, 0),
      perBox:  p.boxSize || 60,
    };
  });
  const totalUnitsStock = stockByProduct.reduce((s, x) => s + x.units, 0);
  const criticalProducts = stockByProduct.filter(x => x.units < x.minUnits).length;

  return (
    <>
      <div className="grid-4" style={{ marginBottom: 14 }}>
        <KPI tone="brand" medal={<Icons.Receipt size={18} strokeWidth={2}/>} label="Receitas cadastradas" value={ctx.state.recipes.length+""} sub="Disponíveis para produção" />
        <KPI tone="info" medal={<Icons.Snowflake size={18} strokeWidth={2}/>} label="Unidades em estoque" value={fmtInt(totalUnitsStock)} sub={`${stockByProduct.filter(x => x.units > 0).length} sabor(es) com produção`} />
        <KPI tone="success" medal={<Icons.Factory size={18} strokeWidth={2}/>} label="Produções registradas" value={history.length+""} sub="Histórico completo" />
        <KPI tone="warning" medal={<Icons.ArrowUp size={18} strokeWidth={2}/>} label="Custo da produção hoje" value={fmtBRL(todayCost)} sub="Insumos consumidos" />
      </div>

      <Card title="Estoque atual de produtos fabricados" subtitle={`Atualizado automáticamente a cada produção${criticalProducts ? " · " + criticalProducts + " abaixo do mínimo" : ""}`} flush
        style={{ marginBottom: 14 }}
      >
        <table className="tbl">
          <thead>
            <tr>
              <th>Produto</th>
              <th className="num">Estoque (un)</th>
              <th className="num">Caixas equivalentes</th>
              <th className="num">Preço un.</th>
              <th className="num">Valor estoque</th>
              <th>Status</th>
            </tr>
          </thead>
          <tbody>
            {stockByProduct
              .sort((a, b) => b.units - a.units)
              .map(x => {
                const boxes = Math.floor(x.units / x.perBox);
                const looseRest = x.units % x.perBox;
                const isCritical = x.units < x.minUnits;
                const isEmpty = x.units === 0;
                return (
                  <tr key={x.product.id}>
                    <td>
                      <div style={{ display:"flex", alignItems:"center", gap:8 }}>
                        <span style={{ width:14, height:14, borderRadius:4, background:x.product.color, flexShrink:0 }} />
                        <div>
                          <div style={{ fontWeight:600, color:"var(--ink-900)" }}>{x.product.flavor}</div>
                          <div className="subtle" style={{ fontSize:11 }}>{x.product.line}</div>
                        </div>
                      </div>
                    </td>
                    <td className="num strong numeric" style={{ color: isEmpty ? "var(--ink-400)" : (isCritical ? "var(--warning)" : "var(--ink-900)") }}>{fmtInt(x.units)}</td>
                    <td className="num muted" style={{ fontSize:12 }}>{boxes} cx{looseRest > 0 ? ` + ${looseRest} un` : ""} <span className="subtle" style={{ fontSize:10 }}>({x.perBox}/cx)</span></td>
                    <td className="num numeric">{fmtBRL(x.product.price)}</td>
                    <td className="num strong numeric">{fmtBRL(x.units * x.product.price)}</td>
                    <td>
                      {isEmpty
                        ? <Chip tone="danger" dot>esgotado</Chip>
                        : isCritical
                          ? <Chip tone="warning" dot>crítico</Chip>
                          : <Chip tone="success" dot>ok</Chip>}
                    </td>
                  </tr>
                );
              })}
          </tbody>
        </table>
      </Card>

      <Card title="Histórico de produção" subtitle="Cada produção consome insumos e adiciona unidades ao estoque do produto correspondente." flush>
        {history.length === 0 ? (
          <div className="empty">
            <Icons.Factory size={26} color="var(--ink-300)"/>
            <h4>Nenhuma produção registrada</h4>
            <p>Use o botão "Produzir" em uma receita para registrar a primeira produção.</p>
          </div>
        ) : (
        <table className="tbl">
          <thead>
            <tr>
              <th>Lote</th>
              <th>Data</th>
              <th>Receita / Lote</th>
              <th className="num">Custo</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {history.map(h => (
              <tr key={h.id}>
                <td className="mono muted">{h.id}</td>
                <td>{fmtDate(h.date)}</td>
                <td className="strong">{h.ref}</td>
                <td className="num strong numeric">{fmtBRL(h.value)}</td>
                <td><Chip tone="success" dot>concluída</Chip></td>
              </tr>
            ))}
          </tbody>
        </table>
        )}
      </Card>
    </>
  );
}

function InsumoModal({ initial, onClose, onSave }) {
  const [name, setName] = useState(initial?.name || "");
  const [stock, setStock] = useState(initial?.stock != null ? String(initial.stock) : "");
  const [unit, setUnit] = useState(initial?.unit || "kg");
  const [cost, setCost] = useState(initial?.unitCost != null ? String(initial.unitCost) : "");
  const [min, setMin] = useState(initial?.min != null ? String(initial.min) : "");
  const [expires, setExpires] = useState(initial?.expires || "");
  const [err, setErr] = useState({});

  const submit = () => {
    const e = {};
    if (!name.trim()) e.name = "Informe o nome";
    if (!stock || isNaN(parseFloat(stock))) e.stock = "Quantidade inválida";
    if (!cost || isNaN(parseFloat(cost))) e.cost = "Custo inválido";
    setErr(e);
    if (Object.keys(e).length) return;
    onSave({
      name: name.trim(), stock: parseFloat(stock), unit,
      unitCost: parseFloat(cost), min: parseFloat(min || 0), expires
    });
  };

  return (
    <Modal title={initial ? "Editar insumo" : "Novo insumo"} subtitle={initial?.name || "Cadastrar nova matéria-prima"} onClose={onClose}
      footer={<><Button variant="ghost" onClick={onClose}>Cancelar</Button><Button variant="primary" onClick={submit}>{initial ? "Salvar alterações" : "Salvar insumo"}</Button></>}
    >
      <div className="grid-2" style={{ gap: 14 }}>
        <Field label="Nome do insumo" required error={err.name} style={{ gridColumn:"span 2" }}>
          <input className="input" placeholder="Ex.: Polpa de morango" value={name} onChange={e => setName(e.target.value)} autoFocus />
        </Field>
        <Field label={initial ? "Quantidade em estoque" : "Quantidade inicial"} required error={err.stock}>
          <input className="input numeric" placeholder="0" value={stock} onChange={e => setStock(e.target.value.replace(/[^\d.,]/g,"").replace(",","."))} />
        </Field>
        <Field label="Unidade de medida" required>
          <select className="select" value={unit} onChange={e => setUnit(e.target.value)}>
            <option>kg</option><option>L</option><option>un</option><option>g</option><option>ml</option>
          </select>
        </Field>
        <Field label="Custo unitário (R$)" required error={err.cost}>
          <input className="input numeric" placeholder="0,00" value={cost} onChange={e => setCost(e.target.value.replace(/[^\d.,]/g,"").replace(",","."))} />
        </Field>
        <Field label="Estoque mínimo">
          <input className="input numeric" placeholder="0" value={min} onChange={e => setMin(e.target.value.replace(/[^\d.,]/g,"").replace(",","."))} />
        </Field>
        <Field label="Validade do lote" style={{ gridColumn:"span 2" }} hint="AAAA-MM-DD (opcional)">
          <input className="input" placeholder="2026-12-31" value={expires} onChange={e => setExpires(e.target.value)} />
        </Field>
      </div>
    </Modal>
  );
}

function ReceitaModal({ ctx, initial, onClose, onSave }) {
  const [name, setName] = useState(initial?.name || "");
  const [productId, setProductId] = useState(initial?.productId || ctx.state.products[0]?.id || "");
  const [yld, setYld] = useState(initial?.yield != null ? String(initial.yield) : "60");
  const [items, setItems] = useState(initial?.items || []);
  const [err, setErr] = useState({});

  const addRow = () => setItems([...items, { inputId: ctx.state.inputs[0]?.id || "", qty: 1 }]);
  const setRow = (i, patch) => setItems(items.map((x, idx) => idx === i ? { ...x, ...patch } : x));
  const delRow = (i) => setItems(items.filter((_, idx) => idx !== i));

  const submit = () => {
    const e = {};
    if (!name.trim()) e.name = "Informe o nome";
    if (!productId) e.productId = "Selecione o sabor";
    if (!yld || isNaN(parseInt(yld, 10))) e.yld = "Rendimento inválido";
    if (items.length === 0) e.items = "Adicione ao menos um insumo";
    setErr(e);
    if (Object.keys(e).length) return;
    onSave({ name: name.trim(), productId, yield: parseInt(yld, 10), items });
  };

  return (
    <Modal title={initial ? "Editar receita" : "Nova receita"} size="lg" onClose={onClose}
      footer={<><Button variant="ghost" onClick={onClose}>Cancelar</Button><Button variant="primary" onClick={submit}>{initial ? "Salvar alterações" : "Criar receita"}</Button></>}
    >
      <div className="grid-2" style={{ gap:14, marginBottom:18 }}>
        <Field label="Nome da receita" required error={err.name} style={{ gridColumn:"span 2" }}>
          <input className="input" value={name} onChange={e => setName(e.target.value)} placeholder="Ex.: Picolé de Morango — base 60u" autoFocus />
        </Field>
        <Field label="Produto resultante" required error={err.productId}>
          <select className="select" value={productId} onChange={e => setProductId(e.target.value)}>
            {ctx.state.products.map(p => <option key={p.id} value={p.id}>{p.line} — {p.flavor}</option>)}
          </select>
        </Field>
        <Field label="Rendimento (unidades)" required error={err.yld}>
          <input className="input numeric" value={yld} onChange={e => setYld(e.target.value.replace(/\D/g,""))} />
        </Field>
      </div>

      <SectionHead title="Insumos da receita" subtitle={err.items} action={<Button variant="secondary" size="sm" icon={<Icons.Plus size={12}/>} onClick={addRow}>Adicionar insumo</Button>} />
      {items.length === 0 ? (
        <div className="empty" style={{ border:"1px dashed var(--line-strong)", borderRadius:10 }}>
          <p>Nenhum insumo. Clique em "Adicionar insumo".</p>
        </div>
      ) : (
        <div style={{ border:"1px solid var(--line)", borderRadius:10, overflow:"hidden" }}>
          {items.map((row, i) => {
            const inp = ctx.state.inputs.find(x => x.id === row.inputId);
            return (
              <div key={i} style={{ display:"flex", gap:10, padding:10, alignItems:"center", borderBottom:"1px solid var(--line)" }}>
                <select className="select" value={row.inputId} onChange={e => setRow(i, { inputId: e.target.value })} style={{ flex:1 }}>
                  {ctx.state.inputs.map(x => <option key={x.id} value={x.id}>{x.name}</option>)}
                </select>
                <input className="input numeric" value={row.qty} onChange={e => setRow(i, { qty: parseFloat(e.target.value.replace(",", ".")) || 0 })} style={{ width:100 }} />
                <span className="muted" style={{ minWidth:30 }}>{inp?.unit || ""}</span>
                <span className="muted" style={{ minWidth:90, textAlign:"right", fontSize:12 }}>{fmtBRL((inp?.unitCost || 0) * row.qty)}</span>
                <button className="icon-btn" onClick={() => delRow(i)} title="Remover"><Icons.Trash size={14} /></button>
              </div>
            );
          })}
        </div>
      )}
    </Modal>
  );
}

function ProduzirModal({ ctx, recipe, onClose, onConfirm }) {
  const [batches, setBatches] = useState(1);
  const [warehouseId, setWarehouseId] = useState(ctx.state.warehouses[0]?.id || WH_DISTRIB_ID);
  const product = ctx.state.products.find(p => p.id === recipe.productId);
  if (!product) return null;

  const totalCost = recipe.items.reduce((s, it) => {
    const inp = ctx.state.inputs.find(x => x.id === it.inputId);
    return s + (inp?.unitCost || 0) * it.qty;
  }, 0) * batches;
  const units = recipe.yield * batches;
  const insufficient = recipe.items.some(it => {
    const inp = ctx.state.inputs.find(x => x.id === it.inputId);
    return !inp || inp.stock < it.qty * batches;
  });

  return (
    <Modal title="Registrar produção" subtitle={recipe.name} size="lg" onClose={onClose}
      footer={
        <>
          <span className="muted" style={{ fontSize:12.5 }}>Ao confirmar, os insumos serão abatidos do estoque automaticamente.</span>
          <div style={{ display:"flex", gap:8 }}>
            <Button variant="ghost" onClick={onClose}>Cancelar</Button>
            <Button variant="primary" icon={<Icons.Factory size={14}/>} onClick={() => onConfirm(batches, warehouseId)} disabled={insufficient || !warehouseId}>Confirmar produção</Button>
          </div>
        </>
      }
    >
      <div className="grid-2" style={{ gap:18 }}>
        <Card title="Quantidade a produzir" flush>
          <div style={{ padding: 20, display:"flex", flexDirection:"column", gap:14 }}>
            <div style={{ display:"flex", alignItems:"center", gap:14 }}>
              <FlavorTagInline product={product} />
              <span className="subtle">{product.line}</span>
            </div>
            <div className="row" style={{ justifyContent:"space-between" }}>
              <span style={{ fontSize:13 }}>Bateladas</span>
              <Stepper value={batches} onChange={setBatches} min={1} max={20} />
            </div>
            <Field label="Armazém de destino" hint="Para qual armazém esta produção será enviada">
              <select className="select" value={warehouseId} onChange={e => setWarehouseId(e.target.value)}>
                {ctx.state.warehouses.map(w => <option key={w.id} value={w.id}>{w.name}</option>)}
              </select>
            </Field>
            <hr className="divider" />
            <div className="pill-row" style={{ flexDirection:"column", gap: 10 }}>
              <div style={{ display:"flex", justifyContent:"space-between" }}><span className="muted">Unidades produzidas</span><strong className="numeric">{units}</strong></div>
              <div style={{ display:"flex", justifyContent:"space-between" }}><span className="muted">Custo total estimado</span><strong className="numeric">{fmtBRL(totalCost)}</strong></div>
              <div style={{ display:"flex", justifyContent:"space-between" }}><span className="muted">Custo por unidade</span><strong className="numeric">{fmtBRL(totalCost / Math.max(1, units))}</strong></div>
              <div style={{ display:"flex", justifyContent:"space-between" }}><span className="muted">Receita estimada</span><strong className="numeric" style={{ color:"var(--success)" }}>{fmtBRL(product.price * units)}</strong></div>
            </div>
          </div>
        </Card>

        <Card title="Insumos a serem consumidos" flush>
          <div style={{ padding:"4px 0" }}>
            {recipe.items.map(it => {
              const inp = ctx.state.inputs.find(x => x.id === it.inputId);
              if (!inp) return (
                <div key={it.inputId} style={{ padding:"12px 20px", borderBottom:"1px solid var(--line)", color:"var(--danger)", fontSize:12 }}>Insumo não encontrado · receita precisa ser ajustada</div>
              );
              const need = it.qty * batches;
              const ok = inp.stock >= need;
              return (
                <div key={it.inputId} style={{ padding:"12px 20px", borderBottom:"1px solid var(--line)", display:"flex", justifyContent:"space-between", alignItems:"center" }}>
                  <div>
                    <div style={{ fontWeight:600, color:"var(--ink-900)" }}>{inp.name}</div>
                    <div className="subtle">Estoque: {inp.stock} {inp.unit}</div>
                  </div>
                  <div style={{ textAlign:"right" }}>
                    <div className="numeric" style={{ fontWeight:600, color: ok ? "var(--ink-900)" : "var(--danger)" }}>−{need} {inp.unit}</div>
                    {!ok && <div style={{ fontSize:11, color:"var(--danger)" }}>Estoque insuficiente</div>}
                    {ok && <div className="subtle">Sobrará {(inp.stock - need).toFixed(2)} {inp.unit}</div>}
                  </div>
                </div>
              );
            })}
          </div>
        </Card>
      </div>
      {insufficient && (
        <div style={{ marginTop: 12, padding:"10px 14px", background:"var(--danger-bg)", color:"var(--danger)", borderRadius:8, fontSize:12.5, display:"flex", gap:8 }}>
          <Icons.AlertTriangle size={14}/>
          Estoque insuficiente para um ou mais insumos. Reduza as bateladas ou reabasteça antes de produzir.
        </div>
      )}
    </Modal>
  );
}

function FlavorTagInline({ product }) {
  return (
    <span className="tag-flavor">
      <span className="sw" style={{ background: product.color }} />
      {product.flavor}
    </span>
  );
}

window.Fabricacao = Fabricacao;

/* ============ Pendências de compras (fiado / parcial) ============ */
function PendenciasInsumos({ ctx, onPay, onPayExpense }) {
  const pendingPurchases = (ctx.state.inputPurchases || [])
    .filter(p => p.paid < p.total)
    .sort((a,b) => a.date.localeCompare(b.date));
  const pendingExpenses = (ctx.state.expenses || [])
    .filter(e => e.paid < e.total)
    .sort((a,b) => a.date.localeCompare(b.date));
  const totalPendingPurch = pendingPurchases.reduce((s, p) => s + (p.total - p.paid), 0);
  const totalPendingExp = pendingExpenses.reduce((s, e) => s + (e.total - e.paid), 0);
  const totalPending = totalPendingPurch + totalPendingExp;
  const totalPaid = pendingPurchases.reduce((s, p) => s + p.paid, 0) + pendingExpenses.reduce((s, e) => s + e.paid, 0);
  const totalCount = pendingPurchases.length + pendingExpenses.length;

  return (
    <>
      <div className="grid-3" style={{ marginBottom: 14 }}>
        <KPI tone="warning" medal={<Icons.Wallet size={18} strokeWidth={2}/>} label="A pagar (total)" value={fmtBRL(totalPending)} sub={`${totalCount} pendência(s)`} />
        <KPI tone="info" medal={<Icons.ArrowUp size={18} strokeWidth={2}/>} label="Já pago (parciais)" value={fmtBRL(totalPaid)} sub="De compras/gastos em aberto" />
        <KPI tone="brand" medal={<Icons.Receipt size={18} strokeWidth={2}/>} label="Volume com pendência" value={fmtBRL(totalPending + totalPaid)} sub="Valor original" />
      </div>

      {totalCount === 0 ? (
        <Card>
          <div className="empty">
            <Icons.Check size={26} color="var(--ink-300)"/>
            <h4>Nenhuma pendência</h4>
            <p>Todas as compras e gastos estão quitados.</p>
          </div>
        </Card>
      ) : (
      <>
      {pendingPurchases.length > 0 && (
      <Card title="Compras de insumos pendentes" subtitle="Fiadas ou parcialmente pagas — só entram em Movimentações quando quitadas" flush
        style={{ marginBottom: pendingExpenses.length > 0 ? 14 : 0 }}
      >
        <table className="tbl">
          <thead>
            <tr>
              <th>Fornecedor</th>
              <th>Data</th>
              <th>Itens</th>
              <th>Forma original</th>
              <th className="num">Total</th>
              <th className="num">Pago</th>
              <th className="num">Pendente</th>
              <th>Progresso</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {pendingPurchases.map(p => {
              const pendingVal = p.total - p.paid;
              const pct = (p.paid / p.total) * 100;
              return (
                <tr key={p.id}>
                  <td className="strong">{p.supplier}</td>
                  <td>{fmtDate(p.date)}</td>
                  <td className="muted" style={{ fontSize:12, maxWidth:200 }}>
                    {p.items.map(it => {
                      const inp = ctx.state.inputs.find(x => x.id === it.inputId);
                      return `${inp?.name||"?"} ${it.qty}${inp?.unit||""}`;
                    }).join(" · ")}
                  </td>
                  <td>{paymentChip(p.payment)}</td>
                  <td className="num strong numeric">{fmtBRL(p.total)}</td>
                  <td className="num numeric" style={{ color: p.paid > 0 ? "var(--success)" : "var(--ink-400)" }}>{p.paid > 0 ? fmtBRL(p.paid) : "—"}</td>
                  <td className="num strong numeric" style={{ color:"var(--warning)" }}>{fmtBRL(pendingVal)}</td>
                  <td style={{ width: 140 }}>
                    <div style={{ display:"flex", alignItems:"center", gap:6 }}>
                      <ProgressBar value={p.paid} max={p.total} tone={pct >= 100 ? "ok" : pct >= 50 ? "warn" : "danger"} />
                      <span className="subtle numeric" style={{ minWidth:32, textAlign:"right" }}>{Math.round(pct)}%</span>
                    </div>
                  </td>
                  <td>
                    <Button variant="primary" size="sm" icon={<Icons.Wallet size={12}/>} onClick={() => onPay(p)}>Pagar</Button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </Card>
      )}

      {pendingExpenses.length > 0 && (
      <Card title="Gastos extras pendentes" subtitle="Embalagens, manutenção, despesas operacionais fiadas ou parciais" flush>
        <table className="tbl">
          <thead>
            <tr>
              <th>Gasto</th>
              <th>Categoria</th>
              <th>Data</th>
              <th>Forma original</th>
              <th className="num">Total</th>
              <th className="num">Pago</th>
              <th className="num">Pendente</th>
              <th>Progresso</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {pendingExpenses.map(e => {
              const pendingVal = e.total - e.paid;
              const pct = (e.paid / e.total) * 100;
              return (
                <tr key={e.id}>
                  <td className="strong">
                    {e.name}
                    {e.qty ? <div className="subtle" style={{ fontSize:11 }}>{e.qty} {e.unit}</div> : null}
                  </td>
                  <td><Chip>{e.category||"Outros"}</Chip></td>
                  <td>{fmtDate(e.date)}</td>
                  <td>{paymentChip(e.payment)}</td>
                  <td className="num strong numeric">{fmtBRL(e.total)}</td>
                  <td className="num numeric" style={{ color: e.paid > 0 ? "var(--success)" : "var(--ink-400)" }}>{e.paid > 0 ? fmtBRL(e.paid) : "—"}</td>
                  <td className="num strong numeric" style={{ color:"var(--warning)" }}>{fmtBRL(pendingVal)}</td>
                  <td style={{ width: 140 }}>
                    <div style={{ display:"flex", alignItems:"center", gap:6 }}>
                      <ProgressBar value={e.paid} max={e.total} tone={pct >= 100 ? "ok" : pct >= 50 ? "warn" : "danger"} />
                      <span className="subtle numeric" style={{ minWidth:32, textAlign:"right" }}>{Math.round(pct)}%</span>
                    </div>
                  </td>
                  <td>
                    <Button variant="primary" size="sm" icon={<Icons.Wallet size={12}/>} onClick={() => onPayExpense(e)}>Pagar</Button>
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </Card>
      )}
      </>
      )}
    </>
  );
}

/* Visual chip por forma de pagamento (com "Fiado" destacado) */
function paymentChip(payment) {
  if (payment === "Fiado") return <Chip tone="warning" dot>Fiado</Chip>;
  if (payment === "PIX") return <Chip tone="info">PIX</Chip>;
  if (payment === "Dinheiro") return <Chip tone="success">Dinheiro</Chip>;
  if ((payment||"").startsWith("Cartão")) return <Chip tone="brand">{payment}</Chip>;
  if ((payment||"").startsWith("Boleto") || (payment||"").startsWith("Prazo")) return <Chip tone="info">{payment}</Chip>;
  return <Chip>{payment || "—"}</Chip>;
}

/* ============ Modal: Nova compra de insumo ============ */
const PURCHASE_METHODS = ["PIX","Dinheiro","Cartão","Transferência","Boleto 7d","Boleto 14d","Prazo 30d","Fiado"];

function ComprarInsumoModal({ ctx, onClose, onConfirm }) {
  const [supplier, setSupplier] = useState("");
  const [date, setDate] = useState(new Date().toISOString().slice(0,10));
  const [items, setItems] = useState([{ inputId: ctx.state.inputs[0]?.id || "", qty: 1, unitCost: ctx.state.inputs[0]?.unitCost || 0 }]);
  const [payment, setPayment] = useState("PIX");
  const [partialPaid, setPartialPaid] = useState("");
  const [note, setNote] = useState("");
  const [err, setErr] = useState({});

  const total = items.reduce((s, it) => s + (parseFloat(it.qty)||0) * (parseFloat(it.unitCost)||0), 0);

  const addRow = () => setItems(prev => [...prev, { inputId: ctx.state.inputs[0]?.id || "", qty: 1, unitCost: ctx.state.inputs[0]?.unitCost || 0 }]);
  const setRow = (i, patch) => setItems(prev => prev.map((x, idx) => idx === i ? { ...x, ...patch } : x));
  const delRow = (i) => setItems(prev => prev.filter((_, idx) => idx !== i));

  /* Pré-preenche custo unit. ao trocar o insumo */
  const setInput = (i, inputId) => {
    const inp = ctx.state.inputs.find(x => x.id === inputId);
    setRow(i, { inputId, unitCost: inp?.unitCost || 0 });
  };

  const isFiado = payment === "Fiado";
  const isPartial = !isFiado && partialPaid !== "" && parseFloat(partialPaid) < total;
  const paidValue = isFiado
    ? (partialPaid ? parseFloat(partialPaid) : 0)
    : (partialPaid !== "" ? parseFloat(partialPaid) : total);

  const submit = () => {
    const e = {};
    if (!supplier.trim()) e.supplier = "Informe o fornecedor";
    if (items.length === 0) e.items = "Adicione ao menos um item";
    if (items.some(it => !it.inputId || !it.qty || it.qty <= 0)) e.items = "Confira quantidades dos itens";
    if (total <= 0) e.items = "Total inválido";
    if (paidValue < 0 || paidValue > total + 0.001) e.paid = "Valor pago inválido";
    setErr(e);
    if (Object.keys(e).length) return;
    onConfirm({
      supplier: supplier.trim(),
      date,
      items: items.map(it => ({ inputId: it.inputId, qty: parseFloat(it.qty), unitCost: parseFloat(it.unitCost) })),
      payment,
      paid: paidValue,
      note: note.trim(),
    });
  };

  return (
    <Modal title="Nova compra de insumos" subtitle="Insumos entram no estoque imediatamente. Pagamento pode ser à vista, parcial ou fiado." size="lg" onClose={onClose}
      footer={
        <>
          <Button variant="ghost" onClick={onClose}>Cancelar</Button>
          <Button variant="primary" icon={<Icons.Check size={14} strokeWidth={2.2}/>} onClick={submit}>
            Registrar compra · {fmtBRL(total)}
          </Button>
        </>
      }
    >
      <div className="grid-2" style={{ gap:14, marginBottom:14 }}>
        <Field label="Fornecedor" required error={err.supplier}>
          <input className="input" value={supplier} onChange={e => setSupplier(e.target.value)} placeholder="Ex.: Distribuidora Frutas S/A" autoFocus />
        </Field>
        <Field label="Data da compra">
          <input className="input" type="date" value={date} onChange={e => setDate(e.target.value)} />
        </Field>
      </div>

      <SectionHead title="Itens" subtitle={err.items} action={<Button variant="secondary" size="sm" icon={<Icons.Plus size={12}/>} onClick={addRow}>Adicionar item</Button>} />
      {items.length === 0 ? (
        <div className="empty" style={{ border:"1px dashed var(--line-strong)", borderRadius:10 }}>
          <p>Nenhum item. Clique em "Adicionar item".</p>
        </div>
      ) : (
        <div style={{ border:"1px solid var(--line)", borderRadius:10, overflow:"hidden", marginBottom:14 }}>
          <div style={{ display:"grid", gridTemplateColumns:"2.2fr 1fr 1fr 1fr 36px", gap:0, padding:"8px 12px", background:"var(--ink-50)", borderBottom:"1px solid var(--line)", fontSize:10.5, fontWeight:700, textTransform:"uppercase", letterSpacing:".06em", color:"var(--ink-500)" }}>
            <span>Insumo</span><span style={{ textAlign:"right" }}>Qtd.</span><span style={{ textAlign:"right" }}>Custo unit. (R$)</span><span style={{ textAlign:"right" }}>Subtotal</span><span></span>
          </div>
          {items.map((row, i) => {
            const inp = ctx.state.inputs.find(x => x.id === row.inputId);
            const subtotal = (parseFloat(row.qty)||0) * (parseFloat(row.unitCost)||0);
            return (
              <div key={i} style={{ display:"grid", gridTemplateColumns:"2.2fr 1fr 1fr 1fr 36px", gap:8, padding:"8px 12px", alignItems:"center", borderBottom:"1px solid var(--line)" }}>
                <select className="select" value={row.inputId} onChange={e => setInput(i, e.target.value)}>
                  {ctx.state.inputs.map(x => <option key={x.id} value={x.id}>{x.name} ({x.unit})</option>)}
                </select>
                <div style={{ display:"flex", alignItems:"center", gap:4 }}>
                  <input className="input numeric" value={row.qty} onChange={e => setRow(i, { qty: e.target.value.replace(/[^\d.,]/g,"").replace(",", ".") })} style={{ textAlign:"right", padding:"6px 8px" }} />
                  <span className="muted" style={{ fontSize:11, minWidth:20 }}>{inp?.unit||""}</span>
                </div>
                <input className="input numeric" value={row.unitCost} onChange={e => setRow(i, { unitCost: e.target.value.replace(/[^\d.,]/g,"").replace(",", ".") })} style={{ textAlign:"right", padding:"6px 8px" }} />
                <strong className="numeric" style={{ textAlign:"right", fontSize:13 }}>{fmtBRL(subtotal)}</strong>
                <button className="icon-btn" onClick={() => delRow(i)} title="Remover"><Icons.Trash size={13}/></button>
              </div>
            );
          })}
          <div style={{ padding:"10px 14px", background:"var(--canvas)", display:"flex", justifyContent:"space-between", alignItems:"center" }}>
            <span style={{ fontWeight:600, color:"var(--ink-700)" }}>Total da compra</span>
            <strong className="numeric" style={{ fontSize:18, color:"var(--brand-600)", fontFamily:"var(--font-display)" }}>{fmtBRL(total)}</strong>
          </div>
        </div>
      )}

      <SectionHead title="Pagamento" subtitle="Como esta compra foi paga?" />
      <div style={{ display:"grid", gridTemplateColumns:"repeat(4, 1fr)", gap:6, marginBottom:14 }}>
        {PURCHASE_METHODS.map(m => {
          const on = payment === m;
          const isFiadoOpt = m === "Fiado";
          return (
            <button key={m} onClick={() => { setPayment(m); setPartialPaid(""); }}
              style={{
                padding:"8px 10px", borderRadius:8, fontSize:12, fontWeight:600,
                border: "1px solid " + (on ? (isFiadoOpt ? "var(--warning)" : "var(--brand-600)") : "var(--line-strong)"),
                background: on ? (isFiadoOpt ? "var(--warning-bg)" : "var(--brand-50)") : "white",
                color: on ? (isFiadoOpt ? "var(--warning)" : "var(--brand-700)") : "var(--ink-700)",
                cursor:"pointer", display:"inline-flex", justifyContent:"center", gap:5, alignItems:"center"
              }}
            >
              {isFiadoOpt && <Icons.AlertTriangle size={12}/>}
              {m}
            </button>
          );
        })}
      </div>

      <div style={{ display:"grid", gridTemplateColumns:"1fr 1fr", gap:14 }}>
        <Field
          label={isFiado ? "Valor pago agora (opcional)" : "Valor pago (deixe vazio para pagar tudo agora)"}
          error={err.paid}
          hint={isFiado ? "Em fiado, geralmente fica 0 — pagamentos parciais entram depois em Pendências." : `Total: ${fmtBRL(total)}`}
        >
          <input className="input numeric" value={partialPaid} onChange={e => setPartialPaid(e.target.value.replace(/[^\d.,]/g,"").replace(",", "."))} placeholder={isFiado ? "0,00" : fmtBRL(total)} />
        </Field>
        <Field label="Observação (opcional)">
          <input className="input" value={note} onChange={e => setNote(e.target.value)} placeholder="NF, lote, recebimento..." />
        </Field>
      </div>

      <div style={{ marginTop:14, padding:"10px 14px", borderRadius:8,
        background: isFiado ? "var(--warning-bg)" : (isPartial ? "var(--info-bg)" : "var(--success-bg)"),
        color: isFiado ? "var(--warning)" : (isPartial ? "var(--info)" : "var(--success)"),
        fontSize:12, display:"flex", gap:8, alignItems:"flex-start" }}>
        <Icons.AlertTriangle size={13} style={{ marginTop:2, flexShrink:0 }}/>
        <span>
          {isFiado
            ? <>Compra <strong>fiada</strong>: insumos entram no estoque, mas <strong>nada</strong> entra em Movimentações até que pagamentos sejam registrados. Saldo: <strong>{fmtBRL(total - paidValue)}</strong>.</>
            : isPartial
              ? <>Pagamento <strong>parcial</strong>: <strong>{fmtBRL(paidValue)}</strong> entra em Movimentações agora. Saldo de <strong>{fmtBRL(total - paidValue)}</strong> fica em Pendências.</>
              : <>Pagamento <strong>integral</strong>: o valor total ({fmtBRL(total)}) entra em Movimentações como saída confirmada.</>
          }
        </span>
      </div>
    </Modal>
  );
}

/* ============ Modal: Pagar compra fiada ============ */
function PayPurchaseModal({ purchase, methods, onClose, onConfirm }) {
  const pendingVal = purchase.total - purchase.paid;
  const [amount, setAmount] = useState(pendingVal);
  const [method, setMethod] = useState(methods?.[0] || "PIX");
  const [date, setDate] = useState(new Date().toISOString().slice(0,10));
  const [err, setErr] = useState("");

  const submit = () => {
    const v = parseFloat(String(amount).replace(",", "."));
    if (!v || v <= 0) { setErr("Valor inválido"); return; }
    if (v > pendingVal + 0.001) { setErr(`Valor maior que o saldo pendente (${fmtBRL(pendingVal)})`); return; }
    onConfirm({ amount: v, method, date });
  };

  const quickFills = [
    { label: "100% (quitar)", value: pendingVal },
    { label: "50%",           value: Math.round(pendingVal * 0.5 * 100) / 100 },
    { label: "25%",           value: Math.round(pendingVal * 0.25 * 100) / 100 },
  ];

  return (
    <Modal title="Pagar compra de insumo" subtitle={`${purchase.supplier} · saldo de ${fmtBRL(pendingVal)}`} onClose={onClose}
      footer={<><Button variant="ghost" onClick={onClose}>Cancelar</Button><Button variant="primary" icon={<Icons.Check size={14} strokeWidth={2.2}/>} onClick={submit}>Registrar pagamento</Button></>}
    >
      <div style={{ padding:"14px 16px", background:"linear-gradient(180deg, var(--brand-50) 0%, #FFFFFF 100%)", border:"1px solid var(--brand-100)", borderRadius:12, marginBottom:14, display:"flex", gap:14, alignItems:"center", flexWrap:"wrap" }}>
        <div>
          <div className="subtle" style={{ textTransform:"uppercase", letterSpacing:".08em", fontWeight:700, fontSize:10 }}>Total da compra</div>
          <strong className="numeric" style={{ fontSize:18, fontFamily:"var(--font-display)", color:"var(--ink-900)" }}>{fmtBRL(purchase.total)}</strong>
        </div>
        <div>
          <div className="subtle" style={{ textTransform:"uppercase", letterSpacing:".08em", fontWeight:700, fontSize:10 }}>Já pago</div>
          <strong className="numeric" style={{ fontSize:18, fontFamily:"var(--font-display)", color:"var(--success)" }}>{fmtBRL(purchase.paid)}</strong>
        </div>
        <div>
          <div className="subtle" style={{ textTransform:"uppercase", letterSpacing:".08em", fontWeight:700, fontSize:10 }}>Saldo pendente</div>
          <strong className="numeric" style={{ fontSize:18, fontFamily:"var(--font-display)", color:"var(--warning)" }}>{fmtBRL(pendingVal)}</strong>
        </div>
      </div>

      <Field label="Valor a pagar (R$)" required error={err}>
        <input className="input numeric" value={amount} onChange={e => { setErr(""); setAmount(e.target.value.replace(/[^\d.,]/g,"").replace(",", ".")); }} autoFocus style={{ fontSize:20, fontWeight:700, padding:"10px 14px" }} />
      </Field>
      <div style={{ display:"flex", gap:6, marginTop:8 }}>
        {quickFills.map(q => (
          <button key={q.label} onClick={() => { setErr(""); setAmount(q.value); }}
            style={{ padding:"5px 12px", borderRadius:100, fontSize:11.5, fontWeight:600, border:"1px solid var(--line-strong)", background:"white", color:"var(--ink-700)", cursor:"pointer" }}>{q.label}</button>
        ))}
      </div>

      <div className="grid-2" style={{ gap:14, marginTop:14 }}>
        <Field label="Forma de pagamento" required>
          <select className="select" value={method} onChange={e => setMethod(e.target.value)}>
            {(methods || ["PIX","Dinheiro","Cartão","Transferência"]).filter(m => m !== "Fiado").map(m => <option key={m}>{m}</option>)}
          </select>
        </Field>
        <Field label="Data do pagamento">
          <input className="input" type="date" value={date} onChange={e => setDate(e.target.value)} />
        </Field>
      </div>
    </Modal>
  );
}

/* ============ Gastos extras ============ */
const EXPENSE_CATEGORIES = ["Embalagem", "Limpeza", "Manutenção", "Combustível", "Energia / Água", "Aluguel", "Marketing", "Equipamentos", "Outros"];
const EXPENSE_UNITS = ["un", "kg", "g", "L", "ml", "m", "pacote", "caixa", "rolo", "fardo", "saco", "hora", "diária", "serviço"];

function GastosTab({ ctx, onNewExpense }) {
  const expenses = (ctx.state.expenses || []).slice().sort((a,b) => (b.date+b.time).localeCompare(a.date+a.time));
  const totalPaid = expenses.reduce((s, e) => s + e.paid, 0);
  const totalAll  = expenses.reduce((s, e) => s + e.total, 0);
  const totalPending = totalAll - totalPaid;

  /* Agrupado por categoria — visual quick-stat */
  const byCategory = {};
  expenses.forEach(e => {
    if (!byCategory[e.category]) byCategory[e.category] = { count: 0, total: 0 };
    byCategory[e.category].count++;
    byCategory[e.category].total += e.total;
  });

  return (
    <>
      <div className="grid-4" style={{ marginBottom: 14 }}>
        <KPI tone="brand" medal={<Icons.Receipt size={18} strokeWidth={2}/>} label="Gastos lançados" value={expenses.length+""} sub="Embalagens, manutenção, etc." />
        <KPI tone="success" medal={<Icons.Wallet size={18} strokeWidth={2}/>} label="Total pago" value={fmtBRL(totalPaid)} sub={`${fmtBRL(totalAll)} lançado`} />
        <KPI tone="warning" medal={<Icons.AlertTriangle size={18} strokeWidth={2}/>} label="A pagar" value={fmtBRL(totalPending)} sub="Em pendências" />
        <KPI tone="info" medal={<Icons.PieChart size={18} strokeWidth={2}/>} label="Categorias usadas" value={Object.keys(byCategory).length+""} sub={Object.keys(byCategory).slice(0,2).join(", ") || "—"} />
      </div>

      <Card title="Gastos extras da fábrica" subtitle="Compras avulsas que não são insumos (embalagem, manutenção, despesas operacionais)" flush
        action={<Button variant="primary" size="sm" icon={<Icons.Plus size={12}/>} onClick={onNewExpense}>Novo gasto</Button>}
      >
        {expenses.length === 0 ? (
          <div className="empty">
            <Icons.Receipt size={26} color="var(--ink-300)"/>
            <h4>Nenhum gasto registrado</h4>
            <p>Use "Novo gasto" para registrar despesas como embalagens, materiais de limpeza, manutenção, etc. — com forma de pagamento e opção de fiado.</p>
          </div>
        ) : (
        <table className="tbl">
          <thead>
            <tr>
              <th>Gasto</th>
              <th>Categoria</th>
              <th>Qtd.</th>
              <th>Data</th>
              <th>Pagamento</th>
              <th className="num">Total</th>
              <th className="num">Pago</th>
              <th>Status</th>
            </tr>
          </thead>
          <tbody>
            {expenses.map(e => (
              <tr key={e.id}>
                <td>
                  <div style={{ fontWeight:600, color:"var(--ink-900)" }}>{e.name}</div>
                  {e.note && <div className="subtle" style={{ fontSize:11 }}>{e.note}</div>}
                </td>
                <td><Chip>{e.category || "Outros"}</Chip></td>
                <td className="muted" style={{ fontSize:12 }}>{e.qty ? `${e.qty} ${e.unit||"un"}` : "—"}</td>
                <td>
                  {fmtDate(e.date)}
                  {e.time && <div className="subtle">{e.time}</div>}
                </td>
                <td>{paymentChip(e.payment)}</td>
                <td className="num strong numeric">{fmtBRL(e.total)}</td>
                <td className="num numeric" style={{ color: e.paid >= e.total ? "var(--success)" : (e.paid > 0 ? "var(--info)" : "var(--ink-400)") }}>{e.paid > 0 ? fmtBRL(e.paid) : "—"}</td>
                <td>
                  {e.status === "confirmado" ? <Chip tone="success" dot>quitado</Chip>
                    : e.status === "parcial" ? <Chip tone="info" dot>parcial</Chip>
                    : <Chip tone="warning" dot>a pagar</Chip>}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        )}
      </Card>
    </>
  );
}

function NovoGastoModal({ onClose, onConfirm }) {
  const [name, setName] = useState("");
  const [category, setCategory] = useState(EXPENSE_CATEGORIES[0]);
  const [qty, setQty] = useState("1");
  const [unit, setUnit] = useState("un");
  const [unitMode, setUnitMode] = useState("preset"); // "preset" | "custom"
  const [customUnit, setCustomUnit] = useState("");
  const [total, setTotal] = useState("");
  const [date, setDate] = useState(new Date().toISOString().slice(0,10));
  const [payment, setPayment] = useState("PIX");
  const [partialPaid, setPartialPaid] = useState("");
  const [note, setNote] = useState("");
  const [err, setErr] = useState({});

  const finalUnit = unitMode === "custom" ? (customUnit || "un") : unit;
  const totalNum = parseFloat(String(total).replace(/[^\d.,]/g, "").replace(",", ".")) || 0;
  const isFiado = payment === "Fiado";
  const isPartial = !isFiado && partialPaid !== "" && parseFloat(partialPaid) < totalNum;
  const paidValue = isFiado
    ? (partialPaid ? parseFloat(partialPaid) : 0)
    : (partialPaid !== "" ? parseFloat(partialPaid) : totalNum);

  const submit = () => {
    const e = {};
    if (!name.trim()) e.name = "Informe o nome do gasto";
    if (totalNum <= 0) e.total = "Total inválido";
    if (paidValue < 0 || paidValue > totalNum + 0.001) e.paid = "Valor pago inválido";
    setErr(e);
    if (Object.keys(e).length) return;
    onConfirm({
      name: name.trim(),
      category,
      qty: parseFloat(qty) || 0,
      unit: finalUnit,
      total: totalNum,
      date,
      payment,
      paid: paidValue,
      note: note.trim(),
    });
  };

  return (
    <Modal title="Novo gasto da fábrica" subtitle="Embalagens, manutenção, materiais — qualquer despesa que não seja insumo de receita" size="lg" onClose={onClose}
      footer={<><Button variant="ghost" onClick={onClose}>Cancelar</Button><Button variant="primary" icon={<Icons.Check size={14} strokeWidth={2.2}/>} onClick={submit}>Registrar · {fmtBRL(totalNum)}</Button></>}
    >
      <div className="grid-2" style={{ gap:14, marginBottom:14 }}>
        <Field label="Nome do gasto / produto" required error={err.name} style={{ gridColumn:"span 2" }}>
          <input className="input" value={name} onChange={e => setName(e.target.value)} placeholder="Ex.: Embalagem para picolé, Tinta para impressora, Conta de água..." autoFocus />
        </Field>
        <Field label="Categoria" required>
          <select className="select" value={category} onChange={e => setCategory(e.target.value)}>
            {EXPENSE_CATEGORIES.map(c => <option key={c}>{c}</option>)}
          </select>
        </Field>
        <Field label="Data">
          <input className="input" type="date" value={date} onChange={e => setDate(e.target.value)} />
        </Field>
      </div>

      <SectionHead title="Quantidade e unidade de medida" subtitle="Quanto está sendo comprado e em que medida" />
      <div style={{ display:"grid", gridTemplateColumns:"1fr 2fr", gap:14, marginBottom:14 }}>
        <Field label="Quantidade">
          <input className="input numeric" value={qty} onChange={e => setQty(e.target.value.replace(/[^\d.,]/g,"").replace(",","."))} placeholder="Ex.: 100" />
        </Field>
        <Field label="Unidade de medida">
          <div style={{ display:"flex", flexDirection:"column", gap:6 }}>
            <Segmented options={[{value:"preset", label:"Comum"}, {value:"custom", label:"Personalizada"}]} value={unitMode} onChange={setUnitMode} />
            {unitMode === "preset" ? (
              <div style={{ display:"flex", flexWrap:"wrap", gap:4 }}>
                {EXPENSE_UNITS.map(u => (
                  <button key={u} type="button" onClick={() => setUnit(u)}
                    style={{
                      padding:"5px 10px", borderRadius:100, fontSize:11.5, fontWeight:600,
                      border:"1px solid " + (unit === u ? "var(--brand-600)" : "var(--line-strong)"),
                      background: unit === u ? "var(--brand-50)" : "white",
                      color: unit === u ? "var(--brand-700)" : "var(--ink-700)",
                      cursor:"pointer"
                    }}>{u}</button>
                ))}
              </div>
            ) : (
              <input className="input" value={customUnit} onChange={e => setCustomUnit(e.target.value)} placeholder="Ex.: cartela, conjunto, kit..." />
            )}
          </div>
        </Field>
      </div>

      <Field label="Valor total (R$)" required error={err.total}>
        <input className="input numeric" value={total} onChange={e => setTotal(e.target.value.replace(/[^\d.,]/g,""))} placeholder="0,00"
          style={{ fontSize:20, fontWeight:700, padding:"10px 14px" }} />
      </Field>

      <SectionHead title="Forma de pagamento" subtitle="Como esse gasto foi pago?" />
      <div style={{ display:"grid", gridTemplateColumns:"repeat(4, 1fr)", gap:6, marginBottom:14 }}>
        {PURCHASE_METHODS.map(m => {
          const on = payment === m;
          const isFiadoOpt = m === "Fiado";
          return (
            <button key={m} onClick={() => { setPayment(m); setPartialPaid(""); }}
              style={{
                padding:"8px 10px", borderRadius:8, fontSize:12, fontWeight:600,
                border: "1px solid " + (on ? (isFiadoOpt ? "var(--warning)" : "var(--brand-600)") : "var(--line-strong)"),
                background: on ? (isFiadoOpt ? "var(--warning-bg)" : "var(--brand-50)") : "white",
                color: on ? (isFiadoOpt ? "var(--warning)" : "var(--brand-700)") : "var(--ink-700)",
                cursor:"pointer", display:"inline-flex", justifyContent:"center", gap:5, alignItems:"center"
              }}
            >
              {isFiadoOpt && <Icons.AlertTriangle size={12}/>}
              {m}
            </button>
          );
        })}
      </div>

      <div className="grid-2" style={{ gap:14 }}>
        <Field
          label={isFiado ? "Valor pago agora (opcional)" : "Valor pago (vazio = pagou tudo)"}
          error={err.paid}
          hint={isFiado ? "Em fiado, geralmente fica 0." : `Total: ${fmtBRL(totalNum)}`}
        >
          <input className="input numeric" value={partialPaid} onChange={e => setPartialPaid(e.target.value.replace(/[^\d.,]/g,"").replace(",","."))} placeholder={isFiado ? "0,00" : fmtBRL(totalNum)} />
        </Field>
        <Field label="Observação (opcional)">
          <input className="input" value={note} onChange={e => setNote(e.target.value)} placeholder="NF, fornecedor, motivo..." />
        </Field>
      </div>

      <div style={{ marginTop:14, padding:"10px 14px", borderRadius:8,
        background: isFiado ? "var(--warning-bg)" : (isPartial ? "var(--info-bg)" : "var(--success-bg)"),
        color: isFiado ? "var(--warning)" : (isPartial ? "var(--info)" : "var(--success)"),
        fontSize:12, display:"flex", gap:8, alignItems:"flex-start" }}>
        <Icons.AlertTriangle size={13} style={{ marginTop:2, flexShrink:0 }}/>
        <span>
          {isFiado
            ? <>Gasto <strong>fiado</strong>: <strong>nada</strong> entra em Movimentações até registrar pagamentos. Saldo: <strong>{fmtBRL(totalNum - paidValue)}</strong>.</>
            : isPartial
              ? <>Pagamento <strong>parcial</strong>: <strong>{fmtBRL(paidValue)}</strong> entra em Movimentações agora. Saldo <strong>{fmtBRL(totalNum - paidValue)}</strong> em Pendências.</>
              : <>Pagamento <strong>integral</strong>: o valor total ({fmtBRL(totalNum)}) entra em Movimentações como saída confirmada.</>
          }
        </span>
      </div>
    </Modal>
  );
}

function PayExpenseModal({ expense, methods, onClose, onConfirm }) {
  const pendingVal = expense.total - expense.paid;
  const [amount, setAmount] = useState(pendingVal);
  const [method, setMethod] = useState(methods?.[0] || "PIX");
  const [date, setDate] = useState(new Date().toISOString().slice(0,10));
  const [err, setErr] = useState("");

  const submit = () => {
    const v = parseFloat(String(amount).replace(",", "."));
    if (!v || v <= 0) { setErr("Valor inválido"); return; }
    if (v > pendingVal + 0.001) { setErr(`Valor maior que o saldo pendente (${fmtBRL(pendingVal)})`); return; }
    onConfirm({ amount: v, method, date });
  };

  const quickFills = [
    { label: "100% (quitar)", value: pendingVal },
    { label: "50%",           value: Math.round(pendingVal * 0.5 * 100) / 100 },
    { label: "25%",           value: Math.round(pendingVal * 0.25 * 100) / 100 },
  ];

  return (
    <Modal title="Pagar gasto" subtitle={`${expense.name} · saldo de ${fmtBRL(pendingVal)}`} onClose={onClose}
      footer={<><Button variant="ghost" onClick={onClose}>Cancelar</Button><Button variant="primary" icon={<Icons.Check size={14} strokeWidth={2.2}/>} onClick={submit}>Registrar pagamento</Button></>}
    >
      <div style={{ padding:"14px 16px", background:"linear-gradient(180deg, var(--brand-50) 0%, #FFFFFF 100%)", border:"1px solid var(--brand-100)", borderRadius:12, marginBottom:14, display:"flex", gap:14, alignItems:"center", flexWrap:"wrap" }}>
        <div>
          <div className="subtle" style={{ textTransform:"uppercase", letterSpacing:".08em", fontWeight:700, fontSize:10 }}>Total</div>
          <strong className="numeric" style={{ fontSize:18, fontFamily:"var(--font-display)", color:"var(--ink-900)" }}>{fmtBRL(expense.total)}</strong>
        </div>
        <div>
          <div className="subtle" style={{ textTransform:"uppercase", letterSpacing:".08em", fontWeight:700, fontSize:10 }}>Já pago</div>
          <strong className="numeric" style={{ fontSize:18, fontFamily:"var(--font-display)", color:"var(--success)" }}>{fmtBRL(expense.paid)}</strong>
        </div>
        <div>
          <div className="subtle" style={{ textTransform:"uppercase", letterSpacing:".08em", fontWeight:700, fontSize:10 }}>Saldo</div>
          <strong className="numeric" style={{ fontSize:18, fontFamily:"var(--font-display)", color:"var(--warning)" }}>{fmtBRL(pendingVal)}</strong>
        </div>
      </div>

      <Field label="Valor a pagar (R$)" required error={err}>
        <input className="input numeric" value={amount} onChange={e => { setErr(""); setAmount(e.target.value.replace(/[^\d.,]/g,"").replace(",","."));}} autoFocus style={{ fontSize:20, fontWeight:700, padding:"10px 14px" }} />
      </Field>
      <div style={{ display:"flex", gap:6, marginTop:8 }}>
        {quickFills.map(q => (
          <button key={q.label} onClick={() => { setErr(""); setAmount(q.value); }}
            style={{ padding:"5px 12px", borderRadius:100, fontSize:11.5, fontWeight:600, border:"1px solid var(--line-strong)", background:"white", color:"var(--ink-700)", cursor:"pointer" }}>{q.label}</button>
        ))}
      </div>

      <div className="grid-2" style={{ gap:14, marginTop:14 }}>
        <Field label="Forma de pagamento" required>
          <select className="select" value={method} onChange={e => setMethod(e.target.value)}>
            {(methods || ["PIX","Dinheiro","Cartão","Transferência"]).filter(m => m !== "Fiado").map(m => <option key={m}>{m}</option>)}
          </select>
        </Field>
        <Field label="Data do pagamento">
          <input className="input" type="date" value={date} onChange={e => setDate(e.target.value)} />
        </Field>
      </div>
    </Modal>
  );
}