/* global React, Icon, Button, Badge, Card, Drawer, Field, PageHead, SearchableSelect, CategoriaSelect, brl, fmtDate,
          useFornecedoresList, useOrdensProducao, usePedidosCompra, useProdutosList, useEmpresasList,
          DocPrintOverlay, DocCabecalhoEmpresa, DocTitulo, DocParteInfo,
          DocTituloSecao, DocTabelaItens, DocObservacoes, DocTabelaCampos,
          DocCaixaConferencia, DocAssinatura, NotaEntradaForm,
          ParcelasEditor, useContasBancarias, RemessaOPDrawer, EtiquetaVolumeModal */

// ─── Módulo Estoque · Suprimentos/Produção (Fase 2) ──────────────────────────
// Fornecedores (mínimo) + Ordem de Produção. A OP explode a ficha técnica do
// acabado → insumos a enviar; o ENVIO baixa insumo (Saída, "Em industrialização")
// e o RECEBIMENTO dá entrada no acabado (parcial), calcula o custo real (material
// da ficha + serviço da fábrica rateado por unidade) e — com CONFIRMAÇÃO — atualiza
// produtos.custo (nunca reescreve o snapshot histórico). Ver DESIGN_suprimentos.md.

const FORN_TIPOS = [
  { id: 'fabrica', l: 'Fábrica' }, { id: 'fornecedor', l: 'Fornecedor de insumo' }, { id: 'ambos', l: 'Ambos' },
];
const OP_STATUS = {
  rascunho:    { l: 'Rascunho',     tone: 'neutral' },
  enviada:     { l: 'Enviada',      tone: 'info' },
  em_producao: { l: 'Em produção',  tone: 'warning' },
  recebida:    { l: 'Recebida',     tone: 'success' },
  cancelada:   { l: 'Cancelada',    tone: 'danger' },
};

function gerarNumOP() {
  const p2 = (n) => String(n).padStart(2, '0');
  const d = new Date();
  return `OP-${String(d.getFullYear()).slice(2)}${p2(d.getMonth() + 1)}${p2(d.getDate())}-${p2(d.getHours())}${p2(d.getMinutes())}`;
}
const hojeIso = () => new Date().toISOString().slice(0, 10);

// ── Lógica pura (testável) ───────────────────────────────────────────────────
// Explode itens a produzir × fichas → insumos agregados (ceil no total).
function explodirInsumos(itens, fichasMap) {
  const acc = {};
  (itens || []).forEach(it => {
    const qtd = Number(it.quantidade) || 0;
    if (!it.produtoId || qtd <= 0) return;
    (fichasMap[it.produtoId] || []).forEach(fl => {
      const need = qtd * (Number(fl.quantidade) || 0) * (1 + (Number(fl.perdaPct) || 0) / 100);
      acc[fl.insumoId] = (acc[fl.insumoId] || 0) + need;
    });
  });
  return Object.keys(acc).map(insumoId => ({ insumoId, quantidade: Math.ceil(acc[insumoId] - 1e-9) }));
}
// Custo unitário de um acabado = material da ficha (× custo do insumo) + serviço/unidade.
function custoUnitarioAcabado(fichaA, custoInsumoMap, servicoPerUnit) {
  const material = (fichaA || []).reduce((a, fl) => {
    const c = custoInsumoMap[fl.insumoId] != null ? Number(custoInsumoMap[fl.insumoId]) : 0;
    return a + (Number(fl.quantidade) || 0) * (1 + (Number(fl.perdaPct) || 0) / 100) * c;
  }, 0);
  return Math.round((material + (Number(servicoPerUnit) || 0)) * 10000) / 10000;
}
const somaQtd = (itens) => (itens || []).reduce((a, i) => a + (Number(i.quantidade) || 0), 0);

// ── Aplicação: ENVIO (baixa insumo) ──────────────────────────────────────────
async function enviarOP(ordem, insumos, prodById) {
  const num = ordem.numero;
  const erros = [];
  for (const ins of insumos) {
    const p = prodById[ins.insumoId];
    const q = Number(ins.quantidade) || 0;
    if (!p || q <= 0) continue;
    try {
      await window.tmDb.salvarMovimentacao({
        tipo: 'Saída', motivo: 'Envio p/ industrialização', sku: p.sku, produtoId: ins.insumoId,
        qty: -Math.abs(q), who: 'Produção', nf: num, pedido_ref: num, localizacao: 'Em industrialização',
      }, true);
    } catch (e) { erros.push((p && p.sku) || ins.insumoId); }
    // snapshot do custo do insumo no envio + marca enviado
    await window.tmSupabase.from('ordem_producao_insumos')
      .update({ quantidade_enviada: q, custo_unitario: Number(p.custo) || 0 }).eq('id', ins.id);
  }
  await window.tmSupabase.from('ordens_producao')
    .update({ status: 'enviada', data_envio: hojeIso() }).eq('id', ordem.id);
  return { erros };
}

// ── Aplicação: RECEBIMENTO (entrada acabado + custo) ─────────────────────────
// recebimentos: { [itemId]: qtdRecebidaAgora }. custoPorItem: { [itemId]: custoUnit }.
// aplicarCusto: Set de produtoId cujos produtos.custo devem ser atualizados.
async function receberOP(ordem, itens, recebimentos, custoPorItem, servicoValor, aplicarCusto, prodById) {
  const num = ordem.numero;
  const erros = [];
  for (const it of itens) {
    const qAgora = Number(recebimentos[it.id]) || 0;
    if (qAgora <= 0) continue;
    const p = prodById[it.produtoId];
    const custoUn = Number(custoPorItem[it.id]) || 0;
    if (p) {
      try {
        await window.tmDb.salvarMovimentacao({
          tipo: 'Entrada', motivo: 'Produção recebida', sku: p.sku, produtoId: it.produtoId,
          qty: Math.abs(qAgora), who: 'Produção', nf: num, pedido_ref: num, custoUn: custoUn,
        }, true);
      } catch (e) { erros.push((p && p.sku) || it.produtoId); }
    }
    const novaRecebida = (Number(it.quantidadeRecebida) || 0) + qAgora;
    await window.tmSupabase.from('ordem_producao_itens')
      .update({ quantidade_recebida: novaRecebida, custo_unitario: custoUn }).eq('id', it.id);
    // Atualiza produtos.custo (custo de reposição) — só se confirmado. Nunca mexe no snapshot.
    if (aplicarCusto && aplicarCusto.has(it.produtoId) && p) {
      await window.tmSupabase.from('produtos').update({ custo: custoUn }).eq('id', it.produtoId);
    }
  }
  // Status: recebida se todos os itens completaram; senão em_producao.
  const completou = itens.every(it => ((Number(it.quantidadeRecebida) || 0) + (Number(recebimentos[it.id]) || 0)) >= (Number(it.quantidade) || 0) - 1e-9);
  const patch = { status: completou ? 'recebida' : 'em_producao', servico_valor: Number(servicoValor) || 0 };
  if (completou) patch.data_recebimento = hojeIso();
  await window.tmSupabase.from('ordens_producao').update(patch).eq('id', ordem.id);
  return { erros, completou };
}

// ── Aplicação: CHECK-IN DE RECEBIMENTO DE COMPRA (Fase 2) ────────────────────
// recebimentos: { [itemId]: qtd que chegou BOA agora }
// avarias:      { [itemId]: qtd que chegou QUEBRADA agora }  → NÃO entra no estoque
// precosNota:   { [itemId]: preço unitário da NOTA }         → vale pro custo (fiscal)
// aplicarCusto: Set de insumoId cujo produtos.custo deve ser atualizado.
//
// Regras travadas no DESIGN_compra.md (B e D):
//  · só a quantidade BOA gera Entrada no estoque; avaria fica registrada (histórico
//    do fornecedor: "não veio" ≠ "veio quebrado" — um é entrega, outro é qualidade);
//  · quantidade_recebida acumula → enquanto < pedida, status recebido_parcial;
//  · custo usa o preço da NOTA quando informado (fallback: preço do pedido), e só
//    atualiza produtos.custo se ela confirmar. Nunca reescreve histórico.
async function receberCompra(pedido, itens, recebimentos, avarias, precosNota, aplicarCusto, prodById) {
  const num = pedido.numero;
  const erros = [];
  for (const it of itens) {
    const qAgora  = Number(recebimentos[it.id]) || 0;
    const avAgora = Number(avarias[it.id]) || 0;
    const pnRaw   = precosNota[it.id];
    const precoNota = (pnRaw === '' || pnRaw == null) ? null : Number(pnRaw);
    const custoUn = (precoNota != null && !isNaN(precoNota)) ? precoNota : (Number(it.precoCompra) || 0);
    if (qAgora <= 0 && avAgora <= 0 && precoNota == null) continue;

    const p = prodById[it.insumoId];
    // Entrada só da quantidade BOA — avaria não vira estoque.
    if (qAgora > 0 && p) {
      try {
        await window.tmDb.salvarMovimentacao({
          tipo: 'Entrada', motivo: 'Recebimento de compra', sku: p.sku, produtoId: it.insumoId,
          qty: Math.abs(qAgora), who: 'Compras', nf: pedido.nf_entrada_numero || num,
          pedido_ref: num, custoUn: custoUn,
        }, true);
      } catch (e) { erros.push((p && p.sku) || it.insumoId); }
    }

    const patch = {
      quantidade_recebida: (Number(it.quantidadeRecebida) || 0) + qAgora,
      quantidade_avaria:   (Number(it.quantidadeAvaria)   || 0) + avAgora,
    };
    if (precoNota != null && !isNaN(precoNota)) patch.preco_nota = precoNota;
    await window.tmSupabase.from('pedido_compra_itens').update(patch).eq('id', it.id);

    // produtos.custo = custo de REPOSIÇÃO (o que a próxima OP usa). Só se confirmado.
    // O custo_unitario da Entrada já guardou o histórico desta compra.
    if (aplicarCusto && aplicarCusto.has(it.insumoId) && p) {
      await window.tmSupabase.from('produtos').update({ custo: custoUn }).eq('id', it.insumoId);
    }
  }

  // Avaria NÃO conta como recebida: 10 quebrados de 100 deixam 10 pendentes com o
  // fornecedor (ela vai cobrar/repor), então o pedido segue recebido_parcial.
  const completou = (itens || []).every(it =>
    ((Number(it.quantidadeRecebida) || 0) + (Number(recebimentos[it.id]) || 0)) >= (Number(it.quantidade) || 0) - 1e-9);
  const patch = { status: completou ? 'concluido' : 'recebido_parcial' };
  if (completou) patch.data_recebimento = hojeIso();
  await window.tmSupabase.from('pedidos_compra').update(patch).eq('id', pedido.id);
  return { erros, completou };
}

// ── Motivos de encerramento de pendência (Fase 2b) ───────────────────────────
const PENDENCIA_MOTIVOS = [
  { id: 'nao_reposto',  l: 'Fornecedor não repôs o que faltou' },
  { id: 'cancelado',    l: 'Cancelado com o fornecedor' },
  { id: 'outro',        l: 'Outro motivo' },
];
// Prefixo fixo → a linha fica parseável se um dia virar coluna/relatório.
const PENDENCIA_TAG = '[PENDENCIA ENCERRADA]';

// ── Aplicação: ENCERRAR PENDÊNCIA ────────────────────────────────────────────
// O que faltou NÃO entra no estoque — só para de cobrar. O pedido vai pra
// concluido e o MOTIVO fica registrado em observacoes (histórico do pedido,
// pra avaliar o fornecedor depois). Zero movimento de estoque, de propósito.
async function encerrarPendenciaCompra(pedido, itens, motivoId, nota, prodById) {
  const m = PENDENCIA_MOTIVOS.find(x => x.id === motivoId) || PENDENCIA_MOTIVOS[2];
  const faltas = (itens || []).map(it => {
    const falta = Math.max(0, (Number(it.quantidade) || 0) - (Number(it.quantidadeRecebida) || 0));
    const p = prodById[it.insumoId];
    return falta > 0 ? `${falta} ${(p && p.sku) || 'item'}` : null;
  }).filter(Boolean);

  // Fase 3: o motivo virou COLUNA (dá pra agregar — "quais fornecedores mais
  // deixaram de repor"). O detalhe/faltas continua em texto, junto do motivo.
  const detalhe = [
    faltas.length ? `nao recebido: ${faltas.join(', ')}` : null,
    nota && nota.trim() ? nota.trim() : null,
  ].filter(Boolean).join(' · ');

  await window.tmSupabase.from('pedidos_compra').update({
    status: 'concluido',
    data_recebimento: hojeIso(),
    encerramento_motivo: detalhe ? `${m.l} · ${detalhe}` : m.l,
    encerramento_data: hojeIso(),
  }).eq('id', pedido.id);
  return { motivo: m.l, detalhe };
}

// ── Aplicação: ESTORNO DE RECEBIMENTO ────────────────────────────────────────
// Mesmo padrão do cancelamento do marketplace: movimento de estoque INVERSO e
// AUDITÁVEL (Saída "Estorno de recebimento") — o movimento original NÃO é
// apagado. Devolve a quantidade pra pendente e reabre o status.
// ⚠️ NÃO reverte produtos.custo: o custo atual é "última compra" (reposição),
// não histórico. A tela avisa pra ela decidir se ajusta à mão.
async function estornarRecebimento(pedido, itens, estornos, estornosAvaria, prodById) {
  const num = pedido.numero;
  const erros = [];
  for (const it of itens) {
    const qEst  = Number(estornos[it.id]) || 0;
    const avEst = Number(estornosAvaria[it.id]) || 0;
    if (qEst <= 0 && avEst <= 0) continue;

    const p = prodById[it.insumoId];
    // Só a quantidade BOA saiu do estoque na entrada, então só ela volta.
    if (qEst > 0 && p) {
      const custoUn = it.precoNota != null ? Number(it.precoNota) : (Number(it.precoCompra) || 0);
      try {
        await window.tmDb.salvarMovimentacao({
          tipo: 'Saída', motivo: 'Estorno de recebimento', sku: p.sku, produtoId: it.insumoId,
          qty: -Math.abs(qEst), who: 'Compras', nf: num, pedido_ref: num, custoUn: custoUn,
        }, true);
      } catch (e) { erros.push((p && p.sku) || it.insumoId); }
    }
    await window.tmSupabase.from('pedido_compra_itens').update({
      quantidade_recebida: Math.max(0, (Number(it.quantidadeRecebida) || 0) - qEst),
      quantidade_avaria:   Math.max(0, (Number(it.quantidadeAvaria)   || 0) - avEst),
    }).eq('id', it.id);
  }

  // Reabre: sem nada recebido volta pra "enviado"; com algo recebido, "recebido_parcial".
  const totalRecebidoDepois = (itens || []).reduce((a, it) =>
    a + Math.max(0, (Number(it.quantidadeRecebida) || 0) - (Number(estornos[it.id]) || 0)), 0);
  const patch = { status: totalRecebidoDepois > 0 ? 'recebido_parcial' : 'enviado', data_recebimento: null };
  await window.tmSupabase.from('pedidos_compra').update(patch).eq('id', pedido.id);
  return { erros, novoStatus: patch.status };
}

// ─── Fornecedores ────────────────────────────────────────────────────────────
const BLANK_FORN = { nome: '', cnpj: '', tipo: 'fabrica', contato: '', empresa_id: '', observacoes: '', situacao: 'Ativo',
  geral_cep: '', geral_endereco: '', geral_numero: '', geral_complemento: '', geral_bairro: '', geral_cidade: '', geral_uf: '' };

// ─── Seletor de fornecedor: busca + cadastro rápido (R1) ─────────────────────
// Reusa o SearchableSelect (busca por digitação, modo objeto {value,label}) e o
// padrão "cadastrar na hora" do Pedido. O "+ Cadastrar" fica SEMPRE visível
// (alwaysCreate) — nomes parecidos não podem impedir um cadastro novo. O cadastro
// rápido pede o mínimo (nome + CNPJ opcional), grava tipo 'ambos' (assim aparece
// tanto na Compra quanto na OP; ela refina depois em Estoque › Fornecedores) e já
// seleciona o recém-criado. Usado no Pedido de Compra e na Ordem de Produção.
function FornecedorSelect({ value, onChange, fornecedores, reload, empresaId, label = 'Fornecedor', required }) {
  const [quick, setQuick]   = React.useState(null);   // null | { nome, cnpj }
  const [saving, setSaving] = React.useState(false);
  const [err, setErr]       = React.useState('');
  const opts = (fornecedores || []).map(f => ({ value: f.id, label: f.nome }));

  const abrir = (nome) => { setErr(''); setQuick({ nome: nome || '', cnpj: '' }); };
  const salvar = async () => {
    const nome = (quick.nome || '').trim();
    if (!nome) { setErr('Nome é obrigatório.'); return; }
    if (!window.tmSupabase) { setErr('Sem conexão com o banco.'); return; }
    setSaving(true); setErr('');
    const payload = { nome, cnpj: (quick.cnpj || '').trim() || null, tipo: 'ambos', situacao: 'Ativo', empresa_id: empresaId || null };
    const { data, error } = await window.tmSupabase.from('fornecedores').insert(payload).select().single();
    setSaving(false);
    if (error) { setErr('Erro ao cadastrar: ' + (error.message || error)); return; }
    if (reload) await reload();
    if (data && data.id) onChange(data.id);   // já seleciona o recém-criado
    setQuick(null);
  };

  return (
    <>
      <SearchableSelect label={label} required={required}
        value={value || ''} onChange={onChange} options={opts}
        placeholder="Digite para buscar o fornecedor…"
        onCreateNew={abrir} alwaysCreate createLabel="Cadastrar novo fornecedor" />
      {quick && (
        <div style={{ position: 'fixed', inset: 0, zIndex: 9999, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
          <div style={{ position: 'absolute', inset: 0, background: 'rgba(0,0,0,0.6)' }} onClick={() => setQuick(null)} />
          <div style={{ position: 'relative', background: 'var(--tm-bg-2)', borderRadius: 14, padding: 28, width: '100%', maxWidth: 460, boxShadow: '0 16px 48px rgba(0,0,0,0.5)', border: '1px solid var(--tm-line-1)' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 6 }}>
              <h3 style={{ margin: 0, fontSize: 17, fontWeight: 600 }}>Cadastro rápido de fornecedor</h3>
              <button onClick={() => setQuick(null)} style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--tm-fg-3)', fontSize: 20 }}>×</button>
            </div>
            <div className="muted" style={{ fontSize: 12, marginBottom: 18 }}>Só o essencial — complete o resto depois em Estoque › Fornecedores.</div>
            <div className="field-grid-2" style={{ gap: 12 }}>
              <Field label="Nome *"><input className="input" autoFocus value={quick.nome} onChange={e => setQuick(q => ({ ...q, nome: e.target.value }))} placeholder="Razão social ou nome" /></Field>
              <Field label="CNPJ"><input className="input" value={quick.cnpj} onChange={e => setQuick(q => ({ ...q, cnpj: e.target.value }))} placeholder="Opcional" /></Field>
            </div>
            {err && <div style={{ color: 'var(--tm-danger)', fontSize: 12.5, marginTop: 10 }}>{err}</div>}
            <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 10, marginTop: 22, paddingTop: 16, borderTop: '1px solid var(--tm-line-1)' }}>
              <Button variant="ghost" size="sm" onClick={() => setQuick(null)}>Cancelar</Button>
              <Button variant="primary" size="sm" icon="check" onClick={salvar} disabled={saving}>{saving ? 'Salvando…' : 'Cadastrar e selecionar'}</Button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

// ─── Seletor de empresa: busca (consistente com o de fornecedor) ─────────────
// Só busca (empresa não se cria por aqui). Os forms pré-preenchem com a empresa
// ATIVA do topo (window.tmEmpresaId) — é o contexto em que ela já está.
function EmpresaSelect({ value, onChange, empresas, label = 'Empresa', required }) {
  const opts = (empresas || []).map(em => ({ value: em.id, label: em.nome_fantasia || em.razao_social || em.nome }));
  return (
    <SearchableSelect label={label} required={required} value={value || ''} onChange={onChange}
      options={opts} placeholder="Buscar empresa…" />
  );
}

// Empresa ativa do seletor do topo, se estiver na lista (default de novos registros).
function empresaAtivaPadrao(empresas) {
  const ativa = window.tmEmpresaId;
  if (ativa && (empresas || []).some(e => e.id === ativa)) return ativa;
  return empresas && empresas[0] ? empresas[0].id : '';
}

function FornecedoresLista({ onNav }) {   // eslint-disable-line no-unused-vars
  const s = useFornecedoresList([]);
  const empresasHook = useEmpresasList([]);
  const [saveErr, setSaveErr] = React.useState('');
  const empresaNome = (id) => { const e = (empresasHook.rows || []).find(x => x.id === id); return e ? (e.nome_fantasia || e.razao_social || e.nome || '—') : '—'; };
  const tipoLabel = (t) => (FORN_TIPOS.find(x => x.id === t) || {}).l || t;
  const ativos = [...(s.rows || [])].filter(f => f.situacao !== 'Arquivado').sort((a, b) => String(a.nome || '').localeCompare(String(b.nome || '')));

  const salvar = async () => {
    setSaveErr('');
    if (!(s.edit && s.edit.draft && (s.edit.draft.nome || '').trim())) { setSaveErr('Informe o nome.'); return; }
    const r = await s.save(); if (r && r.error) setSaveErr(r.error.message || 'Erro ao salvar.');
  };

  // ── Exclusão protegida (mesma regra dos títulos): fornecedor EM USO não sai —
  // lixeira desabilitada com o motivo; a alternativa é arquivar (no editar),
  // que preserva o histórico. Sem uso nenhum, exclui de verdade (com o de-para junto).
  const [usoForn, setUsoForn] = React.useState(null);   // fornId -> { pc, op, ne, cp, depara }
  React.useEffect(() => { (async () => {
    if (!window.tmSupabase) return;
    const [pcs, ops, nes, cps, dps, forns] = await Promise.all([
      window.tmSupabase.from('pedidos_compra').select('fornecedor_id'),
      window.tmSupabase.from('ordens_producao').select('fornecedor_id'),
      window.tmSupabase.from('notas_entrada').select('fornecedor_id'),
      window.tmSupabase.from('contas_pagar').select('fornecedor'),
      window.tmSupabase.from('fornecedor_produto_codigos').select('fornecedor_id'),
      window.tmSupabase.from('fornecedores').select('id, nome'),
    ]);
    const m = {};
    const conta = (rows, campo) => (rows.data || []).forEach(r => { const id = r[campo]; if (!id) return;
      m[id] = m[id] || { pc: 0, op: 0, ne: 0, cp: 0, depara: 0 }; });
    conta(pcs, 'fornecedor_id'); conta(ops, 'fornecedor_id'); conta(nes, 'fornecedor_id'); conta(dps, 'fornecedor_id');
    (pcs.data || []).forEach(r => { if (r.fornecedor_id) m[r.fornecedor_id].pc++; });
    (ops.data || []).forEach(r => { if (r.fornecedor_id) m[r.fornecedor_id].op++; });
    (nes.data || []).forEach(r => { if (r.fornecedor_id) m[r.fornecedor_id].ne++; });
    (dps.data || []).forEach(r => { if (r.fornecedor_id) m[r.fornecedor_id].depara++; });
    // títulos ligam por NOME (contas_pagar.fornecedor é texto)
    const porNome = {};
    (cps.data || []).forEach(r => { const k = String(r.fornecedor || '').trim().toLowerCase(); if (k) porNome[k] = (porNome[k] || 0) + 1; });
    (forns.data || []).forEach(f => { const k = String(f.nome || '').trim().toLowerCase();
      if (porNome[k]) { m[f.id] = m[f.id] || { pc: 0, op: 0, ne: 0, cp: 0, depara: 0 }; m[f.id].cp = porNome[k]; } });
    setUsoForn(m);
  })(); }, [s.rows.length]);   // eslint-disable-line

  const motivoUso = (u) => {
    const p = [];
    if (u.pc) p.push(`${u.pc} pedido${u.pc > 1 ? 's' : ''} de compra`);
    if (u.op) p.push(`${u.op} orde${u.op > 1 ? 'ns' : 'm'} de produção`);
    if (u.ne) p.push(`${u.ne} nota${u.ne > 1 ? 's' : ''} de entrada`);
    if (u.cp) p.push(`${u.cp} título${u.cp > 1 ? 's' : ''} no contas a pagar`);
    return p.join(' · ');
  };

  const excluir = async (f) => {
    const u = (usoForn && usoForn[f.id]) || { pc: 0, op: 0, ne: 0, cp: 0, depara: 0 };
    const extra = u.depara ? `\n\n${u.depara} vínculo(s) de código de-para deste fornecedor serão apagados junto.` : '';
    if (!confirm(`Excluir permanentemente "${f.nome}"?\n\nSem uso em pedidos, OPs, notas ou títulos — só o cadastro some.${extra}\n\nIsso não pode ser desfeito. Se preferir manter o histórico, use Arquivar (no editar).`)) return;
    if (u.depara) await window.tmSupabase.from('fornecedor_produto_codigos').delete().eq('fornecedor_id', f.id);
    const { error } = await window.tmSupabase.from('fornecedores').delete().eq('id', f.id);
    if (error) { alert('Erro ao excluir: ' + error.message); return; }
    s.reload();
  };

  return (
    <div className="canvas">
      <PageHead title="Estoque · Fornecedores" sub={`${ativos.length} cadastrado${ativos.length !== 1 ? 's' : ''}`}
        right={<Button variant="primary" icon="plus" size="sm" onClick={() => { setSaveErr(''); s.open('new', null, { ...BLANK_FORN, empresa_id: window.tmEmpresaId || '' }); }}>Novo fornecedor</Button>} />
      <Card>
        {ativos.length === 0 ? (
          <div style={{ padding: '48px 0', textAlign: 'center', color: 'var(--tm-fg-3)' }}>
            <Icon name="truck" size={36} style={{ opacity: 0.3, marginBottom: 12 }} />
            <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhum fornecedor</div>
            <div style={{ fontSize: 12 }}>Cadastre a fábrica (industrialização) e os fornecedores de insumo.</div>
          </div>
        ) : (
          <table className="tbl"><thead><tr><th>Nome</th><th>Tipo</th><th>CNPJ</th><th>Contato</th><th>Empresa</th><th></th></tr></thead>
            <tbody>
              {ativos.map(f => (
                <tr key={f.id} className="clickable" onClick={() => { setSaveErr(''); s.open('edit', s.rows.findIndex(x => x.id === f.id)); }}>
                  <td style={{ fontWeight: 600 }}>{f.nome}</td>
                  <td><Badge tone="neutral">{tipoLabel(f.tipo)}</Badge></td>
                  <td className="muted">{f.cnpj || '—'}</td>
                  <td className="muted">{f.contato || '—'}</td>
                  <td className="muted">{f.empresa_id ? empresaNome(f.empresa_id) : '—'}</td>
                  <td onClick={e => e.stopPropagation()} style={{ whiteSpace: 'nowrap' }}>
                    <Button variant="ghost" size="sm" icon="pencil" title="Editar" onClick={() => { setSaveErr(''); s.open('edit', s.rows.findIndex(x => x.id === f.id)); }} />
                    {(() => {
                      const u = usoForn && usoForn[f.id];
                      const emUso = u && (u.pc || u.op || u.ne || u.cp);
                      return emUso
                        ? <span title={`Não dá pra excluir: usado em ${motivoUso(u)}. Arquive (no editar) pra tirar da frente preservando o histórico.`}>
                            <Button variant="ghost" size="sm" icon="trash-2" disabled />
                          </span>
                        : <Button variant="ghost" size="sm" icon="trash-2" disabled={usoForn === null}
                            title={usoForn === null ? 'Conferindo usos…' : 'Excluir fornecedor'} onClick={() => excluir(f)} />;
                    })()}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </Card>

      {s.edit && (
        <Drawer open={true} width={520} title={s.edit.mode === 'new' ? 'Novo fornecedor' : 'Editar fornecedor'}
          onClose={s.close}
          footer={<><span style={{ flex: 1 }} />
            {s.edit.mode === 'edit' && <Button variant="danger-ghost" size="sm" icon="archive" onClick={async () => { await s.archive(); }}>Arquivar</Button>}
            <Button variant="secondary" size="sm" onClick={s.close}>Cancelar</Button>
            <Button variant="primary" size="sm" icon="check" onClick={salvar}>Salvar</Button></>}>
          <div className="field-grid-2">
            <Field label="Nome *"><input className="input" value={s.edit.draft.nome || ''} onChange={e => s.set('nome', e.target.value)} /></Field>
            <Field label="CNPJ"><input className="input" value={s.edit.draft.cnpj || ''} onChange={e => s.set('cnpj', e.target.value)} /></Field>
          </div>
          <div className="field-grid-2">
            <Field label="Tipo">
              <select className="input" value={s.edit.draft.tipo || 'fabrica'} onChange={e => s.set('tipo', e.target.value)}>
                {FORN_TIPOS.map(t => <option key={t.id} value={t.id}>{t.l}</option>)}
              </select>
            </Field>
            <Field label="Contato"><input className="input" value={s.edit.draft.contato || ''} onChange={e => s.set('contato', e.target.value)} placeholder="Telefone / e-mail" /></Field>
          </div>
          <div className="field-grid-2">
            <Field label="Prazo de entrega (dias)" hint="Quanto ele demora a entregar — a Sugestão de Compra usa isso pra avisar antes de faltar. Vazio = 15">
              <input className="input" type="number" min="0" step="1" placeholder="15"
                value={s.edit.draft.prazo_entrega_dias != null ? s.edit.draft.prazo_entrega_dias : ''}
                onChange={e => s.set('prazo_entrega_dias', e.target.value)} style={{ textAlign: 'right' }} />
            </Field>
            <div />
          </div>
          <EmpresaSelect label="Empresa (dona)" value={s.edit.draft.empresa_id || ''}
            onChange={v => s.set('empresa_id', v)} empresas={empresasHook.rows || []} />

          {/* Endereço (geral_*) — pré-requisito da NF-e de remessa: a fábrica é
              o destinatário da nota. CEP puxa o resto pelo ViaCEP. */}
          <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.08em',
            color: 'var(--tm-fg-4)', margin: '14px 0 8px', paddingTop: 10, borderTop: '1px solid var(--tm-line-1)' }}>
            Endereço <span style={{ fontWeight: 400, textTransform: 'none', letterSpacing: 0 }}>· usado na nota de remessa (fábrica) e na etiqueta</span>
          </div>
          <div className="field-grid-2">
            <Field label="CEP" hint="preenche o resto sozinho">
              <input className="input" inputMode="numeric" value={s.edit.draft.geral_cep || ''} placeholder="00000-000"
                onChange={async (e) => {
                  const v = e.target.value; s.set('geral_cep', v);
                  const d = String(v).replace(/[^0-9]/g, '');
                  if (d.length === 8) {
                    try {
                      const r = await fetch('https://viacep.com.br/ws/' + d + '/json/');
                      const c = await r.json();
                      if (!c.erro) s.set({ geral_endereco: c.logradouro || '', geral_bairro: c.bairro || '',
                        geral_cidade: c.localidade || '', geral_uf: (c.uf || '').toUpperCase() });
                    } catch (err) { /* sem ViaCEP, preenche à mão */ }
                  }
                }} />
            </Field>
            <Field label="Endereço"><input className="input" value={s.edit.draft.geral_endereco || ''} onChange={e => s.set('geral_endereco', e.target.value)} placeholder="Rua / avenida" /></Field>
          </div>
          <div className="field-grid-2">
            <Field label="Número"><input className="input" value={s.edit.draft.geral_numero || ''} onChange={e => s.set('geral_numero', e.target.value)} /></Field>
            <Field label="Complemento"><input className="input" value={s.edit.draft.geral_complemento || ''} onChange={e => s.set('geral_complemento', e.target.value)} placeholder="opcional" /></Field>
          </div>
          <div className="field-grid-2">
            <Field label="Bairro"><input className="input" value={s.edit.draft.geral_bairro || ''} onChange={e => s.set('geral_bairro', e.target.value)} /></Field>
            <div className="field-grid-2" style={{ gap: 10 }}>
              <Field label="Cidade"><input className="input" value={s.edit.draft.geral_cidade || ''} onChange={e => s.set('geral_cidade', e.target.value)} /></Field>
              <Field label="UF"><input className="input" maxLength={2} value={s.edit.draft.geral_uf || ''} onChange={e => s.set('geral_uf', e.target.value.toUpperCase())} /></Field>
            </div>
          </div>

          <Field label="Observações"><textarea className="input" rows={2} value={s.edit.draft.observacoes || ''} onChange={e => s.set('observacoes', e.target.value)} /></Field>
          {saveErr && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{saveErr}</div>}
        </Drawer>
      )}
    </div>
  );
}

// ─── Ordem de Produção ───────────────────────────────────────────────────────
function OrdensProducao({ onNav }) {   // eslint-disable-line no-unused-vars
  const ops = useOrdensProducao();
  const prodHook = useProdutosList([]);
  const fornHook = useFornecedoresList([]);
  const empresasHook = useEmpresasList([]);
  const [novo, setNovo] = React.useState(false);
  const [editando, setEditando] = React.useState(null);   // { ordem, itens, insumos }
  const [detalhe, setDetalhe] = React.useState(null);      // { ordem, itens, insumos }
  const [doc, setDoc] = React.useState(null);              // { ordem, itens, insumos } — documento p/ a fábrica
  const [acao, setAcao] = React.useState(null);            // { tipo:'enviar'|'receber', ordem, itens, insumos }
  const [busy, setBusy] = React.useState(false);
  const [indus, setIndus] = React.useState([]);            // agregado "em industrialização"
  const [remessa, setRemessa] = React.useState(null);      // { ordem, insumos } — NF-e de remessa (Fase B)
  const [nfPorOp, setNfPorOp] = React.useState({});        // ordem_id -> nota de remessa viva
  const [etqOP, setEtqOP] = React.useState(null);          // ordem — etiquetas de volume da remessa

  const prodById = {}; (prodHook.rows || []).forEach(p => { prodById[p.id] = p; });
  const fornById = {}; (fornHook.rows || []).forEach(f => { fornById[f.id] = f; });
  const fabricas = (fornHook.rows || []).filter(f => f.situacao !== 'Arquivado' && (f.tipo === 'fabrica' || f.tipo === 'ambos'));
  const acabados = (prodHook.rows || []).filter(p => (p.tipo || 'venda') !== 'insumo');
  const insumosProd = (prodHook.rows || []).filter(p => (p.tipo || 'venda') === 'insumo');

  const carregarIndustrializacao = React.useCallback(async () => {
    if (!window.tmSupabase) return;
    const abertas = (ops.rows || []).filter(o => o.status === 'enviada' || o.status === 'em_producao').map(o => o.id);
    if (!abertas.length) { setIndus([]); return; }
    const { data } = await window.tmSupabase.from('ordem_producao_insumos').select('insumo_id,quantidade_enviada,ordem_id').in('ordem_id', abertas);
    const acc = {};
    (data || []).forEach(r => { acc[r.insumo_id] = (acc[r.insumo_id] || 0) + (Number(r.quantidade_enviada) || 0); });
    setIndus(Object.keys(acc).filter(k => acc[k] > 0).map(k => ({ insumoId: k, qtd: acc[k] })).sort((a, b) => b.qtd - a.qtd));
  }, [ops.rows]);
  React.useEffect(() => { carregarIndustrializacao(); }, [carregarIndustrializacao]);

  // Notas de remessa vivas por OP (Rejeitada/Cancelada não conta — deixa reemitir)
  const carregarNfRemessa = React.useCallback(async () => {
    if (!window.tmSupabase) return;
    const { data } = await window.tmSupabase.from('notas_fiscais')
      .select('id, numero, status, danfe_url, ordem_producao_id')
      .not('ordem_producao_id', 'is', null);
    const m = {};
    (data || []).forEach(n => {
      if (n.status === 'Rejeitada' || n.status === 'Cancelada') return;
      m[n.ordem_producao_id] = n;
    });
    setNfPorOp(m);
  }, []);
  React.useEffect(() => { carregarNfRemessa(); }, [carregarNfRemessa]);

  const abrirDanfeRemessa = (nf) => {
    if (nf.danfe_url) window.open(nf.danfe_url, '_blank');
    else alert('DANFE ainda não disponível para a NF ' + nf.numero + ' — veja em NF › Histórico.');
  };

  const recarregar = () => { ops.reload(); prodHook.reload && prodHook.reload(); carregarIndustrializacao(); carregarNfRemessa(); };
  const abrir = async (ordem, setter) => { setBusy(true); const d = await window.tmDb.loadOrdemProducao(ordem.id); setBusy(false); setter({ ordem, itens: d.itens, insumos: d.insumos }); };
  const fornNome = (id) => (fornById[id] && fornById[id].nome) || '—';
  const fmtD = (iso) => iso ? (fmtDate(iso) || String(iso).slice(0, 10).split('-').reverse().join('/')) : '—';

  return (
    <div className="canvas">
      <PageHead title="Estoque · Ordem de Produção" sub={`${(ops.rows || []).length} OP${(ops.rows || []).length !== 1 ? 's' : ''}`}
        right={<Button variant="primary" icon="plus" size="sm" disabled={fabricas.length === 0} onClick={() => setNovo(true)}>Nova OP</Button>} />

      {fabricas.length === 0 && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: '0 0 16px', padding: '10px 14px', borderRadius: 'var(--tm-radius-sm)', fontSize: 12.5,
          color: 'var(--tm-warning)', background: 'color-mix(in srgb, var(--tm-warning) 12%, transparent)', border: '1px solid color-mix(in srgb, var(--tm-warning) 30%, transparent)' }}>
          <Icon name="alert-circle" size={15} /> <span>Cadastre uma <b>fábrica</b> primeiro em <b>Estoque › Fornecedores</b>.</span>
        </div>
      )}

      {indus.length > 0 && (
        <Card title="Em industrialização (material na fábrica agora)" style={{ marginBottom: 16 }}>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 10 }}>
            {indus.slice(0, 12).map(x => (
              <div key={x.insumoId} style={{ padding: '8px 12px', borderRadius: 'var(--tm-radius-sm)', background: 'var(--tm-bg-2)', border: '1px solid var(--tm-line-1)', fontSize: 12.5 }}>
                <span className="ref-mono">{prodById[x.insumoId] ? prodById[x.insumoId].sku : '—'}</span> {prodById[x.insumoId] ? (prodById[x.insumoId].nome || prodById[x.insumoId].name) : ''} · <b>{x.qtd}</b>
              </div>
            ))}
          </div>
          <div style={{ fontSize: 11.5, color: 'var(--tm-fg-4)', marginTop: 8 }}>Já saiu do galpão (baixado no envio) e está na fábrica. Patrimônio do insumo = estoque no galpão + isto.</div>
        </Card>
      )}

      <Card>
        {(ops.rows || []).length === 0 ? (
          <div style={{ padding: '48px 0', textAlign: 'center', color: 'var(--tm-fg-3)' }}>
            <Icon name="factory" size={36} style={{ opacity: 0.3, marginBottom: 12 }} />
            <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhuma ordem de produção</div>
            <div style={{ fontSize: 12 }}>Crie uma OP: escolha a fábrica, os acabados a produzir, e o app calcula os insumos.</div>
          </div>
        ) : (
          <table className="tbl">
            <thead><tr><th>Nº</th><th>Fábrica</th><th>Criada</th><th>Prevista</th><th>Status</th><th></th></tr></thead>
            <tbody>
              {(ops.rows || []).map(o => {
                const st = OP_STATUS[o.status] || OP_STATUS.rascunho;
                return (
                  <tr key={o.id} className="clickable" onClick={() => abrir(o, setDetalhe)}>
                    <td><span className="ref-mono gold">{o.numero}</span></td>
                    <td>{fornNome(o.fornecedor_id)}</td>
                    <td className="muted">{fmtD(o.data_criacao || o.created_at)}</td>
                    <td className="muted">{fmtD(o.data_prevista)}</td>
                    <td><Badge tone={st.tone}>{st.l}</Badge></td>
                    <td onClick={e => e.stopPropagation()} style={{ whiteSpace: 'nowrap' }}>
                      <Button variant="ghost" size="sm" icon="eye" title="Ver detalhes" onClick={() => abrir(o, setDetalhe)} />
                      <Button variant="ghost" size="sm" icon="printer" disabled={busy} title="Documento interno (p/ a fábrica)" onClick={() => abrir(o, setDoc)} />
                      <Button variant="ghost" size="sm" icon="tag" disabled={busy} title="Etiquetas de volume (remessa p/ a fábrica)"
                        onClick={() => abrir(o, (d) => setEtqOP({ ordem: d.ordem, insumos: d.insumos }))} />
                      {/* Fase B: NF-e de remessa acompanha o material. Sem nota ainda → emitir; com nota → DANFE. */}
                      {(o.status === 'rascunho' || o.status === 'enviada') && !nfPorOp[o.id] && (
                        <Button variant="ghost" size="sm" icon="file-check" disabled={busy} title="Emitir nota de remessa"
                          onClick={() => abrir(o, (d) => setRemessa({ ordem: d.ordem, insumos: d.insumos }))} />
                      )}
                      {nfPorOp[o.id] && (
                        <Button variant="ghost" size="sm" icon="file-text" title={`DANFE da remessa · NF ${nfPorOp[o.id].numero} (${nfPorOp[o.id].status})`}
                          onClick={() => abrirDanfeRemessa(nfPorOp[o.id])} />
                      )}
                      {o.status === 'rascunho' && <Button variant="ghost" size="sm" icon="pencil" disabled={busy} title="Editar" onClick={() => abrir(o, setEditando)} />}
                      {o.status === 'rascunho' && <Button variant="ghost" size="sm" icon="send" disabled={busy} title="Enviar p/ fábrica" onClick={() => abrir(o, (d) => setAcao({ tipo: 'enviar', ...d }))} />}
                      {(o.status === 'enviada' || o.status === 'em_producao') && <Button variant="ghost" size="sm" icon="package-check" disabled={busy} title="Receber produção" onClick={() => abrir(o, (d) => setAcao({ tipo: 'receber', ...d }))} />}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </Card>

      {novo && <OPForm fabricas={fabricas} reload={fornHook.reload} empresas={empresasHook.rows || []} acabados={acabados} insumosProd={insumosProd} prodById={prodById}
        onClose={() => setNovo(false)} onSaved={() => { setNovo(false); recarregar(); }} />}
      {editando && <OPForm edit={editando} fabricas={fabricas} reload={fornHook.reload} empresas={empresasHook.rows || []} acabados={acabados} insumosProd={insumosProd} prodById={prodById}
        onClose={() => setEditando(null)} onSaved={() => { setEditando(null); recarregar(); }} />}
      {detalhe && <OPDetalhe ordem={detalhe.ordem} itens={detalhe.itens} insumos={detalhe.insumos} prodById={prodById} fornNome={fornNome} onClose={() => setDetalhe(null)} />}
      {doc && <OPDoc ordem={doc.ordem} itens={doc.itens} insumos={doc.insumos} prodById={prodById}
        fabrica={fornById[doc.ordem.fornecedor_id]} empresa={(empresasHook.rows || []).find(e => e.id === doc.ordem.empresa_id)}
        onClose={() => setDoc(null)} />}
      {remessa && <RemessaOPDrawer ordem={remessa.ordem} insumos={remessa.insumos}
        fabrica={fornById[remessa.ordem.fornecedor_id]} prodById={prodById}
        onClose={() => setRemessa(null)} onEmitida={carregarNfRemessa} />}
      {/* Fase 2 da etiqueta de volume: MESMO componente do pedido de venda,
          com o destino trocado pra fábrica da OP (cadastro geral_*). */}
      {etqOP && <EtiquetaVolumeModal
        pedido={{ id: null, numero: etqOP.ordem.numero, transp: {},
          expedicaoData: fmtDate(etqOP.ordem.expedicao_data) || '',
          expedicaoResponsavel: etqOP.ordem.expedicao_responsavel || '' }}
        destino={{ rotulo: 'FÁBRICA', opId: etqOP.ordem.id,
          nome: (fornById[etqOP.ordem.fornecedor_id] || {}).nome || '',
          cadastro: fornById[etqOP.ordem.fornecedor_id] || {},
          empresa: (empresasHook.rows || []).find(e => e.id === etqOP.ordem.empresa_id) || null,
          // total pro "Distribuir": o que efetivamente vai na remessa
          totalItens: Math.round((etqOP.insumos || []).reduce((a, ins) => {
            const q = Number(ins.quantidadeEnviada != null ? ins.quantidadeEnviada : ins.quantidade_enviada) || Number(ins.quantidade) || 0;
            return a + q;
          }, 0)) }}
        onClose={() => { setEtqOP(null); ops.reload(); }} />}
      {acao && acao.tipo === 'enviar' && <EnvioConfirm ordem={acao.ordem} insumos={acao.insumos} prodById={prodById}
        onClose={() => setAcao(null)} onDone={() => { setAcao(null); recarregar(); }} />}
      {acao && acao.tipo === 'receber' && <RecebimentoForm ordem={acao.ordem} itens={acao.itens} insumos={acao.insumos} prodById={prodById}
        onClose={() => setAcao(null)} onDone={() => { setAcao(null); recarregar(); }} />}
    </div>
  );
}

// Form de OP (só rascunho): cabeçalho + itens a produzir + Calcular insumos (editável).
function OPForm({ edit, fabricas, reload, empresas, acabados, insumosProd, prodById, onClose, onSaved }) {
  const ehEdicao = !!edit;
  const o = ehEdicao ? edit.ordem : null;
  const [fornecedorId, setFornecedorId] = React.useState(ehEdicao ? (o.fornecedor_id || '') : '');   // busca começa vazia (R1)
  const [empresaId, setEmpresaId] = React.useState(ehEdicao ? (o.empresa_id || '') : empresaAtivaPadrao(empresas));   // nasce com a empresa ativa do topo
  const [dataPrevista, setDataPrevista] = React.useState(ehEdicao ? (String(o.data_prevista || '').slice(0, 10)) : '');
  const [obs, setObs] = React.useState(ehEdicao ? (o.observacoes || '') : '');
  const [itens, setItens] = React.useState(ehEdicao ? (edit.itens || []).map(i => ({ produtoId: i.produtoId, quantidade: i.quantidade })) : [{ produtoId: '', quantidade: 1 }]);
  const [insumos, setInsumos] = React.useState(ehEdicao ? (edit.insumos || []).map(i => ({ insumoId: i.insumoId, quantidade: i.quantidade })) : []);
  const [saving, setSaving] = React.useState(false);
  const [calc, setCalc] = React.useState(false);
  const [err, setErr] = React.useState('');

  const acabOpts = acabados.map(p => ({ value: p.id, label: `${p.sku} · ${p.nome || p.name}` }));
  const insumoOpts = insumosProd.map(p => ({ value: p.id, label: `${p.sku} · ${p.nome || p.name}` }));

  const setItem = (i, patch) => setItens(rows => rows.map((r, idx) => idx === i ? { ...r, ...patch } : r));
  const addItem = () => setItens(rows => [...rows, { produtoId: '', quantidade: 1 }]);
  const rmItem = (i) => setItens(rows => rows.length > 1 ? rows.filter((_, idx) => idx !== i) : rows);
  const setIns = (i, patch) => setInsumos(rows => rows.map((r, idx) => idx === i ? { ...r, ...patch } : r));
  const rmIns = (i) => setInsumos(rows => rows.filter((_, idx) => idx !== i));
  const addIns = (insumoId) => { if (!insumoId || insumos.some(x => x.insumoId === insumoId)) return; setInsumos(rows => [...rows, { insumoId, quantidade: 1 }]); };

  const calcularInsumos = async () => {
    setCalc(true); setErr('');
    const acabIds = [...new Set(itens.filter(i => i.produtoId && Number(i.quantidade) > 0).map(i => i.produtoId))];
    const fichasMap = {};
    for (const id of acabIds) { fichasMap[id] = await window.tmDb.loadFichaTecnica(id); }
    setInsumos(explodirInsumos(itens, fichasMap));
    setCalc(false);
  };

  const salvar = async () => {
    if (!fornecedorId) { setErr('Escolha a fábrica.'); return; }
    const itensValidos = itens.filter(i => i.produtoId && Number(i.quantidade) > 0);
    if (!itensValidos.length) { setErr('Adicione ao menos um acabado a produzir.'); return; }
    setSaving(true); setErr('');
    const draft = {
      id: ehEdicao ? o.id : undefined, numero: ehEdicao ? o.numero : gerarNumOP(),
      empresa_id: empresaId || null, fornecedor_id: fornecedorId, status: 'rascunho',
      data_criacao: ehEdicao ? (o.data_criacao || hojeIso()) : hojeIso(), data_prevista: dataPrevista || null, observacoes: obs || null,
      itens: itensValidos, insumos: insumos.filter(x => x.insumoId && Number(x.quantidade) > 0),
    };
    const r = await window.tmDb.salvarOrdemProducao(draft);
    setSaving(false);
    if (r.error) { setErr(r.error.message || 'Erro ao salvar.'); return; }
    onSaved();
  };

  const nomeDe = (id) => { const p = prodById[id]; return p ? (p.nome || p.name) : ''; };
  const skuDe = (id) => { const p = prodById[id]; return p ? p.sku : ''; };
  const custoDe = (id) => { const p = prodById[id]; return p ? (Number(p.custo) || 0) : 0; };
  const estoqueDe = (id) => { const p = prodById[id]; return p ? (Number(p.estoque) || 0) : 0; };

  return (
    <Drawer open={true} width={760} title={ehEdicao ? `Editar OP ${o.numero}` : 'Nova ordem de produção'}
      subtitle="Escolha os acabados a produzir; o app calcula os insumos pela ficha técnica"
      onClose={onClose}
      footer={<><span style={{ flex: 1 }} />
        <Button variant="secondary" size="sm" onClick={onClose}>Cancelar</Button>
        <Button variant="primary" size="sm" icon="check" onClick={salvar} disabled={saving}>{saving ? 'Salvando…' : 'Salvar rascunho'}</Button></>}>

      <div className="field-grid-3">
        <FornecedorSelect label="Fábrica" required value={fornecedorId} onChange={setFornecedorId}
          fornecedores={fabricas} reload={reload} empresaId={empresaId} />
        <EmpresaSelect value={empresaId} onChange={setEmpresaId} empresas={empresas} />
        <Field label="Previsão de retorno"><input className="input" type="date" value={dataPrevista} onChange={e => setDataPrevista(e.target.value)} /></Field>
      </div>

      <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--tm-fg-4)', margin: '12px 0 6px' }}>Acabados a produzir</div>
      <table className="tbl" style={{ fontSize: 12.5 }}>
        <thead><tr><th>Produto acabado</th><th style={{ width: 110 }}>Qtd a produzir</th><th style={{ width: 36 }}></th></tr></thead>
        <tbody>
          {itens.map((it, i) => (
            <tr key={i}>
              <td><SearchableSelect value={it.produtoId} options={acabOpts} placeholder="Buscar acabado (SKU/nome)…" onChange={(id) => setItem(i, { produtoId: id })} /></td>
              <td><input className="input" type="number" min="1" step="1" value={it.quantidade} onChange={e => setItem(i, { quantidade: e.target.value })} style={{ padding: '4px 8px' }} /></td>
              <td>{itens.length > 1 && <Button variant="ghost" size="sm" icon="x" title="Remover" onClick={() => rmItem(i)} />}</td>
            </tr>
          ))}
        </tbody>
      </table>
      <div style={{ marginTop: 8, display: 'flex', gap: 8, alignItems: 'center' }}>
        <Button variant="secondary" size="sm" icon="plus" onClick={addItem}>Adicionar acabado</Button>
        <Button variant="primary" size="sm" icon="flask-conical" onClick={calcularInsumos} disabled={calc}>{calc ? 'Calculando…' : 'Calcular insumos da ficha'}</Button>
      </div>

      <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--tm-fg-4)', margin: '16px 0 6px' }}>Insumos a enviar (editável)</div>
      {insumos.length === 0 ? (
        <div style={{ padding: '18px 0', textAlign: 'center', color: 'var(--tm-fg-3)', fontSize: 12.5 }}>
          Clique em <b>Calcular insumos da ficha</b> pra explodir a receita, ou adicione manualmente abaixo.
        </div>
      ) : (
        <table className="tbl" style={{ fontSize: 12.5 }}>
          <thead><tr><th>Insumo</th><th style={{ width: 100 }} className="num right">Enviar</th><th style={{ width: 100 }} className="num right">Em estoque</th><th style={{ width: 110 }} className="num right">Custo un.</th><th style={{ width: 36 }}></th></tr></thead>
          <tbody>
            {insumos.map((ins, i) => (
              <tr key={ins.insumoId || i}>
                <td>{ins.insumoId ? <span><span className="ref-mono">{skuDe(ins.insumoId)}</span> {nomeDe(ins.insumoId)}</span> : '—'}</td>
                <td className="num right"><input className="input" type="number" min="0" step="1" value={ins.quantidade} onChange={e => setIns(i, { quantidade: e.target.value })} style={{ padding: '4px 8px', textAlign: 'right', width: 80 }} /></td>
                <td className="num right muted">{estoqueDe(ins.insumoId)}</td>
                <td className="num right muted">R$ {brl(custoDe(ins.insumoId))}</td>
                <td><Button variant="ghost" size="sm" icon="x" title="Remover" onClick={() => rmIns(i)} /></td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
      <div style={{ marginTop: 8, maxWidth: 360 }}>
        <SearchableSelect value="" options={insumoOpts.filter(o2 => !insumos.some(x => x.insumoId === o2.value))} placeholder="Adicionar insumo avulso…" onChange={addIns} />
      </div>

      <Field label="Observações" style={{ marginTop: 14 }}><textarea className="input" rows={2} value={obs} onChange={e => setObs(e.target.value)} /></Field>
      {err && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{err}</div>}
    </Drawer>
  );
}

// Detalhe (view) — cabeçalho, acabados (a produzir / recebido), insumos (enviar / enviado).
function OPDetalhe({ ordem, itens, insumos, prodById, fornNome, onClose }) {
  const st = OP_STATUS[ordem.status] || OP_STATUS.rascunho;
  const nomeDe = (id) => { const p = prodById[id]; return p ? (p.nome || p.name) : '—'; };
  const skuDe = (id) => { const p = prodById[id]; return p ? p.sku : '—'; };
  const fmtD = (iso) => iso ? (fmtDate(iso) || String(iso).slice(0, 10).split('-').reverse().join('/')) : '—';
  return (
    <Drawer open={true} width={720} title={`OP ${ordem.numero}`} subtitle={`${fornNome(ordem.fornecedor_id)} · ${st.l}`} onClose={onClose}
      footer={<><span style={{ flex: 1 }} /><Button variant="secondary" size="sm" onClick={onClose}>Fechar</Button></>}>
      <div className="field-grid-3" style={{ marginBottom: 14 }}>
        <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Criada</div><div>{fmtD(ordem.data_criacao || ordem.created_at)}</div></div>
        <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Enviada</div><div>{fmtD(ordem.data_envio)}</div></div>
        <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Recebida</div><div>{fmtD(ordem.data_recebimento)}</div></div>
      </div>
      <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--tm-fg-4)', margin: '4px 0 6px' }}>Acabados</div>
      <table className="tbl" style={{ fontSize: 12.5, marginBottom: 14 }}>
        <thead><tr><th>Produto</th><th className="num right">A produzir</th><th className="num right">Recebido</th><th className="num right">Custo un.</th></tr></thead>
        <tbody>{(itens || []).map((it, i) => (
          <tr key={i}><td><span className="ref-mono">{skuDe(it.produtoId)}</span> {nomeDe(it.produtoId)}</td>
            <td className="num right">{it.quantidade}</td><td className="num right">{it.quantidadeRecebida}</td>
            <td className="num right muted">{it.custoUnitario != null ? `R$ ${brl(it.custoUnitario)}` : '—'}</td></tr>
        ))}</tbody>
      </table>
      <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--tm-fg-4)', margin: '4px 0 6px' }}>Insumos</div>
      <table className="tbl" style={{ fontSize: 12.5 }}>
        <thead><tr><th>Insumo</th><th className="num right">A enviar</th><th className="num right">Enviado</th></tr></thead>
        <tbody>{(insumos || []).map((ins, i) => (
          <tr key={i}><td><span className="ref-mono">{skuDe(ins.insumoId)}</span> {nomeDe(ins.insumoId)}</td>
            <td className="num right">{ins.quantidade}</td><td className="num right">{ins.quantidadeEnviada}</td></tr>
        ))}</tbody>
      </table>
      {ordem.servico_valor != null && <div style={{ fontSize: 12.5, color: 'var(--tm-fg-3)', marginTop: 12 }}>Serviço da fábrica: <b>R$ {brl(ordem.servico_valor)}</b></div>}
    </Drawer>
  );
}

// Documento imprimível da Ordem de Produção — MESMO layout de venda/compra
// (blocos de src/DocImpressao.jsx, sem CSS nem regra de print própria).
// É documento de REMESSA: vai junto com o material pra fábrica, que o usa pra
// saber o que produzir e pra CONFERIR o material na chegada — por isso a tabela
// de insumos tem coluna de conferência em branco (marcação a caneta) e há bloco
// de assinatura no rodapé.
// ⚠️ SEM VALORES: a fábrica não vê custo de insumo nem valor de serviço.
function OPDoc({ ordem, itens, insumos, prodById, fabrica, empresa, onClose }) {
  const prodDe = (id) => prodById[id] || {};
  const nomeDe = (id) => { const p = prodDe(id); return p.nome || p.name || '—'; };
  const skuDe  = (id) => prodDe(id).sku || '';
  const unDe   = (id) => prodDe(id).unidade || 'UN';
  const fmtD   = (iso) => iso ? (fmtDate(iso) || String(iso).slice(0, 10).split('-').reverse().join('/')) : '—';
  const qtd    = (n) => (Number(n) || 0).toLocaleString('pt-BR');

  const acabados = (itens || []).filter(it => it.produtoId);
  const envio    = (insumos || []).filter(ins => ins.insumoId);
  const st       = OP_STATUS[ordem.status] || OP_STATUS.rascunho;
  const emp      = empresa || window.tmEmpresa || (window.tmEmpresas || [])[0] || {};

  const colsProduto = [
    { label: "Descrição do produto" },
    { label: "Código / SKU", width: 90 },
    { label: "Un.",          width: 40, align: "center" },
    { label: "Quantidade",   width: 80, align: "right" },
  ];

  return (
    <DocPrintOverlay barraTitulo={`Pré-visualização — OP ${ordem.numero}`} onClose={onClose}>

      <DocCabecalhoEmpresa empresa={emp} />

      <DocTitulo texto="Ordem de Produção" numero={ordem.numero} />

      <DocParteInfo
        parteLabel="Fábrica"
        parteNome={fabrica && fabrica.nome}
        detalhes={(() => {
          const doc = fabrica && fabrica.cnpj;
          const ctt = fabrica && fabrica.contato;
          return (
            <div style={{ fontSize: 10.5, color: "#444", lineHeight: 1.7 }}>
              {doc && <div>CNPJ: {doc}</div>}
              {ctt && <div>Tel/Contato: {ctt}</div>}
            </div>
          );
        })()}
        info={[
          ["Número da OP",        ordem.numero],
          ["Data de emissão",     fmtD(ordem.data_criacao || ordem.created_at)],
          ["Previsão de entrega", fmtD(ordem.data_prevista)],
          ["Situação",            st.l],
        ]}
      />

      {/* ── TABELA 1 — o que produzir ── */}
      <div className="doc-section-break">
        <DocTituloSecao>Produtos a produzir</DocTituloSecao>
        <DocTabelaItens
          colunas={colsProduto}
          linhas={acabados.map((it) => [
            { v: nomeDe(it.produtoId) },
            { v: skuDe(it.produtoId), muted: true },
            { v: unDe(it.produtoId), align: "center" },
            { v: qtd(it.quantidade), align: "right", num: true },
          ])}
          totais={[
            ["N° de itens",    qtd(acabados.length), false],
            ["Soma das Qtdes", qtd(acabados.reduce((a, it) => a + (Number(it.quantidade) || 0), 0)), true],
          ]}
        />
      </div>

      {/* ── TABELA 2 — o que segue junto; a fábrica confere a caneta na chegada ──
          O destaque do rodapé é o Nº DE ITENS (o que se risca na conferência); a soma
          de quantidades mistura unidades (UN + CX), então fica como referência. */}
      <div className="doc-section-break">
        <DocTituloSecao>Insumos enviados — conferir no recebimento</DocTituloSecao>
        <DocTabelaItens
          colunas={[
            { label: "Descrição do insumo" },
            { label: "Código / SKU", width: 90 },
            { label: "Un.",          width: 40, align: "center" },
            { label: "Quantidade",   width: 80, align: "right" },
            { label: "Conferido",    width: 62, align: "center" },
          ]}
          linhas={envio.map((ins) => [
            { v: nomeDe(ins.insumoId) },
            { v: skuDe(ins.insumoId), muted: true },
            { v: unDe(ins.insumoId), align: "center" },
            { v: qtd(ins.quantidade), align: "right", num: true },
            { v: <DocCaixaConferencia />, align: "center" },
          ])}
          totais={[
            ["Itens a conferir", qtd(envio.length), true],
            ["Soma das Qtdes",   qtd(envio.reduce((a, ins) => a + (Number(ins.quantidade) || 0), 0)), false],
          ]}
        />
      </div>

      <DocObservacoes texto={ordem.observacoes} />

      <DocAssinatura
        titulo="Recebimento do material pela fábrica"
        nota="Confira as quantidades da tabela de insumos antes de assinar. Divergência: anote ao lado do item e comunique no ato." />

    </DocPrintOverlay>
  );
}

// Confirmação de ENVIO — mostra o que baixa e AVISA a falta (deixa seguir).
function EnvioConfirm({ ordem, insumos, prodById, onClose, onDone }) {
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');
  const linhas = (insumos || []).filter(i => i.insumoId && Number(i.quantidade) > 0).map(ins => {
    const p = prodById[ins.insumoId] || {};
    const estoque = Number(p.estoque) || 0;
    const enviar = Number(ins.quantidade) || 0;
    return { ins, sku: p.sku || '—', nome: p.nome || p.name || '', estoque, enviar, falta: Math.max(0, enviar - estoque) };
  });
  const temFalta = linhas.some(l => l.falta > 0);
  const confirmar = async () => {
    setBusy(true); setErr('');
    try { const r = await enviarOP(ordem, insumos.filter(i => i.insumoId && Number(i.quantidade) > 0), prodById); if (r.erros && r.erros.length) console.warn('envio: falhas', r.erros); onDone(); }
    catch (e) { setErr(String((e && e.message) || e)); setBusy(false); }
  };
  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 500, background: 'rgba(0,0,0,0.65)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div onClick={e => e.stopPropagation()} style={{ width: 620, maxWidth: '94vw', maxHeight: '88vh', overflow: 'auto', background: 'var(--tm-bg-1)', borderRadius: 'var(--tm-radius-md)', boxShadow: 'var(--tm-shadow-lg)' }}>
        <div style={{ padding: '16px 22px', borderBottom: '1px solid var(--tm-line-1)', fontWeight: 700, fontSize: 15 }}>Enviar {ordem.numero} para a fábrica</div>
        <div style={{ padding: '18px 22px' }}>
          <div style={{ fontSize: 12.5, color: 'var(--tm-fg-3)', marginBottom: 10 }}>Isto <b>baixa</b> os insumos do estoque (vão pra "Em industrialização"):</div>
          <table className="tbl" style={{ fontSize: 12.5 }}>
            <thead><tr><th>Insumo</th><th className="num right">Enviar</th><th className="num right">Em estoque</th><th className="num right">Falta</th></tr></thead>
            <tbody>{linhas.map((l, i) => (
              <tr key={i}><td><span className="ref-mono">{l.sku}</span> {l.nome}</td><td className="num right">{l.enviar}</td>
                <td className="num right muted">{l.estoque}</td>
                <td className="num right" style={{ color: l.falta > 0 ? 'var(--tm-danger)' : 'var(--tm-fg-4)', fontWeight: l.falta > 0 ? 700 : 400 }}>{l.falta > 0 ? `−${l.falta}` : '—'}</td></tr>
            ))}</tbody>
          </table>
          {temFalta && (
            <div style={{ marginTop: 12, padding: '10px 14px', borderRadius: 'var(--tm-radius-sm)', fontSize: 12.5,
              color: 'var(--tm-warning)', background: 'color-mix(in srgb, var(--tm-warning) 12%, transparent)', border: '1px solid color-mix(in srgb, var(--tm-warning) 30%, transparent)' }}>
              Falta estoque de algum insumo — provavelmente uma <b>compra ainda não lançada</b>. Dá pra enviar mesmo assim; o estoque fica em 0 (o "Falta" acima é o que você deve regularizar).
            </div>
          )}
          {err && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{err}</div>}
        </div>
        <div style={{ padding: '14px 22px', borderTop: '1px solid var(--tm-line-1)', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
          <Button variant="secondary" size="sm" onClick={onClose}>Cancelar</Button>
          <Button variant="primary" size="sm" icon="send" onClick={confirmar} disabled={busy}>{busy ? 'Enviando…' : 'Confirmar envio'}</Button>
        </div>
      </div>
    </div>
  );
}

// Recebimento (parcial) — qtd recebida por acabado, serviço rateado por unidade,
// custo calculado (material da ficha + serviço/un) e atualização de produtos.custo com CONFIRMAÇÃO.
function RecebimentoForm({ ordem, itens, insumos, prodById, onClose, onDone }) {
  const [fichas, setFichas] = React.useState(null);   // { produtoId: [linhas] }
  const [servico, setServico] = React.useState(ordem.servico_valor != null ? String(ordem.servico_valor) : '');
  const [rec, setRec] = React.useState({});           // { itemId: qtd }
  const [aplicar, setAplicar] = React.useState({});   // { produtoId: true }
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState('');

  React.useEffect(() => { (async () => {
    const ids = [...new Set((itens || []).map(i => i.produtoId))];
    const map = {};
    for (const id of ids) { map[id] = await window.tmDb.loadFichaTecnica(id); }
    setFichas(map);
    const r0 = {}; (itens || []).forEach(it => { r0[it.id] = Math.max(0, (Number(it.quantidade) || 0) - (Number(it.quantidadeRecebida) || 0)); });
    setRec(r0);
  })(); }, [ordem.id]);

  // custo do insumo: snapshot do envio (op insumo) → fallback custo atual do produto
  const custoInsumoMap = {};
  (insumos || []).forEach(ins => { custoInsumoMap[ins.insumoId] = ins.custoUnitario != null ? Number(ins.custoUnitario) : (prodById[ins.insumoId] ? Number(prodById[ins.insumoId].custo) || 0 : 0); });
  (itens || []).forEach(it => { (fichas && fichas[it.produtoId] || []).forEach(fl => { if (custoInsumoMap[fl.insumoId] == null) custoInsumoMap[fl.insumoId] = prodById[fl.insumoId] ? Number(prodById[fl.insumoId].custo) || 0 : 0; }); });

  const totalUnid = somaQtd(itens);
  const servicoPerUnit = totalUnid > 0 ? (Number(servico) || 0) / totalUnid : 0;

  const custoDoItem = (it) => custoUnitarioAcabado((fichas && fichas[it.produtoId]) || [], custoInsumoMap, servicoPerUnit);
  const nomeDe = (id) => { const p = prodById[id]; return p ? (p.nome || p.name) : '—'; };
  const skuDe = (id) => { const p = prodById[id]; return p ? p.sku : '—'; };
  const fmtPct = (n) => (n >= 0 ? '+' : '') + (Number(n) || 0).toFixed(1).replace('.', ',') + '%';

  const algumRecebe = (itens || []).some(it => (Number(rec[it.id]) || 0) > 0);

  const confirmar = async () => {
    if (!algumRecebe) { setErr('Informe a quantidade recebida de ao menos um acabado.'); return; }
    setBusy(true); setErr('');
    const custoPorItem = {}; (itens || []).forEach(it => { custoPorItem[it.id] = custoDoItem(it); });
    const aplicarSet = new Set(Object.keys(aplicar).filter(pid => aplicar[pid]));
    try {
      const r = await receberOP(ordem, itens, rec, custoPorItem, Number(servico) || 0, aplicarSet, prodById);
      if (r.erros && r.erros.length) console.warn('recebimento: falhas', r.erros);
      onDone();
    } catch (e) { setErr(String((e && e.message) || e)); setBusy(false); }
  };

  return (
    <Drawer open={true} width={720} title={`Receber produção · ${ordem.numero}`}
      subtitle="Dê entrada no acabado; o custo é calculado (material + serviço rateado por unidade)"
      onClose={onClose}
      footer={<><span style={{ flex: 1 }} />
        <Button variant="secondary" size="sm" onClick={onClose}>Cancelar</Button>
        <Button variant="primary" size="sm" icon="check" onClick={confirmar} disabled={busy || !fichas}>{busy ? 'Recebendo…' : 'Confirmar recebimento'}</Button></>}>
      {!fichas ? <div style={{ padding: '20px 0', color: 'var(--tm-fg-3)' }}>Carregando fichas…</div> : (<>
        <div className="field-grid-2" style={{ marginBottom: 4 }}>
          <Field label="Serviço da fábrica (R$)" hint="Da NF de retorno — rateado por unidade produzida">
            <input className="input" type="number" min="0" step="0.01" placeholder="0,00" value={servico} onChange={e => setServico(e.target.value)} style={{ textAlign: 'right' }} />
          </Field>
          <div style={{ alignSelf: 'end', fontSize: 12, color: 'var(--tm-fg-4)', paddingBottom: 8 }}>
            {totalUnid > 0 ? `= R$ ${brl(servicoPerUnit)} por unidade (${totalUnid} un no lote)` : ''}
          </div>
        </div>

        <table className="tbl" style={{ fontSize: 12.5 }}>
          <thead><tr>
            <th>Acabado</th><th style={{ width: 80 }} className="num right">Falta</th>
            <th style={{ width: 90 }} className="num right">Receber</th>
            <th style={{ width: 150 }} className="num right">Custo calculado</th>
            <th style={{ width: 150 }} className="num right">Custo atual</th>
            <th style={{ width: 130 }}>Atualizar custo?</th>
          </tr></thead>
          <tbody>
            {(itens || []).map((it) => {
              const falta = Math.max(0, (Number(it.quantidade) || 0) - (Number(it.quantidadeRecebida) || 0));
              const novo = custoDoItem(it);
              const atual = prodById[it.produtoId] ? Number(prodById[it.produtoId].custo) || 0 : 0;
              const diff = atual > 0 ? ((novo - atual) / atual) * 100 : null;
              return (
                <tr key={it.id}>
                  <td><span className="ref-mono">{skuDe(it.produtoId)}</span> {nomeDe(it.produtoId)}</td>
                  <td className="num right muted">{falta}</td>
                  <td className="num right"><input className="input" type="number" min="0" step="1" value={rec[it.id] != null ? rec[it.id] : ''} onChange={e => setRec(s => ({ ...s, [it.id]: e.target.value }))} style={{ padding: '4px 8px', textAlign: 'right', width: 74 }} /></td>
                  <td className="num right" style={{ fontWeight: 600 }}>R$ {brl(novo)}</td>
                  <td className="num right muted">R$ {brl(atual)}{diff != null && <span style={{ marginLeft: 6, color: Math.abs(diff) < 0.05 ? 'var(--tm-fg-4)' : (diff > 0 ? 'var(--tm-danger)' : 'var(--tm-success)') }}>{fmtPct(diff)}</span>}</td>
                  <td><label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12 }}><input type="checkbox" checked={!!aplicar[it.produtoId]} onChange={e => setAplicar(s => ({ ...s, [it.produtoId]: e.target.checked }))} /> atualizar</label></td>
                </tr>
              );
            })}
          </tbody>
        </table>
        <div style={{ fontSize: 11.5, color: 'var(--tm-fg-4)', marginTop: 10 }}>
          O <b>custo calculado</b> = material da ficha (custo dos insumos) + serviço da fábrica ÷ unidades do lote. Marcar <b>atualizar</b> grava esse valor em <b>produtos.custo</b> (custo de reposição, pras vendas futuras) — <b>nunca</b> reescreve a margem histórica (o snapshot dos pedidos passados fica intacto). Recebimento parcial: cada unidade recebida carrega sua parte do serviço.
        </div>
        {err && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{err}</div>}
      </>)}
    </Drawer>
  );
}

// ─── Pedido de Compra (Fase 1 da corrente de compra) ─────────────────────────
// Categorias = as de CMV_CATS do DRE (a Naii escolhe; default Embalagens → CMV).
const COMPRA_CATEGORIAS = ['Embalagens', 'Matéria-prima', 'Produção', 'Frete'];
const PC_STATUS = {
  rascunho:        { l: 'Rascunho',     tone: 'neutral' },
  enviado:         { l: 'Enviado',      tone: 'info' },
  recebido_parcial:{ l: 'Recebido parcial', tone: 'warning' },
  concluido:       { l: 'Concluído',    tone: 'success' },
  cancelado:       { l: 'Cancelado',    tone: 'danger' },
};
function gerarNumPC() {
  const p2 = (n) => String(n).padStart(2, '0');
  const d = new Date();
  return `PC-${String(d.getFullYear()).slice(2)}${p2(d.getMonth() + 1)}${p2(d.getDate())}-${p2(d.getHours())}${p2(d.getMinutes())}`;
}

function PedidosCompra({ onNav }) {   // eslint-disable-line no-unused-vars
  const pcs = usePedidosCompra();
  const prodHook = useProdutosList([]);
  const fornHook = useFornecedoresList([]);
  const empresasHook = useEmpresasList([]);
  const [novo, setNovo] = React.useState(false);
  const [editando, setEditando] = React.useState(null);
  const [detalhe, setDetalhe] = React.useState(null);
  const [doc, setDoc] = React.useState(null);
  const [receber, setReceber] = React.useState(null);      // { pedido, itens } — check-in (Fase 2)
  const [encerrar, setEncerrar] = React.useState(null);    // { pedido, itens } — encerrar pendência (2b)
  const [estorno, setEstorno]   = React.useState(null);    // { pedido, itens } — estorno de recebimento (2b)
  const [nota, setNota]         = React.useState(null);    // { pedido, itens } — nota de entrada XML (Fase 3)
  const [qtdDaNota, setQtdDaNota] = React.useState(null);  // { itemId: qtd } — pré-preenche o check-in
  const [busy, setBusy] = React.useState(false);

  const prodById = {}; (prodHook.rows || []).forEach(p => { prodById[p.id] = p; });
  const fornById = {}; (fornHook.rows || []).forEach(f => { fornById[f.id] = f; });
  // Qualquer fornecedor ativo pode receber um pedido de compra (uma fábrica também
  // vende insumo). Não filtramos por tipo aqui — senão os fornecedores já cadastrados
  // (tipo 'fabrica' por padrão) somem e o botão "Novo pedido" fica desabilitado (B1).
  const fornecedores = (fornHook.rows || []).filter(f => f.situacao !== 'Arquivado');
  const insumos = (prodHook.rows || []).filter(p => (p.tipo || 'venda') === 'insumo');
  const fornNome = (id) => (fornById[id] && fornById[id].nome) || '—';
  const fmtD = (iso) => iso ? (fmtDate(iso) || String(iso).slice(0, 10).split('-').reverse().join('/')) : '—';

  const recarregar = () => { pcs.reload(); };
  const abrir = async (pc, setter) => { setBusy(true); const d = await window.tmDb.loadPedidoCompra(pc.id); setBusy(false); setter({ pedido: pc, itens: d.itens }); };
  const marcarEnviado = async (pc) => { await window.tmSupabase.from('pedidos_compra').update({ status: 'enviado' }).eq('id', pc.id); recarregar(); };
  const cancelar = async (pc) => { if (confirm(`Cancelar o pedido de compra ${pc.numero}?`)) { await window.tmSupabase.from('pedidos_compra').update({ status: 'cancelado' }).eq('id', pc.id); recarregar(); } };

  return (
    <div className="canvas">
      <PageHead title="Estoque · Pedido de Compra" sub={`${(pcs.rows || []).length} pedido${(pcs.rows || []).length !== 1 ? 's' : ''}`}
        right={<Button variant="primary" icon="plus" size="sm" disabled={fornecedores.length === 0} onClick={() => setNovo(true)}>Novo pedido</Button>} />

      {fornecedores.length === 0 && (
        <div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: '0 0 16px', padding: '10px 14px', borderRadius: 'var(--tm-radius-sm)', fontSize: 12.5,
          color: 'var(--tm-warning)', background: 'color-mix(in srgb, var(--tm-warning) 12%, transparent)', border: '1px solid color-mix(in srgb, var(--tm-warning) 30%, transparent)' }}>
          <Icon name="alert-circle" size={15} /> <span>Cadastre um <b>fornecedor</b> primeiro em <b>Estoque › Fornecedores</b>.</span>
        </div>
      )}

      <Card>
        {(pcs.rows || []).length === 0 ? (
          <div style={{ padding: '48px 0', textAlign: 'center', color: 'var(--tm-fg-3)' }}>
            <Icon name="clipboard-list" size={36} style={{ opacity: 0.3, marginBottom: 12 }} />
            <div style={{ fontSize: 14, marginBottom: 6 }}>Nenhum pedido de compra</div>
            <div style={{ fontSize: 12 }}>Compre insumos do fornecedor; o recebimento (próxima fase) dá entrada no estoque.</div>
          </div>
        ) : (
          <table className="tbl">
            <thead><tr><th>Nº</th><th>Fornecedor</th><th>Categoria</th><th>Previsão</th><th>Status</th><th className="num right">Total</th><th></th></tr></thead>
            <tbody>
              {(pcs.rows || []).map(pc => {
                const st = PC_STATUS[pc.status] || PC_STATUS.rascunho;
                return (
                  <tr key={pc.id} className="clickable" onClick={() => abrir(pc, setDetalhe)}>
                    <td><span className="ref-mono gold">{pc.numero}</span></td>
                    <td>{fornNome(pc.fornecedor_id)}</td>
                    <td className="muted">{pc.categoria || '—'}</td>
                    <td className="muted">{fmtD(pc.data_prevista)}</td>
                    <td><Badge tone={st.tone}>{st.l}</Badge></td>
                    <td className="num right cell-money">R$ {brl(pc.valor_total)}</td>
                    <td onClick={e => e.stopPropagation()} style={{ whiteSpace: 'nowrap' }}>
                      <Button variant="ghost" size="sm" icon="eye" title="Ver detalhes" onClick={() => abrir(pc, setDetalhe)} />
                      <Button variant="ghost" size="sm" icon="printer" disabled={busy} title="Documento p/ o fornecedor" onClick={() => abrir(pc, setDoc)} />
                      {pc.status === 'rascunho' && <Button variant="ghost" size="sm" icon="pencil" disabled={busy} title="Editar" onClick={() => abrir(pc, setEditando)} />}
                      {pc.status === 'rascunho' && <Button variant="ghost" size="sm" icon="send" disabled={busy} title="Marcar como enviado" onClick={() => marcarEnviado(pc)} />}
                      {(pc.status === 'enviado' || pc.status === 'recebido_parcial') && <Button variant="ghost" size="sm" icon="package-check" disabled={busy} title="Receber / Check-in" onClick={() => abrir(pc, setReceber)} />}
                      {(pc.status === 'enviado' || pc.status === 'recebido_parcial' || pc.status === 'concluido') && <Button variant="ghost" size="sm" icon="file-input" disabled={busy} title="Nota de entrada (XML)" onClick={() => abrir(pc, setNota)} />}
                      {pc.status === 'recebido_parcial' && <Button variant="ghost" size="sm" icon="flag-off" disabled={busy} title="Encerrar pendência (não vou receber o resto)" onClick={() => abrir(pc, setEncerrar)} />}
                      {(pc.status === 'recebido_parcial' || pc.status === 'concluido') && <Button variant="ghost" size="sm" icon="rotate-ccw" disabled={busy} title="Estornar recebimento" onClick={() => abrir(pc, setEstorno)} />}
                      {(pc.status === 'rascunho' || pc.status === 'enviado') && <Button variant="ghost" size="sm" icon="x-circle" disabled={busy} title="Cancelar" onClick={() => cancelar(pc)} />}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </Card>

      {novo && <PedidoCompraForm fornecedores={fornecedores} reload={fornHook.reload} empresas={empresasHook.rows || []} insumos={insumos} produtos={prodHook.rows || []} prodById={prodById}
        onClose={() => setNovo(false)} onSaved={() => { setNovo(false); recarregar(); }} />}
      {editando && <PedidoCompraForm edit={editando} fornecedores={fornecedores} reload={fornHook.reload} empresas={empresasHook.rows || []} insumos={insumos} produtos={prodHook.rows || []} prodById={prodById}
        onClose={() => setEditando(null)} onSaved={() => { setEditando(null); recarregar(); }} />}
      {detalhe && <PedidoCompraDetalhe pedido={detalhe.pedido} itens={detalhe.itens} prodById={prodById} fornNome={fornNome} onClose={() => setDetalhe(null)} />}
      {doc && <PedidoCompraDoc pedido={doc.pedido} itens={doc.itens} prodById={prodById} fornecedor={fornById[doc.pedido.fornecedor_id]}
        empresa={(empresasHook.rows || []).find(e => e.id === doc.pedido.empresa_id)} onClose={() => setDoc(null)} />}
      {receber && <RecebimentoCompraForm pedido={receber.pedido} itens={receber.itens} prodById={prodById} fornNome={fornNome}
        qtdSugeridas={qtdDaNota}
        onClose={() => { setReceber(null); setQtdDaNota(null); }}
        onDone={() => { setReceber(null); setQtdDaNota(null); recarregar(); prodHook.reload && prodHook.reload(); }} />}
      {encerrar && <EncerrarPendenciaConfirm pedido={encerrar.pedido} itens={encerrar.itens} prodById={prodById}
        onClose={() => setEncerrar(null)} onDone={() => { setEncerrar(null); recarregar(); }} />}
      {estorno && <EstornoRecebimentoConfirm pedido={estorno.pedido} itens={estorno.itens} prodById={prodById}
        onClose={() => setEstorno(null)} onDone={() => { setEstorno(null); recarregar(); prodHook.reload && prodHook.reload(); }} />}
      {nota && <NotaEntradaForm pedido={nota.pedido} itens={nota.itens} prodById={prodById} insumos={insumos}
        fornecedor={fornById[nota.pedido.fornecedor_id]}
        onClose={() => { setNota(null); recarregar(); }}
        onRegistrada={recarregar}
        onIrParaCheckin={async (qtds) => {
          // recarrega os itens: o preco_nota acabou de ser gravado pela nota
          const d = await window.tmDb.loadPedidoCompra(nota.pedido.id);
          setQtdDaNota(qtds); setReceber({ pedido: nota.pedido, itens: d.itens }); setNota(null);
        }} />}
    </div>
  );
}

// Bloco de rótulo de seção do form (padrão Bling: cabeçalho em blocos)
function PCSecao({ children }) {
  return <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.08em',
    color: 'var(--tm-fg-4)', margin: '18px 0 6px', paddingBottom: 4, borderBottom: '1px solid var(--tm-line-1)' }}>{children}</div>;
}
const FRETE_CONTA_OPTS = ['Remetente (CIF)', 'Destinatário (FOB)'];

// ⚠️ Fora do componente de propósito: componente declarado DENTRO do corpo do pai
// ganha identidade nova a cada render, o React remonta o <input> e o campo perde o
// foco a cada tecla. Já foi bug aqui — não mova pra dentro.
function PCNum({ v, on, ro, w = 78, step = '0.01', ph = '0,00' }) {
  return <input className="input" type="number" min="0" step={step} placeholder={ph}
    value={v != null ? v : ''} disabled={ro} onChange={e => on(e.target.value)}
    style={{ padding: '4px 8px', textAlign: 'right', width: w }} />;
}

function PedidoCompraForm({ edit, fornecedores, reload, empresas, insumos, produtos, prodById, onClose, onSaved }) {
  const ehEdicao = !!edit;
  const p = ehEdicao ? edit.pedido : null;
  // ⚠️ salvarPedidoCompra faz DELETE+INSERT dos itens. Em pedido já recebido isso
  // zeraria quantidade_recebida e preco_nota — por isso só rascunho é editável.
  const soLeitura = ehEdicao && (p.status || 'rascunho') !== 'rascunho';

  const [fornecedorId, setFornecedorId] = React.useState(ehEdicao ? (p.fornecedor_id || '') : '');
  const [empresaId, setEmpresaId] = React.useState(ehEdicao ? (p.empresa_id || '') : empresaAtivaPadrao(empresas));
  const [categoria, setCategoria] = React.useState(ehEdicao ? (p.categoria || 'Embalagens') : 'Embalagens');
  const [dataCompra, setDataCompra] = React.useState(ehEdicao ? String(p.data_emissao || '').slice(0, 10) : hojeIso());
  const [dataPrevista, setDataPrevista] = React.useState(ehEdicao ? String(p.data_prevista || '').slice(0, 10) : '');
  const [numeroForn, setNumeroForn] = React.useState(ehEdicao ? (p.numero_fornecedor || '') : '');
  const [condPag, setCondPag] = React.useState(ehEdicao ? (p.cond_pagamento || '') : '');
  const [parcelas, setParcelas] = React.useState(ehEdicao && Array.isArray(p.parcelas) ? p.parcelas : []);
  const [desconto, setDesconto] = React.useState(ehEdicao ? (p.desconto != null ? p.desconto : '') : '');
  const [frete, setFrete] = React.useState(ehEdicao ? (p.frete != null ? p.frete : '') : '');
  const [icmsSt, setIcmsSt] = React.useState(ehEdicao ? (p.total_icms_st != null ? p.total_icms_st : '') : '');
  const [transp, setTransp] = React.useState(ehEdicao && p.transportador ? p.transportador : { nome: '', freteConta: FRETE_CONTA_OPTS[0], volumes: '', pesoBruto: '' });
  const [obs, setObs] = React.useState(ehEdicao ? (p.observacoes || '') : '');
  const [obsInt, setObsInt] = React.useState(ehEdicao ? (p.observacoes_internas || '') : '');
  const [linhas, setLinhas] = React.useState(ehEdicao
    ? (edit.itens || []).map(i => ({ insumoId: i.insumoId, quantidade: i.quantidade,
        precoCompra: i.precoCompra != null ? i.precoCompra : '',
        descontoPct: i.descontoPct || '', ipiPct: i.ipiPct || '', codigoFornecedor: '' }))
    : [{ insumoId: '', quantidade: 1, precoCompra: '', descontoPct: '', ipiPct: '', codigoFornecedor: '' }]);
  const [dePara, setDePara] = React.useState({});     // cProd → produtoId (do fornecedor escolhido)
  const [saving, setSaving] = React.useState(false);
  const [err, setErr] = React.useState('');
  const { contas } = useContasBancarias();

  // de-para do fornecedor: preenche o "Cód. fornecedor" sozinho e casa o XML depois
  React.useEffect(() => { (async () => {
    if (!fornecedorId || !window.carregarDePara) { setDePara({}); return; }
    const m = await window.carregarDePara(fornecedorId);
    setDePara(m || {});
    const inverso = {}; Object.keys(m || {}).forEach(cod => { inverso[m[cod]] = cod; });
    setLinhas(rows => rows.map(l => (l.insumoId && !l.codigoFornecedor && inverso[l.insumoId])
      ? { ...l, codigoFornecedor: inverso[l.insumoId] } : l));
  })(); }, [fornecedorId]);   // eslint-disable-line

  // Insumo primeiro (caminho comum), acabado depois — ela às vezes compra pronto
  // pra revender, e antes isso simplesmente não cabia no pedido de compra.
  const listaCompra = (produtos && produtos.length ? produtos : insumos) || [];
  const opts = [...listaCompra]
    .sort((a, b) => {
      const ta = (a.tipo || 'venda') === 'insumo' ? 0 : 1;
      const tb = (b.tipo || 'venda') === 'insumo' ? 0 : 1;
      return ta !== tb ? ta - tb : String(a.sku || '').localeCompare(String(b.sku || ''));
    })
    .map(x => ({ value: x.id, label: `${x.sku} · ${x.nome || x.name}${(x.tipo || 'venda') === 'insumo' ? '' : '  · acabado'}` }));

  const prodDe = (id) => prodById[id] || {};
  const skuDe = (id) => prodDe(id).sku || '';
  const unDe  = (id) => prodDe(id).unidade || 'UN';
  const custoDe = (id) => Number(prodDe(id).custo) || 0;

  const setLinha = (i, patch) => setLinhas(rows => rows.map((r, idx) => idx === i ? { ...r, ...patch } : r));
  const addLinha = () => setLinhas(rows => [...rows, { insumoId: '', quantidade: 1, precoCompra: '', descontoPct: '', ipiPct: '', codigoFornecedor: '' }]);
  const rmLinha = (i) => setLinhas(rows => rows.length > 1 ? rows.filter((_, idx) => idx !== i) : rows);

  const r2 = (x) => Math.round((Number(x) || 0) * 100) / 100;
  const brutoDa   = (l) => (Number(l.quantidade) || 0) * (Number(l.precoCompra) || 0);
  const liquidoDa = (l) => r2(brutoDa(l) * (1 - (Number(l.descontoPct) || 0) / 100));
  const ipiDa     = (l) => r2(liquidoDa(l) * ((Number(l.ipiPct) || 0) / 100));

  const validas       = linhas.filter(l => l.insumoId && Number(l.quantidade) > 0);
  const totalProdutos = r2(validas.reduce((a, l) => a + liquidoDa(l), 0));
  const totalIpi      = r2(validas.reduce((a, l) => a + ipiDa(l), 0));
  const somaQtdes     = validas.reduce((a, l) => a + (Number(l.quantidade) || 0), 0);
  const totalPedido   = r2(totalProdutos + totalIpi + (Number(icmsSt) || 0) + (Number(frete) || 0) - (Number(desconto) || 0));

  const gerarParcelas = () => {
    if (!condPag) { setErr('Informe a condição de pagamento (ex.: 30/60/90).'); return; }
    setErr('');
    // parseParcelas é compartilhado com a venda e cai em "Dinheiro" quando a
    // condição não diz a forma ("30/60/90"). Em compra de fornecedor o padrão é
    // boleto — troco só aqui, sem mexer no comportamento da venda.
    const geradas = window.parseParcelas(condPag, totalPedido, fmtDate(dataCompra) || window.hojeBR());
    setParcelas(geradas.map(par => ({ ...par, forma: par.forma === 'Dinheiro' ? 'Boleto' : par.forma, conta: '' })));
  };
  const diffParcelas = parcelas.length ? window.diferencaParcelas(totalPedido, parcelas) : 0;

  const salvar = async () => {
    if (soLeitura) return;
    if (!fornecedorId) { setErr('Escolha o fornecedor.'); return; }
    if (!validas.length) { setErr('Adicione ao menos um item com quantidade.'); return; }
    if (parcelas.length && diffParcelas !== 0) { setErr(`As parcelas não fecham com o total (diferença de R$ ${brl(Math.abs(diffParcelas))}).`); return; }
    setSaving(true); setErr('');

    // Número: sequência do BANCO. Se falhar, NÃO inventamos número — aborta.
    let numero = ehEdicao ? p.numero : null;
    if (!numero) {
      const rn = await window.tmDb.proximoNumeroPC();
      if (rn.error || !rn.numero) {
        setSaving(false);
        setErr('Não consegui gerar o número do pedido: ' + ((rn.error && rn.error.message) || 'sem resposta do banco') + '. O pedido não foi salvo.');
        return;
      }
      numero = rn.numero;
    }

    const draft = {
      id: ehEdicao ? p.id : undefined, numero,
      fornecedor_id: fornecedorId, empresa_id: empresaId || null, categoria,
      status: ehEdicao ? p.status : 'rascunho',
      data_emissao: dataCompra || hojeIso(), data_prevista: dataPrevista || null,
      numero_fornecedor: numeroForn || null,
      cond_pagamento: condPag || null,
      forma_pagamento: parcelas.length ? (parcelas[0].forma || null) : null,
      parcelas: parcelas.length ? parcelas : null,
      total_produtos: totalProdutos, desconto: Number(desconto) || 0, frete: Number(frete) || 0,
      total_ipi: totalIpi, total_icms_st: Number(icmsSt) || 0,
      valor_total: totalPedido,
      transportador: (transp.nome || transp.volumes || transp.pesoBruto) ? transp : null,
      observacoes: obs || null, observacoes_internas: obsInt || null,
      itens: validas.map(l => ({ insumoId: l.insumoId, quantidade: Number(l.quantidade) || 0,
        precoCompra: l.precoCompra, descontoPct: l.descontoPct, ipiPct: l.ipiPct })),
    };
    const r = await window.tmDb.salvarPedidoCompra(draft);
    if (r.error) { setSaving(false); setErr(r.error.message || 'Erro ao salvar.'); return; }

    // guarda o de-para do que ela digitou — é o que faz o XML da próxima nota casar
    const paraMapear = validas.filter(l => l.codigoFornecedor && l.codigoFornecedor.trim())
      .map(l => ({ cProd: l.codigoFornecedor.trim(), xProd: prodDe(l.insumoId).nome || '', produtoId: l.insumoId }));
    if (paraMapear.length && window.salvarDePara) {
      try { await window.salvarDePara(fornecedorId, paraMapear); } catch (e) { console.warn('de-para nao salvo', e); }
    }
    setSaving(false);
    onSaved();
  };

  return (
    <Drawer open={true} width={1040}
      title={ehEdicao ? `${soLeitura ? 'Pedido' : 'Editar'} ${p.numero}` : 'Novo pedido de compra'}
      subtitle={soLeitura ? 'Somente leitura — pedido já saiu do rascunho' : 'Compra do fornecedor · o recebimento dá entrada no estoque'}
      onClose={onClose}
      footer={<><span style={{ flex: 1 }} />
        <Button variant="secondary" size="sm" onClick={onClose}>{soLeitura ? 'Fechar' : 'Cancelar'}</Button>
        {!soLeitura && <Button variant="primary" size="sm" icon="check" onClick={salvar} disabled={saving}>{saving ? 'Salvando…' : `Salvar rascunho (R$ ${brl(totalPedido)})`}</Button>}</>}>

      {soLeitura && (
        <div style={{ display: 'flex', gap: 8, alignItems: 'flex-start', padding: '10px 12px', borderRadius: 8,
                      background: 'rgba(107,163,214,0.10)', border: '1px solid var(--tm-info)', marginBottom: 6, fontSize: 12.5, lineHeight: 1.6 }}>
          <Icon name="lock" size={15} style={{ flexShrink: 0, marginTop: 2, color: 'var(--tm-info)' }} />
          <span>Este pedido está <b>{(PC_STATUS[p.status] || {}).l || p.status}</b> e não pode mais ser editado aqui: salvar substituiria os itens
            e apagaria o que já foi conferido no recebimento (quantidade recebida, avaria e preço da nota). Para corrigir, use
            <b> Estornar recebimento</b> na lista.</span>
        </div>
      )}

      <PCSecao>Fornecedor</PCSecao>
      {/* Em leitura os seletores viram TEXTO: SearchableSelect/CategoriaSelect têm
          estado interno próprio e continuariam digitáveis mesmo com onChange vazio. */}
      <div className="field-grid-3">
        {soLeitura ? (<>
          <Field label="Fornecedor"><div className="input" style={{ display: 'flex', alignItems: 'center', color: 'var(--tm-fg-2)' }}>
            {(fornecedores.find(f => f.id === fornecedorId) || {}).nome || '—'}</div></Field>
          <Field label="Categoria"><div className="input" style={{ display: 'flex', alignItems: 'center', color: 'var(--tm-fg-2)' }}>{categoria || '—'}</div></Field>
          <Field label="Empresa"><div className="input" style={{ display: 'flex', alignItems: 'center', color: 'var(--tm-fg-2)' }}>
            {(() => { const e = (empresas || []).find(x => x.id === empresaId); return e ? (e.nome_fantasia || e.razao_social || e.nome) : '—'; })()}</div></Field>
        </>) : (<>
          <FornecedorSelect label="Fornecedor" required value={fornecedorId} onChange={setFornecedorId}
            fornecedores={fornecedores} reload={reload} empresaId={empresaId} />
          <CategoriaSelect label="Categoria" value={categoria} onChange={setCategoria} contexto="compra" />
          <EmpresaSelect value={empresaId} onChange={setEmpresaId} empresas={empresas} />
        </>)}
      </div>

      <PCSecao>Itens do pedido de compra</PCSecao>
      <table className="tbl" style={{ fontSize: 12.5 }}>
        <thead><tr>
          <th style={{ minWidth: 180 }}>Item</th>
          <th style={{ width: 78 }}>Código</th>
          <th style={{ width: 104 }}>Cód. forn.</th>
          <th style={{ width: 44 }}>Un</th>
          <th style={{ width: 74 }} className="num right">Qtde</th>
          <th style={{ width: 86 }} className="num right">Preço un</th>
          <th style={{ width: 64 }} className="num right">Desc. %</th>
          <th style={{ width: 60 }} className="num right">IPI %</th>
          <th style={{ width: 96 }} className="num right">Preço total</th>
          <th style={{ width: 32 }}></th>
        </tr></thead>
        <tbody>
          {linhas.map((l, i) => (
            <tr key={i}>
              <td>{soLeitura
                ? <span>{skuDe(l.insumoId)} · {prodDe(l.insumoId).nome || ''}</span>
                : <SearchableSelect value={l.insumoId} options={opts} placeholder="Buscar item (SKU/nome)…"
                    onChange={(id) => setLinha(i, { insumoId: id,
                      precoCompra: l.precoCompra === '' ? (custoDe(id) || '') : l.precoCompra,
                      codigoFornecedor: l.codigoFornecedor || (Object.keys(dePara).find(c => dePara[c] === id) || '') })} />}</td>
              <td className="muted"><span className="ref-mono">{skuDe(l.insumoId) || '—'}</span></td>
              <td><input className="input" value={l.codigoFornecedor || ''} placeholder={fornecedorId ? 'código dele' : 'escolha o fornecedor'}
                    disabled={soLeitura || !fornecedorId}
                    onChange={e => setLinha(i, { codigoFornecedor: e.target.value })} style={{ padding: '4px 8px', width: 96 }} /></td>
              <td className="muted">{l.insumoId ? unDe(l.insumoId) : '—'}</td>
              <td className="num right"><PCNum v={l.quantidade} on={v => setLinha(i, { quantidade: v })} ro={soLeitura} w={64} step="1" ph="0" /></td>
              <td className="num right"><PCNum v={l.precoCompra} on={v => setLinha(i, { precoCompra: v })} ro={soLeitura} /></td>
              <td className="num right"><PCNum v={l.descontoPct} on={v => setLinha(i, { descontoPct: v })} ro={soLeitura} w={54} step="0.01" ph="0" /></td>
              <td className="num right"><PCNum v={l.ipiPct} on={v => setLinha(i, { ipiPct: v })} ro={soLeitura} w={50} step="0.01" ph="0" /></td>
              <td className="num right" style={{ fontWeight: 600, whiteSpace: 'nowrap' }}>R$ {brl(liquidoDa(l))}</td>
              <td>{!soLeitura && linhas.length > 1 && <Button variant="ghost" size="sm" icon="x" title="Remover" onClick={() => rmLinha(i)} />}</td>
            </tr>
          ))}
        </tbody>
      </table>
      {!soLeitura && <div style={{ marginTop: 8 }}><Button variant="secondary" size="sm" icon="plus" onClick={addLinha}>Adicionar item</Button></div>}

      <PCSecao>Totais da compra</PCSecao>
      <div className="field-grid-4">
        <Field label="Total dos produtos"><div className="input" style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>R$ {brl(totalProdutos)}</div></Field>
        <Field label="Total do IPI"><div className="input" style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>R$ {brl(totalIpi)}</div></Field>
        <Field label="Total ICMS ST (R$)"><input className="input" type="number" min="0" step="0.01" placeholder="0,00" value={icmsSt} disabled={soLeitura} onChange={e => setIcmsSt(e.target.value)} style={{ textAlign: 'right' }} /></Field>
        <Field label="Total do pedido">
          <div className="input" style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end', fontWeight: 700, color: 'var(--tm-brand-champagne)' }}>R$ {brl(totalPedido)}</div>
        </Field>
      </div>
      <div className="field-grid-4">
        <Field label="Nº de itens"><div className="input" style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>{validas.length}</div></Field>
        <Field label="Soma das qtdes"><div className="input" style={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>{somaQtdes}</div></Field>
        <Field label="Desconto (R$)"><input className="input" type="number" min="0" step="0.01" placeholder="0,00" value={desconto} disabled={soLeitura} onChange={e => setDesconto(e.target.value)} style={{ textAlign: 'right' }} /></Field>
        <Field label="Frete (R$)"><input className="input" type="number" min="0" step="0.01" placeholder="0,00" value={frete} disabled={soLeitura} onChange={e => setFrete(e.target.value)} style={{ textAlign: 'right' }} /></Field>
      </div>

      <PCSecao>Detalhes da compra</PCSecao>
      <div className="field-grid-4">
        <Field label="Número do pedido"><div className="input" style={{ display: 'flex', alignItems: 'center', color: 'var(--tm-fg-3)' }}>{ehEdicao ? p.numero : 'gerado ao salvar'}</div></Field>
        <Field label="Nº no fornecedor" hint="O número que ele usa pro mesmo pedido"><input className="input" value={numeroForn} disabled={soLeitura} onChange={e => setNumeroForn(e.target.value)} placeholder="Ex.: OC-4471" /></Field>
        <Field label="Data da compra"><input className="input" type="date" value={dataCompra} disabled={soLeitura} onChange={e => setDataCompra(e.target.value)} /></Field>
        <Field label="Previsão de entrega"><input className="input" type="date" value={dataPrevista} disabled={soLeitura} onChange={e => setDataPrevista(e.target.value)} /></Field>
      </div>
      {/* ⚠️ A primitiva Field renderiza um <input> PRÓPRIO quando children é falsy.
          `<Field>{!soLeitura && <Button/>}</Field>` vira children=false em leitura e
          criava um campo de texto editável do nada — por isso o bloco inteiro sai. */}
      <div className="field-grid-2">
        <Field label="Condição de pagamento" hint="Ex.: 30/60/90, à vista, Cartão 3x — opcional">
          <input className="input" value={condPag} disabled={soLeitura} onChange={e => setCondPag(e.target.value)} placeholder="30/60/90" />
        </Field>
        {!soLeitura && (
          <Field label="&nbsp;">
            <Button variant="secondary" size="sm" icon="calendar" onClick={gerarParcelas} disabled={!condPag || !totalPedido}>Gerar parcelas</Button>
          </Field>
        )}
      </div>

      <PCSecao>Parcelas</PCSecao>
      <div style={{ fontSize: 11.5, color: 'var(--tm-fg-4)', marginBottom: 8 }}>
        Opcional — fornecedor que não parcela fica sem nada aqui, e a compra vira <b>um título só</b>, como sempre foi.
        Com parcelas, cada uma vira <b>um título</b> no contas a pagar, com o vencimento certo.
      </div>
      {soLeitura
        ? (parcelas.length
            ? <table className="tbl" style={{ fontSize: 12.5 }}>
                <thead><tr><th style={{ width: 40 }}>Nº</th><th>Vencimento</th><th className="num right">Valor</th><th>Forma</th><th>Conta</th></tr></thead>
                <tbody>{parcelas.map((par, i) => (
                  <tr key={i}><td>{i + 1}</td><td>{par.venc}</td><td className="num right">R$ {brl(par.valor)}</td><td>{par.forma || '—'}</td><td>{par.conta || '—'}</td></tr>))}</tbody>
              </table>
            : <div className="muted" style={{ fontSize: 12.5 }}>Sem parcelas — título único.</div>)
        : <ParcelasEditor parcelas={parcelas} onChange={setParcelas} total={totalPedido}
            contas={contas} dataBase={fmtDate(dataCompra) || ''} formaPadrao="Boleto" />}

      <PCSecao>Transportador</PCSecao>
      <div className="field-grid-4">
        <Field label="Nome"><input className="input" value={transp.nome || ''} disabled={soLeitura} onChange={e => setTransp(t => ({ ...t, nome: e.target.value }))} placeholder="Transportadora" /></Field>
        <Field label="Frete por conta">
          <select className="input" value={transp.freteConta || FRETE_CONTA_OPTS[0]} disabled={soLeitura} onChange={e => setTransp(t => ({ ...t, freteConta: e.target.value }))}>
            {FRETE_CONTA_OPTS.map(f => <option key={f} value={f}>{f}</option>)}
          </select>
        </Field>
        <Field label="Volumes"><input className="input" type="number" min="0" step="1" value={transp.volumes || ''} disabled={soLeitura} onChange={e => setTransp(t => ({ ...t, volumes: e.target.value }))} style={{ textAlign: 'right' }} /></Field>
        <Field label="Peso bruto (kg)"><input className="input" type="number" min="0" step="0.001" value={transp.pesoBruto || ''} disabled={soLeitura} onChange={e => setTransp(t => ({ ...t, pesoBruto: e.target.value }))} style={{ textAlign: 'right' }} /></Field>
      </div>

      <PCSecao>Dados adicionais</PCSecao>
      <Field label="Observações" hint="SAI no documento enviado ao fornecedor">
        <textarea className="input" rows={2} value={obs} disabled={soLeitura} onChange={e => setObs(e.target.value)} placeholder="Instruções pro fornecedor, condições…" />
      </Field>
      <Field label="Observações internas" hint="NÃO sai no documento — só você vê">
        <textarea className="input" rows={2} value={obsInt} disabled={soLeitura} onChange={e => setObsInt(e.target.value)} placeholder="Anotação interna sobre esta compra…" />
      </Field>

      {err && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{err}</div>}
    </Drawer>
  );
}

function PedidoCompraDetalhe({ pedido, itens, prodById, fornNome, onClose }) {
  const st = PC_STATUS[pedido.status] || PC_STATUS.rascunho;
  const nomeDe = (id) => { const x = prodById[id]; return x ? (x.nome || x.name) : '—'; };
  const skuDe = (id) => { const x = prodById[id]; return x ? x.sku : '—'; };
  const fmtD = (iso) => iso ? (fmtDate(iso) || String(iso).slice(0, 10).split('-').reverse().join('/')) : '—';
  const total = (itens || []).reduce((a, it) => a + (Number(it.quantidade) || 0) * (Number(it.precoCompra) || 0), 0);
  return (
    <Drawer open={true} width={680} title={`Pedido ${pedido.numero}`} subtitle={`${fornNome(pedido.fornecedor_id)} · ${st.l}`} onClose={onClose}
      footer={<><span style={{ flex: 1 }} /><Button variant="secondary" size="sm" onClick={onClose}>Fechar</Button></>}>
      <div className="field-grid-3" style={{ marginBottom: 14 }}>
        <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Categoria</div><div>{pedido.categoria || '—'}</div></div>
        <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Previsão</div><div>{fmtD(pedido.data_prevista)}</div></div>
        <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Emissão</div><div>{fmtD(pedido.data_emissao || pedido.created_at)}</div></div>
      </div>
      <table className="tbl" style={{ fontSize: 12.5 }}>
        <thead><tr><th>Insumo</th><th className="num right">Qtd</th><th className="num right">Recebido</th><th className="num right">Preço</th><th className="num right">Subtotal</th></tr></thead>
        <tbody>
          {(itens || []).map((it, i) => (
            <tr key={i}><td><span className="ref-mono">{skuDe(it.insumoId)}</span> {nomeDe(it.insumoId)}</td>
              <td className="num right">{it.quantidade}</td><td className="num right muted">{it.quantidadeRecebida}</td>
              <td className="num right">R$ {brl(it.precoCompra)}</td>
              <td className="num right cell-money">R$ {brl((Number(it.quantidade) || 0) * (Number(it.precoCompra) || 0))}</td></tr>
          ))}
          <tr style={{ borderTop: '2px solid var(--tm-brand-champagne)', fontWeight: 700 }}>
            <td colSpan={4}>Total</td><td className="num right cell-money">R$ {brl(total)}</td>
          </tr>
        </tbody>
      </table>
      {/* Pendência encerrada: vem da COLUNA (Fase 3). As linhas legadas com o
          prefixo PENDENCIA_TAG foram migradas pra coluna, então ficam escondidas
          do texto livre pra não aparecer duas vezes. */}
      {pedido.encerramento_motivo && (
        <div style={{ fontSize: 12.5, marginTop: 12, color: 'var(--tm-warning)', display: 'flex', gap: 6, alignItems: 'flex-start' }}>
          <Icon name="flag-off" size={14} style={{ flexShrink: 0, marginTop: 2 }} />
          <span>Pendência encerrada{pedido.encerramento_data ? ` em ${fmtDate(pedido.encerramento_data) || pedido.encerramento_data}` : ''}: {pedido.encerramento_motivo}</span>
        </div>
      )}
      {pedido.nf_entrada_numero && (
        <div style={{ fontSize: 12.5, marginTop: 8, color: 'var(--tm-fg-3)', display: 'flex', gap: 6, alignItems: 'center' }}>
          <Icon name="file-text" size={14} /> Nota de entrada nº <b>{pedido.nf_entrada_numero}</b>
          {pedido.nf_entrada_chave && <span className="ref-mono" style={{ fontSize: 10.5 }}>{pedido.nf_entrada_chave}</span>}
        </div>
      )}
      {(() => {
        const linhas = String(pedido.observacoes || '').split('\n')
          .filter(l => l.trim() && l.indexOf(PENDENCIA_TAG) !== 0);
        return linhas.length ? (
          <div style={{ fontSize: 12.5, marginTop: 12, color: 'var(--tm-fg-3)' }}>
            {linhas.map((l, i) => <div key={i}>{i === 0 ? 'Obs.: ' : ''}{l}</div>)}
          </div>
        ) : null;
      })()}
    </Drawer>
  );
}

// ─── Check-in de Recebimento (Fase 2 da corrente de compra) ──────────────────
// Mostra o que foi PEDIDO e ela informa o que CHEGOU, item por item. Parcial é
// previsto (o que faltou continua pendente); avaria é registrada SEPARADO e não
// entra no estoque. O custo usa o preço da NOTA (valor fiscal) e só sobe pra
// produtos.custo com confirmação — anterior → novo + variação %.
function RecebimentoCompraForm({ pedido, itens, prodById, fornNome, qtdSugeridas, onClose, onDone }) {
  const [rec, setRec]         = React.useState({});   // { itemId: qtd boa }
  const [avar, setAvar]       = React.useState({});   // { itemId: qtd avariada }
  const [nota, setNota]       = React.useState({});   // { itemId: preço da nota }
  const [aplicar, setAplicar] = React.useState({});   // { insumoId: true }
  const [busy, setBusy]       = React.useState(false);
  const [err, setErr]         = React.useState('');

  React.useEffect(() => {
    const r0 = {}, n0 = {};
    (itens || []).forEach(it => {
      // veio da NF-e? usa a quantidade da nota. Senão, default = o que falta.
      const daNota = qtdSugeridas && qtdSugeridas[it.id] != null ? Number(qtdSugeridas[it.id]) : null;
      r0[it.id] = daNota != null ? daNota
        : Math.max(0, (Number(it.quantidade) || 0) - (Number(it.quantidadeRecebida) || 0));
      n0[it.id] = it.precoNota != null ? String(it.precoNota) : (it.precoCompra != null ? String(it.precoCompra) : '');
    });
    setRec(r0); setNota(n0);
  }, [pedido.id]);   // eslint-disable-line

  const nomeDe = (id) => { const p = prodById[id]; return p ? (p.nome || p.name) : '—'; };
  const skuDe  = (id) => { const p = prodById[id]; return p ? p.sku : '—'; };
  const fmtPct = (n) => (n >= 0 ? '+' : '') + (Number(n) || 0).toFixed(1).replace('.', ',') + '%';

  // custo que vale = preço da NOTA quando informado; senão o do pedido.
  const custoDoItem = (it) => {
    const v = nota[it.id];
    const n = (v === '' || v == null) ? null : Number(v);
    return (n != null && !isNaN(n)) ? n : (Number(it.precoCompra) || 0);
  };
  const divergencia = (it) => {
    const ped = Number(it.precoCompra) || 0;
    const nt  = custoDoItem(it);
    if (!ped || Math.abs(nt - ped) < 0.005) return null;
    return { ped, nt, pct: ped > 0 ? ((nt - ped) / ped) * 100 : null };
  };

  const linhas   = itens || [];
  const algum    = linhas.some(it => (Number(rec[it.id]) || 0) > 0 || (Number(avar[it.id]) || 0) > 0);
  const insumos  = [...new Set(linhas.map(it => it.insumoId))];
  const todosMarcados = insumos.length > 0 && insumos.every(id => !!aplicar[id]);
  const marcarTodos = (v) => { const s = {}; insumos.forEach(id => { s[id] = v; }); setAplicar(s); };

  // prévia do status resultante — ela vê antes de confirmar se fecha ou fica pendente
  const completaria = linhas.every(it =>
    ((Number(it.quantidadeRecebida) || 0) + (Number(rec[it.id]) || 0)) >= (Number(it.quantidade) || 0) - 1e-9);
  const totalAvaria = linhas.reduce((a, it) => a + (Number(avar[it.id]) || 0), 0);

  const confirmar = async () => {
    if (!algum) { setErr('Informe a quantidade recebida (ou avariada) de ao menos um insumo.'); return; }
    setBusy(true); setErr('');
    const aplicarSet = new Set(Object.keys(aplicar).filter(id => aplicar[id]));
    try {
      const r = await receberCompra(pedido, linhas, rec, avar, nota, aplicarSet, prodById);
      if (r.erros && r.erros.length) console.warn('recebimento de compra: falhas', r.erros);
      onDone();
    } catch (e) { setErr(String((e && e.message) || e)); setBusy(false); }
  };

  return (
    <Drawer open={true} width={1000} title={`Receber · ${pedido.numero}`}
      subtitle={`${fornNome ? fornNome(pedido.fornecedor_id) : ''} · confira o que chegou contra o pedido`}
      onClose={onClose}
      footer={<>
        <span style={{ fontSize: 12, color: 'var(--tm-fg-3)' }}>
          Ao confirmar: <b>{completaria ? 'pedido concluído' : 'recebido parcial'}</b>
          {totalAvaria > 0 ? ` · ${totalAvaria} avariado(s) fora do estoque` : ''}
        </span>
        <span style={{ flex: 1 }} />
        <Button variant="secondary" size="sm" onClick={onClose}>Cancelar</Button>
        <Button variant="primary" size="sm" icon="check" onClick={confirmar} disabled={busy}>{busy ? 'Recebendo…' : 'Confirmar recebimento'}</Button></>}>

      <table className="tbl" style={{ fontSize: 12.5 }}>
        <thead><tr>
          <th style={{ minWidth: 190 }}>Insumo</th>
          <th style={{ width: 62 }} className="num right">Pedido</th>
          <th style={{ width: 62 }} className="num right">Falta</th>
          <th style={{ width: 86 }} className="num right">Recebendo</th>
          <th style={{ width: 86 }} className="num right">Avaria</th>
          <th style={{ width: 132 }} className="num right">Preço da nota</th>
          <th style={{ width: 200 }}>
            Custo do insumo
            <label style={{ display: 'flex', alignItems: 'center', gap: 5, fontSize: 11, fontWeight: 400, marginTop: 2, color: 'var(--tm-fg-3)' }}>
              <input type="checkbox" checked={todosMarcados} onChange={e => marcarTodos(e.target.checked)} /> atualizar todos
            </label>
          </th>
        </tr></thead>
        <tbody>
          {linhas.map((it) => {
            const pedida = Number(it.quantidade) || 0;
            const jaRec  = Number(it.quantidadeRecebida) || 0;
            const falta  = Math.max(0, pedida - jaRec);
            const novo   = custoDoItem(it);
            const atual  = prodById[it.insumoId] ? Number(prodById[it.insumoId].custo) || 0 : 0;
            const diff   = atual > 0 ? ((novo - atual) / atual) * 100 : null;
            const dv     = divergencia(it);
            const aMais  = (Number(rec[it.id]) || 0) > falta;
            return (
              <tr key={it.id}>
                <td>
                  <span className="ref-mono">{skuDe(it.insumoId)}</span> {nomeDe(it.insumoId)}
                  {(Number(it.quantidadeAvaria) || 0) > 0 && (
                    <div style={{ fontSize: 11, color: 'var(--tm-warning)', whiteSpace: 'nowrap' }}>{it.quantidadeAvaria} avariado(s) antes</div>
                  )}
                </td>
                <td className="num right muted">
                  {pedida}
                  {jaRec > 0 && <div style={{ fontSize: 10.5, whiteSpace: 'nowrap' }}>{jaRec} já rec.</div>}
                </td>
                <td className="num right" style={{ fontWeight: 600 }}>{falta}</td>
                <td className="num right">
                  <input className="input" type="number" min="0" step="1" value={rec[it.id] != null ? rec[it.id] : ''}
                    onChange={e => setRec(s => ({ ...s, [it.id]: e.target.value }))}
                    style={{ padding: '4px 8px', textAlign: 'right', width: 70 }} />
                  {aMais && <div style={{ fontSize: 10.5, color: 'var(--tm-info)' }}>acima do pedido</div>}
                </td>
                <td className="num right">
                  <input className="input" type="number" min="0" step="1" placeholder="0" value={avar[it.id] != null ? avar[it.id] : ''}
                    onChange={e => setAvar(s => ({ ...s, [it.id]: e.target.value }))}
                    style={{ padding: '4px 8px', textAlign: 'right', width: 70 }} />
                </td>
                <td className="num right">
                  <input className="input" type="number" min="0" step="0.01" value={nota[it.id] != null ? nota[it.id] : ''}
                    onChange={e => setNota(s => ({ ...s, [it.id]: e.target.value }))}
                    style={{ padding: '4px 8px', textAlign: 'right', width: 88 }} />
                  {dv && <div style={{ fontSize: 10.5, color: 'var(--tm-warning)', marginTop: 2 }}>
                    pedido R$ {brl(dv.ped)} · nota R$ {brl(dv.nt)}{dv.pct != null ? ` (${fmtPct(dv.pct)})` : ''}
                  </div>}
                </td>
                <td>
                  <div style={{ whiteSpace: 'nowrap' }}>
                    <span className="muted">R$ {brl(atual)}</span>
                    <span style={{ margin: '0 5px', color: 'var(--tm-fg-4)' }}>→</span>
                    <b>R$ {brl(novo)}</b>
                    {diff != null && <span style={{ marginLeft: 6, color: Math.abs(diff) < 0.05 ? 'var(--tm-fg-4)' : (diff > 0 ? 'var(--tm-danger)' : 'var(--tm-success)') }}>{fmtPct(diff)}</span>}
                  </div>
                  <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, marginTop: 3 }}>
                    <input type="checkbox" checked={!!aplicar[it.insumoId]}
                      onChange={e => setAplicar(s => ({ ...s, [it.insumoId]: e.target.checked }))} /> atualizar
                  </label>
                </td>
              </tr>
            );
          })}
        </tbody>
      </table>

      <div style={{ fontSize: 11.5, color: 'var(--tm-fg-4)', marginTop: 10 }}>
        <b>Recebendo</b> dá <b>Entrada</b> no estoque do insumo. <b>Avaria</b> fica registrada e <b>não entra no estoque</b> —
        "não veio" e "veio quebrado" são problemas diferentes (um é entrega, outro é qualidade do fornecedor), e o que
        faltar continua <b>pendente no pedido</b> pra receber depois. Quem vale pro custo é o <b>preço da nota</b> (o valor
        fiscal, o que você pagou); se divergir do pedido, a diferença aparece na linha. Marcar <b>atualizar</b> grava esse
        preço em <b>produtos.custo</b> (custo de reposição) — isso propaga pro custo do acabado <b>na próxima produção</b> e
        <b> nunca</b> reescreve o histórico (as compras e vendas passadas ficam com o custo delas).
      </div>
      {err && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{err}</div>}
    </Drawer>
  );
}

// ─── Encerrar pendência (Fase 2b) ────────────────────────────────────────────
// Para o pedido que ficou parcial e não vai mais receber o resto. Registra o
// MOTIVO (fica no histórico do pedido, serve pra avaliar o fornecedor depois).
// O que faltou NÃO entra no estoque — só deixa de ficar pendente.
function EncerrarPendenciaConfirm({ pedido, itens, prodById, onClose, onDone }) {
  const [motivo, setMotivo] = React.useState('nao_reposto');
  const [nota, setNota]     = React.useState('');
  const [busy, setBusy]     = React.useState(false);
  const [err, setErr]       = React.useState('');

  const pendentes = (itens || []).map(it => ({
    it, falta: Math.max(0, (Number(it.quantidade) || 0) - (Number(it.quantidadeRecebida) || 0)),
    p: prodById[it.insumoId] || {},
  })).filter(x => x.falta > 0);

  const confirmar = async () => {
    setBusy(true); setErr('');
    try { await encerrarPendenciaCompra(pedido, itens, motivo, nota, prodById); onDone(); }
    catch (e) { setErr(String((e && e.message) || e)); setBusy(false); }
  };

  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 500, background: 'rgba(0,0,0,0.65)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div onClick={e => e.stopPropagation()} style={{ background: 'var(--tm-bg-1)', borderRadius: 14, width: 580, maxHeight: '88vh', overflow: 'auto', border: '1px solid var(--tm-line-1)', boxShadow: '0 24px 64px rgba(0,0,0,0.5)' }}>
        <div style={{ padding: '18px 22px', borderBottom: '1px solid var(--tm-line-1)' }}>
          <div style={{ fontFamily: 'var(--tm-font-display)', fontSize: 18 }}>Encerrar pendência de {pedido.numero}?</div>
          <div className="muted" style={{ fontSize: 12.5, marginTop: 2 }}>Confirma que o restante não vai mais chegar.</div>
        </div>
        <div style={{ padding: '18px 22px', fontSize: 13 }}>
          <div style={{ marginBottom: 8 }}>Fica <b>sem receber</b>:</div>
          <table className="tbl" style={{ fontSize: 12.5, marginBottom: 14 }}>
            <thead><tr><th>Insumo</th><th style={{ width: 90 }} className="num right">Não recebido</th></tr></thead>
            <tbody>
              {pendentes.map(({ it, falta, p }) => (
                <tr key={it.id}><td><span className="ref-mono">{p.sku || '—'}</span> {p.nome || p.name || ''}</td>
                  <td className="num right" style={{ fontWeight: 600 }}>{falta}</td></tr>
              ))}
            </tbody>
          </table>

          <Field label="Motivo *">
            <select className="input" value={motivo} onChange={e => setMotivo(e.target.value)}>
              {PENDENCIA_MOTIVOS.map(m => <option key={m.id} value={m.id}>{m.l}</option>)}
            </select>
          </Field>
          <Field label="Detalhe (opcional)" hint="Fica junto do motivo no histórico do pedido">
            <input className="input" value={nota} onChange={e => setNota(e.target.value)} placeholder="Ex.: fornecedor alegou falta de matéria-prima" />
          </Field>

          <div style={{ fontSize: 12, color: 'var(--tm-fg-4)', marginTop: 12, lineHeight: 1.6 }}>
            O que faltou <b>não entra no estoque</b> — encerrar só para de cobrar a pendência. O pedido vira
            <b> Concluído</b> e o motivo fica registrado nas observações, no histórico do pedido.
          </div>
          {err && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{err}</div>}
        </div>
        <div style={{ padding: '14px 22px', borderTop: '1px solid var(--tm-line-1)', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
          <Button variant="secondary" size="sm" onClick={onClose}>Voltar</Button>
          <Button variant="primary" size="sm" icon="check" onClick={confirmar} disabled={busy}>{busy ? 'Encerrando…' : 'Encerrar pendência'}</Button>
        </div>
      </div>
    </div>
  );
}

// ─── Estornar recebimento (Fase 2b) ──────────────────────────────────────────
// Corrige erro de digitação sem lançamento manual ao contrário: gera movimento
// de estoque INVERSO auditável (o original não é apagado), devolve a quantidade
// pra pendente e reabre o status.
function EstornoRecebimentoConfirm({ pedido, itens, prodById, onClose, onDone }) {
  const [est, setEst]   = React.useState({});
  const [avr, setAvr]   = React.useState({});
  const [busy, setBusy] = React.useState(false);
  const [err, setErr]   = React.useState('');

  React.useEffect(() => {
    const e0 = {}, a0 = {};
    (itens || []).forEach(it => { e0[it.id] = Number(it.quantidadeRecebida) || 0; a0[it.id] = Number(it.quantidadeAvaria) || 0; });
    setEst(e0); setAvr(a0);
  }, [pedido.id]);   // eslint-disable-line

  const comRecebimento = (itens || []).filter(it => (Number(it.quantidadeRecebida) || 0) > 0 || (Number(it.quantidadeAvaria) || 0) > 0);
  const algum = comRecebimento.some(it => (Number(est[it.id]) || 0) > 0 || (Number(avr[it.id]) || 0) > 0);
  const totalDepois = (itens || []).reduce((a, it) => a + Math.max(0, (Number(it.quantidadeRecebida) || 0) - (Number(est[it.id]) || 0)), 0);

  const confirmar = async () => {
    if (!algum) { setErr('Informe a quantidade a estornar de ao menos um insumo.'); return; }
    setBusy(true); setErr('');
    try {
      const r = await estornarRecebimento(pedido, itens, est, avr, prodById);
      if (r.erros && r.erros.length) console.warn('estorno: falhas', r.erros);
      onDone();
    } catch (e) { setErr(String((e && e.message) || e)); setBusy(false); }
  };

  return (
    <div onClick={onClose} style={{ position: 'fixed', inset: 0, zIndex: 500, background: 'rgba(0,0,0,0.65)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div onClick={e => e.stopPropagation()} style={{ background: 'var(--tm-bg-1)', borderRadius: 14, width: 820, maxWidth: '95vw', maxHeight: '88vh', overflow: 'auto', border: '1px solid var(--tm-line-1)', boxShadow: '0 24px 64px rgba(0,0,0,0.5)' }}>
        <div style={{ padding: '18px 22px', borderBottom: '1px solid var(--tm-line-1)' }}>
          <div style={{ fontFamily: 'var(--tm-font-display)', fontSize: 18 }}>Estornar recebimento de {pedido.numero}?</div>
          <div className="muted" style={{ fontSize: 12.5, marginTop: 2 }}>Desfaz o que foi dado como recebido — para corrigir erro de digitação.</div>
        </div>
        <div style={{ padding: '18px 22px', fontSize: 13 }}>
          <div style={{ marginBottom: 8 }}>Será estornado:</div>
          <table className="tbl" style={{ fontSize: 12.5 }}>
            <thead><tr>
              <th style={{ minWidth: 180 }}>Insumo</th>
              <th style={{ width: 80 }} className="num right">Recebido</th>
              <th style={{ width: 96 }} className="num right">Estornar</th>
              <th style={{ width: 80 }} className="num right">Avaria</th>
              <th style={{ width: 96 }} className="num right">Estornar av.</th>
              <th style={{ width: 128 }} className="num right">Custo atual</th>
            </tr></thead>
            <tbody>
              {comRecebimento.map(it => {
                const p = prodById[it.insumoId] || {};
                return (
                  <tr key={it.id}>
                    <td><span className="ref-mono">{p.sku || '—'}</span> {p.nome || p.name || ''}</td>
                    <td className="num right muted">{Number(it.quantidadeRecebida) || 0}</td>
                    <td className="num right"><input className="input" type="number" min="0" step="1" value={est[it.id] != null ? est[it.id] : ''}
                      onChange={e => setEst(s => ({ ...s, [it.id]: e.target.value }))} style={{ padding: '4px 8px', textAlign: 'right', width: 78 }} /></td>
                    <td className="num right muted">{Number(it.quantidadeAvaria) || 0}</td>
                    <td className="num right"><input className="input" type="number" min="0" step="1" value={avr[it.id] != null ? avr[it.id] : ''}
                      onChange={e => setAvr(s => ({ ...s, [it.id]: e.target.value }))} style={{ padding: '4px 8px', textAlign: 'right', width: 78 }} /></td>
                    <td className="num right muted" style={{ whiteSpace: 'nowrap' }}>R$ {brl(Number(p.custo) || 0)}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>

          <ul style={{ margin: '12px 0 0', paddingLeft: 18, lineHeight: 1.7, fontSize: 12.5 }}>
            <li><b>Estoque:</b> sai a quantidade estornada — <b>Saída auditável</b> "Estorno de recebimento". O movimento original <b>não é apagado</b>.</li>
            <li><b>Pendência:</b> a quantidade volta a ficar pendente no pedido.</li>
            <li><b>Status:</b> o pedido reabre como <b>{totalDepois > 0 ? 'Recebido parcial' : 'Enviado'}</b>.</li>
          </ul>

          <div style={{ marginTop: 12, padding: '10px 12px', borderRadius: 8, background: 'rgba(212,160,74,0.10)', border: '1px solid var(--tm-warning)', fontSize: 12.5, lineHeight: 1.6 }}>
            <b>O custo do insumo NÃO volta.</b> Se você marcou "atualizar custo" naquele recebimento, o
            <b> produtos.custo</b> continua com o valor novo — o custo atual é a <b>última compra</b> (custo de
            reposição), não um histórico que se desfaz. Se o preço estornado estava errado, ajuste o custo
            à mão em <b>Produtos</b> (a coluna "Custo atual" acima mostra o valor de agora).
          </div>
          {err && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{err}</div>}
        </div>
        <div style={{ padding: '14px 22px', borderTop: '1px solid var(--tm-line-1)', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
          <Button variant="secondary" size="sm" onClick={onClose}>Voltar</Button>
          <Button variant="danger-ghost" size="sm" icon="rotate-ccw" onClick={confirmar} disabled={busy}>{busy ? 'Estornando…' : 'Estornar recebimento'}</Button>
        </div>
      </div>
    </div>
  );
}

// Documento imprimível/enviável ao fornecedor — peça NOVA (não o PDF de venda).
// Documento imprimível do Pedido de Compra — MESMO layout do pedido de venda
// (blocos compartilhados de src/DocImpressao.jsx). Adaptações do contexto de
// compra: o bloco de CLIENTE vira FORNECEDOR e não há parcelas/transportador —
// o que existe de condição comercial vira "Condições" + "Observações".
function PedidoCompraDoc({ pedido, itens, prodById, fornecedor, empresa, onClose }) {
  const prodDe = (id) => prodById[id] || {};
  const nomeDe = (id) => { const x = prodDe(id); return x.nome || x.name || '—'; };
  const skuDe  = (id) => prodDe(id).sku || '';
  const unDe   = (id) => prodDe(id).unidade || 'UN';
  const fmtD   = (iso) => iso ? (fmtDate(iso) || String(iso).slice(0, 10).split('-').reverse().join('/')) : '—';
  const fmt    = (n) => (parseFloat(n) || 0).toLocaleString('pt-BR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  const r2     = (x) => Math.round((Number(x) || 0) * 100) / 100;

  // Código do item no catálogo DO FORNECEDOR — é o que ele reconhece no papel.
  const [codForn, setCodForn] = React.useState({});   // produtoId → cProd
  React.useEffect(() => { (async () => {
    if (!pedido.fornecedor_id || !window.carregarDePara) return;
    const m = await window.carregarDePara(pedido.fornecedor_id);   // cProd → produtoId
    const inv = {}; Object.keys(m || {}).forEach(c => { inv[m[c]] = c; });
    setCodForn(inv);
  })(); }, [pedido.fornecedor_id]);   // eslint-disable-line

  const lista   = itens || [];
  const somaQtd = lista.reduce((a, it) => a + (Number(it.quantidade) || 0), 0);
  const st      = PC_STATUS[pedido.status] || PC_STATUS.rascunho;
  const emp     = empresa || window.tmEmpresa || (window.tmEmpresas || [])[0] || {};
  const transp  = (pedido.transportador && typeof pedido.transportador === 'object') ? pedido.transportador : null;
  const parcelas = Array.isArray(pedido.parcelas) ? pedido.parcelas.filter(x => x) : [];

  const liquidoDa = (it) => r2((Number(it.quantidade) || 0) * (Number(it.precoCompra) || 0) * (1 - (Number(it.descontoPct) || 0) / 100));
  const totalProdutos = pedido.total_produtos != null ? Number(pedido.total_produtos) : r2(lista.reduce((a, it) => a + liquidoDa(it), 0));
  const totalIpi   = Number(pedido.total_ipi) || 0;
  const totalIcmsSt = Number(pedido.total_icms_st) || 0;
  const frete      = Number(pedido.frete) || 0;
  const descontoRs = Number(pedido.desconto) || 0;
  const totalPedido = pedido.valor_total != null ? Number(pedido.valor_total)
    : r2(totalProdutos + totalIpi + totalIcmsSt + frete - descontoRs);
  const temDesc = lista.some(it => (Number(it.descontoPct) || 0) > 0);
  const temIpi  = lista.some(it => (Number(it.ipiPct) || 0) > 0);

  const colunas = [
    { label: "Descrição do item" },
    { label: "Código",      width: 62 },
    { label: "Cód. forn.",  width: 70 },
    { label: "Un.",         width: 30, align: "center" },
    { label: "Qtd.",        width: 46, align: "right" },
    { label: "Valor unit.", width: 68, align: "right" },
  ];
  // ⚠️ A PENÚLTIMA coluna é a que carrega os rótulos dos totalizadores no
  // DocTabelaItens (compartilhado com a venda — não dá pra mudar lá). Se ela ficar
  // estreita, "Total dos produtos" quebra em 3 linhas no papel. Por isso a última
  // coluna antes de "Valor total" sai larga o bastante pros rótulos.
  if (temDesc) colunas.push({ label: "Desc.%", width: 48, align: "right" });
  colunas.push({ label: "IPI%", width: temIpi ? 86 : 86, align: "right" });
  colunas.push({ label: "Valor total", width: 74, align: "right" });

  return (
    <DocPrintOverlay barraTitulo={`Pré-visualização — ${pedido.numero}`} onClose={onClose}>

      <DocCabecalhoEmpresa empresa={emp} />

      <DocTitulo texto="Pedido de Compra" numero={pedido.numero} />

      <DocParteInfo
        parteLabel="Fornecedor"
        parteNome={fornecedor && fornecedor.nome}
        detalhes={(() => {
          const doc = fornecedor && fornecedor.cnpj;
          const ctt = fornecedor && fornecedor.contato;
          return (
            <div style={{ fontSize: 10.5, color: "#444", lineHeight: 1.7 }}>
              {doc && <div>CNPJ: {doc}</div>}
              {ctt && <div>Contato: {ctt}</div>}
              {pedido.categoria && <div style={{ marginTop: 2 }}>Categoria: {pedido.categoria}</div>}
            </div>
          );
        })()}
        info={[
          ["Número do pedido",     pedido.numero],
          pedido.numero_fornecedor ? ["Nº no fornecedor", pedido.numero_fornecedor] : null,
          ["Emissão",              fmtD(pedido.data_emissao || pedido.created_at)],
          ["Previsão de entrega",  fmtD(pedido.data_prevista)],
          ["Situação",             st.l],
        ]}
      />

      <DocTituloSecao>Itens do pedido de compra</DocTituloSecao>
      <DocTabelaItens
        colunas={colunas}
        linhas={lista.map((it) => {
          const q  = Number(it.quantidade) || 0;
          const pu = Number(it.precoCompra) || 0;
          const linha = [
            { v: nomeDe(it.insumoId) },
            { v: skuDe(it.insumoId), muted: true },
            { v: codForn[it.insumoId] || '—', muted: true },
            { v: unDe(it.insumoId), align: "center" },
            { v: q.toLocaleString("pt-BR"), align: "right", num: true },
            { v: fmt(pu), align: "right", num: true },
          ];
          if (temDesc) linha.push({ v: (Number(it.descontoPct) || 0) ? fmt(it.descontoPct) : '—', align: "right", num: true });
          linha.push({ v: (Number(it.ipiPct) || 0) ? fmt(it.ipiPct) : '—', align: "right", num: true });
          linha.push({ v: fmt(liquidoDa(it)), align: "right", num: true });
          return linha;
        })}
        totais={[
          ["N° de itens",        lista.length.toLocaleString("pt-BR"), false],
          ["Soma das Qtdes",     somaQtd.toLocaleString("pt-BR"),      false],
          ["Total dos produtos", fmt(totalProdutos),                   false],
          totalIpi    > 0.005 ? ["Total do IPI",   fmt(totalIpi),    false] : null,
          totalIcmsSt > 0.005 ? ["Total ICMS ST",  fmt(totalIcmsSt), false] : null,
          frete       > 0.005 ? ["Frete",          fmt(frete),       false] : null,
          descontoRs  > 0.005 ? ["Desconto",       fmt(descontoRs),  false] : null,
          ["Total do pedido",    fmt(totalPedido),                     true],
        ]}
      />

      {parcelas.length > 0 && (
        <div className="doc-section-break">
          <DocTituloSecao>Parcelas</DocTituloSecao>
          <DocTabelaItens
            colunas={[
              { label: "Parcela", width: 62 },
              { label: "Vencimento" },
              { label: "Forma de pagamento" },
              { label: "Valor", width: 84, align: "right" },
            ]}
            linhas={parcelas.map((par, i) => [
              { v: `${i + 1}ª` },
              { v: par.venc || '—' },
              { v: par.forma || 'Boleto' },
              { v: fmt(par.valor), align: "right", num: true },
            ])}
          />
        </div>
      )}

      {transp && (transp.nome || transp.freteConta || transp.volumes || transp.pesoBruto) && (
        <div className="doc-section-break">
          <DocTituloSecao>Transportador</DocTituloSecao>
          <DocTabelaCampos linhas={[
            transp.nome ? ["Nome", transp.nome] : null,
            ["Frete por conta", transp.freteConta || "—"],
            transp.volumes   ? ["Volumes", String(transp.volumes)] : null,
            transp.pesoBruto ? ["Peso bruto (kg)", String(transp.pesoBruto)] : null,
          ]} />
        </div>
      )}

      <div className="doc-section-break">
        <DocTituloSecao>Condições</DocTituloSecao>
        <DocTabelaCampos linhas={[
          pedido.cond_pagamento ? ["Condição de pagamento", pedido.cond_pagamento] : null,
          ["Previsão de entrega", fmtD(pedido.data_prevista)],
          ["Categoria (CMV)",     pedido.categoria || "—"],
          ["Situação",            st.l],
        ]} />
      </div>

      {/* ⚠️ observacoes_internas NÃO entra aqui — é esse o propósito do campo.
          Só `observacoes` vai pro papel que o fornecedor recebe. */}
      <DocObservacoes texto={pedido.observacoes} />

    </DocPrintOverlay>
  );
}

Object.assign(window, { FornecedoresLista, OrdensProducao, PedidosCompra, FornecedorSelect, gerarNumPC, hojeIso });
