/* global React, Icon, Button, Badge, Card, Drawer, Field, SearchableSelect, EmptyState,
          PageHead, NFTabs, brl, numBr, fmtDate, parseDate,
          parseNFeXml, carregarDePara, salvarDePara, mapaContasPorNome,
          FornecedorSelect, CategoriaSelect, ParcelasEditor, FORMAS_PARCELA,
          somaParcelas, useContasBancarias, hojeIso */

// ─── Notas de Entrada (ciclo fiscal · Fase A) ────────────────────────────────
// O hub de TODA nota de terceiro que entra na casa: da compra (PC), do retorno
// de industrialização (OP) e a avulsa — importada por XML ou digitada à mão.
// Mora na tabela PRÓPRIA notas_entrada (nunca em notas_fiscais, que é só
// emissão própria — decisão da Fase A, raciocínio no SUPABASE_notas-entrada.sql).
//
// Reusa o parser e o de-para do NotaEntrada.jsx (parseNFeXml, carregarDePara,
// salvarDePara) — o import avulso é o mesmo fluxo da compra, sem o pedido.

const soDigitosNE = (s) => String(s || '').replace(/[^0-9]/g, '');

// Título de seção do formulário (escopo do módulo — nunca dentro do componente,
// senão o React desmonta a subárvore a cada tecla; ver CLAUDE.md).
function NESecao({ children }) {
  return <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.08em',
    color: 'var(--tm-fg-4)', margin: '18px 0 8px', paddingTop: 12, borderTop: '1px solid var(--tm-line-1)' }}>{children}</div>;
}

// De onde a nota veio — decide o rótulo da coluna Vínculo do hub.
function neVinculo(n) {
  if (n.pedidoCompraId)  return { tipo: 'compra',   label: 'Compra',            ref: n.pcNumero, tone: 'info' };
  if (n.ordemProducaoId) return { tipo: 'industrializacao', label: 'Industrialização', ref: n.opNumero, tone: 'warning' };
  return { tipo: 'avulsa', label: 'Avulsa', ref: null, tone: 'neutral' };
}

// A âncora de idempotência do título: a MESMA tag que o fluxo do pedido de
// compra grava em contas_pagar.observacoes ("NF-e {chave}") — assim a nota que
// passou pelos dois caminhos não gera título duas vezes. Sem chave (manual),
// o id da nota é a âncora.
const notaTagDe = (nota) => nota.chave ? `NF-e ${nota.chave}` : `Nota de entrada ${nota.id}`;

async function titulosDaNotaTag(tag) {
  if (!window.tmSupabase || !tag) return [];
  const { data } = await window.tmSupabase.from('contas_pagar')
    .select('id, referencia, valor, status, vencimento, parcela').eq('observacoes', tag);
  return data || [];
}

// Nudge do contas a pagar — IDEMPOTENTE (se já existe título com a tag, não cria)
// e NUNCA PARCIAL (insert de array atômico; sobrou órfão depois de erro, apaga).
// Com parcelas na nota → N títulos; sem → 1.
async function gerarContaPagarDaNota(nota, fornecedorNome, categoria) {
  const tag = notaTagDe(nota);
  const jaTem = await titulosDaNotaTag(tag);
  if (jaTem.length) return { jaExiste: jaTem[0], quantos: jaTem.length };

  const total = Number(nota.valorTotal) || 0;
  const parcelas = Array.isArray(nota.parcelas) ? nota.parcelas.filter(p => p) : [];
  if (parcelas.length) {
    const soma = window.somaParcelas(parcelas);
    if (Math.abs(soma - total) > 0.005) {
      return { error: { message: `As parcelas somam R$ ${brl(soma)} e o total da nota é R$ ${brl(total)}. Ajuste antes de gerar.` } };
    }
  }

  const contaMap = await window.mapaContasPorNome();
  const resolveConta = (nome) => nome ? (contaMap[String(nome).trim().toLowerCase()] || null) : null;
  const venc = nota.dataEmissao || nota.dataEntrada || null;
  const quem = fornecedorNome || nota.emitenteNome || null;

  const rows = parcelas.length
    ? parcelas.map((par, i) => ({
        referencia: `NF ${nota.numero || 's/n'}/${i + 1}`,
        fornecedor: quem, categoria: categoria || 'Fornecedores',
        vencimento: parseDate(par.venc) || venc, valor: Number(par.valor) || 0,
        parcela: i + 1, status: 'Em aberto', forma_pagamento: par.forma || 'Boleto',
        conta_id: resolveConta(par.conta), observacoes: tag,
      }))
    : [{
        referencia: `NF ${nota.numero || 's/n'} · ${quem || 'entrada'}`,
        fornecedor: quem, categoria: categoria || 'Fornecedores',
        vencimento: venc, valor: total, parcela: null, status: 'Em aberto',
        forma_pagamento: nota.formaPagamento || 'Boleto', conta_id: null, observacoes: tag,
      }];

  const { error } = await window.tmSupabase.from('contas_pagar').insert(rows);
  if (error) {
    try {
      const sobrou = await titulosDaNotaTag(tag);
      if (sobrou.length) await window.tmSupabase.from('contas_pagar').delete().eq('observacoes', tag);
    } catch (e) { /* reporta o erro original */ }
    return { error };
  }
  return { criado: { n: rows.length, total: rows.reduce((a, r) => a + (Number(r.valor) || 0), 0) } };
}

// Entrada no estoque dos itens casados — motivo fixo 'Nota de entrada avulsa'
// (é o que separa este caminho do 'Recebimento de compra' e da 'Produção
// recebida' nas movimentações). Custo unitário = o valor da NOTA.
async function darEntradaDosItensNE(notaSalva, linhas, quem) {
  const erros = [];
  for (const l of linhas) {
    const q = numBr(l.quantidade);
    if (!l.produtoId || !l.sku || q <= 0) continue;
    try {
      const r = await window.tmDb.salvarMovimentacao({
        tipo: 'Entrada', motivo: 'Nota de entrada avulsa', sku: l.sku, produtoId: l.produtoId,
        qty: Math.abs(q), who: quem, nf: notaSalva.numero || notaSalva.chave || 'entrada',
        custoUn: numBr(l.valorUnitario),
      }, true);
      if (r && r.error) erros.push(l.sku);
    } catch (e) { erros.push(l.sku); }
  }
  return erros;
}

// ── Nudge compartilhado: bloco "Gerar conta a pagar?" ────────────────────────
// Usado no passo final dos dois formulários E no drawer de visualização — é o
// caminho de recuperação se ela pulou o nudge na hora do lançamento.
function NENudgeContaPagar({ nota, fornecedorNome }) {
  const [tits, setTits] = React.useState(undefined);   // undefined = carregando
  const [categoria, setCategoria] = React.useState('');
  const [busy, setBusy] = React.useState(false);
  const [msg, setMsg] = React.useState('');

  React.useEffect(() => { (async () => {
    setTits(await titulosDaNotaTag(notaTagDe(nota)));
  })(); }, [nota.id]);   // eslint-disable-line

  const gerar = async () => {
    setBusy(true); setMsg('');
    const r = await gerarContaPagarDaNota(nota, fornecedorNome, categoria);
    setBusy(false);
    if (r.error) { setMsg('Erro: ' + (r.error.message || r.error) + ' Nada foi criado.'); return; }
    if (r.jaExiste) { setTits(await titulosDaNotaTag(notaTagDe(nota))); setMsg('Esta nota já tem título — não dupliquei.'); return; }
    setTits(await titulosDaNotaTag(notaTagDe(nota)));
    setMsg(`${r.criado.n > 1 ? r.criado.n + ' títulos criados' : 'Conta a pagar criada'} (R$ ${brl(r.criado.total)}).`);
  };

  const parcelas = Array.isArray(nota.parcelas) ? nota.parcelas.filter(p => p) : [];

  return (
    <div style={{ padding: '16px 18px', borderRadius: 10, border: '1px solid var(--tm-line-2)', background: 'var(--tm-bg-2)', marginTop: 14 }}>
      <div style={{ fontSize: 14, fontWeight: 600, marginBottom: 4 }}>
        {parcelas.length > 1 ? `Gerar as ${parcelas.length} contas a pagar desta nota?` : 'Gerar conta a pagar desta nota?'}
      </div>
      {tits === undefined && <div className="muted" style={{ fontSize: 12.5 }}>Conferindo o financeiro…</div>}
      {tits !== undefined && tits.length > 0 && (
        <div style={{ fontSize: 12.5, color: 'var(--tm-fg-3)', lineHeight: 1.6 }}>
          Esta nota <b>já tem</b> {tits.length > 1 ? <>{tits.length} títulos</> : <>um título</>} no financeiro
          (<b>{tits[0].referencia}</b> · R$ {brl(tits[0].valor)} · {tits[0].status}). Não vou duplicar.
        </div>
      )}
      {tits !== undefined && tits.length === 0 && (<>
        <div style={{ fontSize: 12.5, color: 'var(--tm-fg-3)', lineHeight: 1.6 }}>
          {parcelas.length
            ? <>Cria <b>{parcelas.length} títulos</b> em <b>Financeiro › Contas a pagar</b> — um por parcela — para
                <b> {fornecedorNome || nota.emitenteNome || '—'}</b>, total <b>R$ {brl(Number(nota.valorTotal) || 0)}</b>.</>
            : <>Cria <b>um título</b> em <b>Financeiro › Contas a pagar</b>: fornecedor <b>{fornecedorNome || nota.emitenteNome || '—'}</b>,
                valor <b>R$ {brl(Number(nota.valorTotal) || 0)}</b>,
                vencimento <b>{nota.dataEmissao ? (fmtDate(nota.dataEmissao) || nota.dataEmissao) : '—'}</b>.</>}
          {' '}Se você já lançou à mão, ignore.
        </div>
        <div className="field-grid-2" style={{ marginTop: 10, maxWidth: 440 }}>
          <CategoriaSelect value={categoria} onChange={setCategoria} contexto="despesa" label="Categoria do título" />
        </div>
        <div style={{ marginTop: 10 }}>
          <Button variant="primary" size="sm" icon="file-plus" onClick={gerar} disabled={busy || !categoria}>
            {busy ? 'Gerando…' : (parcelas.length > 1 ? `Gerar ${parcelas.length} contas a pagar` : 'Gerar conta a pagar')}
          </Button>
          {!categoria && <span className="muted" style={{ fontSize: 11.5, marginLeft: 10 }}>escolha a categoria primeiro</span>}
        </div>
      </>)}
      {msg && <div style={{ fontSize: 12.5, marginTop: 10, color: msg.indexOf('Erro') === 0 ? 'var(--tm-danger)' : 'var(--tm-success)' }}>{msg}</div>}
    </div>
  );
}

// ── Import de XML avulso (sem pedido de compra) ──────────────────────────────
function NotaEntradaXmlForm({ fornecedores, produtos, onClose, onSalva }) {
  const [nota, setNota]       = React.useState(null);
  const [erro, setErro]       = React.useState('');
  const [fornecedorId, setFornecedorId] = React.useState('');
  const [fornAuto, setFornAuto] = React.useState(false);   // casado pelo CNPJ
  const [dataEntrada, setDataEntrada] = React.useState(window.hojeIso ? window.hojeIso() : new Date().toISOString().slice(0, 10));
  const [mapa, setMapa]       = React.useState({});
  const [escolha, setEscolha] = React.useState({});
  const [semEntrada, setSemEntrada] = React.useState({});  // cProd -> true = NÃO dar entrada
  const [busy, setBusy]       = React.useState(false);
  const [passo, setPasso]     = React.useState('importar'); // importar | registrada
  const [salva, setSalva]     = React.useState(null);
  const [errosMov, setErrosMov] = React.useState([]);
  const inputRef = React.useRef(null);

  // de-para do fornecedor escolhido (auto-casa os itens das próximas notas dele)
  React.useEffect(() => { (async () => {
    setMapa(fornecedorId ? await window.carregarDePara(fornecedorId) : {});
  })(); }, [fornecedorId]);

  const prodById = {}; (produtos || []).forEach(p => { prodById[p.id] = p; });
  const prodOpts = (produtos || []).map(p => ({ value: p.id, label: `${p.sku} · ${p.nome}` }));
  const fornSel  = (fornecedores || []).find(f => f.id === fornecedorId) || null;

  const lerArquivo = (file) => {
    if (!file) return;
    setErro('');
    const fr = new FileReader();
    fr.onload = () => {
      const r = window.parseNFeXml(String(fr.result || ''));
      if (r.error) { setErro(r.error); setNota(null); return; }
      setNota(r);
      // casa o fornecedor pelo CNPJ do emitente
      const cnpj = soDigitosNE(r.emitCnpj);
      const f = cnpj ? (fornecedores || []).find(x => soDigitosNE(x.cnpj) === cnpj) : null;
      setFornecedorId(f ? f.id : ''); setFornAuto(!!f);
    };
    fr.onerror = () => setErro('Falha ao ler o arquivo.');
    fr.readAsText(file, 'UTF-8');
  };

  const casarAuto = (it) => {
    if (mapa[it.cProd]) return { produtoId: mapa[it.cProd], via: 'de-para' };
    const porSku = (produtos || []).find(p => String(p.sku || '').toLowerCase() === String(it.cProd || '').toLowerCase());
    if (porSku) return { produtoId: porSku.id, via: 'sku' };
    return { produtoId: '', via: null };
  };
  const resolvido = (it) => escolha[it.cProd] !== undefined ? escolha[it.cProd] : casarAuto(it).produtoId;

  const pendentes = nota ? nota.itens.filter(it => !semEntrada[it.cProd] && !resolvido(it)) : [];

  const registrar = async () => {
    if (!nota || busy) return;
    if (pendentes.length) { setErro(`Faltam ${pendentes.length} item(ns) sem produto — escolha o produto ou desmarque a entrada no estoque.`); return; }
    setBusy(true); setErro('');
    try {
      // 0) trava de duplicidade (o índice único do banco é a rede de segurança)
      if (nota.chave) {
        const { data: dup } = await window.tmSupabase.from('notas_entrada')
          .select('id').eq('chave_acesso', nota.chave).limit(1);
        if (dup && dup.length) throw new Error('Esta nota já foi lançada — a chave de acesso já existe no hub.');
      }

      // 1) de-para (só com fornecedor vinculado — é por fornecedor)
      if (fornecedorId) {
        const paraSalvar = nota.itens
          .map(it => ({ cProd: it.cProd, xProd: it.xProd, produtoId: resolvido(it) }))
          .filter(l => l.produtoId);
        const rDp = await window.salvarDePara(fornecedorId, paraSalvar);
        if (rDp.error) throw new Error('Falha ao salvar o de-para: ' + (rDp.error.message || rDp.error));
      }

      // 2) a nota + itens (item de array sem id — regra do CLAUDE.md)
      const itens = nota.itens.map(it => ({
        produtoId: resolvido(it) || null, codigoFornecedor: it.cProd, descricao: it.xProd,
        ncm: it.ncm || null, unidade: it.uCom, quantidade: it.qCom,
        valorUnitario: it.vUnCom, valorTotal: it.vProd,
      }));
      const r = await window.tmDb.salvarNotaEntrada({
        fornecedorId: fornecedorId || null, emitenteNome: nota.emitNome, emitenteCnpj: nota.emitCnpj,
        numero: nota.numero, serie: nota.serie, chave: nota.chave || null,
        dataEmissao: nota.dataEmissao || null, dataEntrada: dataEntrada || null,
        valorProdutos: nota.valorProdutos, valorFrete: nota.valorFrete,
        valorDesconto: nota.valorDesconto, valorTotal: nota.valorTotal,
        origem: 'xml', empresaId: window.tmEmpresaId || null,
        criadoPor: (window.tmUserProfile && window.tmUserProfile.nome) || null,
      }, itens);
      if (r.error) {
        const m = String(r.error.message || r.error);
        throw new Error(m.indexOf('uq_notas_entrada_chave') >= 0 || m.toLowerCase().indexOf('duplicate') >= 0
          ? 'Esta nota já foi lançada — a chave de acesso já existe no hub.' : m);
      }

      // 3) entrada no estoque dos itens marcados
      const quem = (window.tmUserProfile && window.tmUserProfile.nome) || 'Fiscal';
      const linhas = nota.itens.filter(it => !semEntrada[it.cProd]).map(it => {
        const p = prodById[resolvido(it)];
        return p ? { produtoId: p.id, sku: p.sku, quantidade: it.qCom, valorUnitario: it.vUnCom } : null;
      }).filter(Boolean);
      setErrosMov(await darEntradaDosItensNE(r.nota, linhas, quem));

      setSalva(r.nota); setPasso('registrada');
      if (onSalva) onSalva();
    } catch (e) { setErro(String((e && e.message) || e)); }
    setBusy(false);
  };

  const cnpjBate = nota && fornSel && fornSel.cnpj
    ? soDigitosNE(nota.emitCnpj) === soDigitosNE(fornSel.cnpj) : null;

  return (
    <Drawer open={true} width={980} title="Importar XML de nota de entrada"
      subtitle="Nota avulsa, sem pedido de compra — os itens casados entram no estoque com o custo da nota"
      onClose={onClose}
      footer={passo === 'importar'
        ? (<><span style={{ flex: 1 }} />
            <Button variant="secondary" size="sm" onClick={onClose}>Cancelar</Button>
            <Button variant="primary" size="sm" icon="check" onClick={registrar} disabled={busy || !nota}>{busy ? 'Registrando…' : 'Registrar nota'}</Button></>)
        : (<><span style={{ flex: 1 }} />
            <Button variant="primary" size="sm" onClick={onClose}>Concluir</Button></>)}>

      {passo === 'importar' && (<>
        {!nota && (
          <div onClick={() => inputRef.current && inputRef.current.click()}
            onDragOver={e => e.preventDefault()}
            onDrop={e => { e.preventDefault(); lerArquivo(e.dataTransfer.files && e.dataTransfer.files[0]); }}
            style={{ border: '2px dashed var(--tm-line-2)', borderRadius: 'var(--tm-radius-md)', padding: '38px 20px',
                     textAlign: 'center', cursor: 'pointer', color: 'var(--tm-fg-3)' }}>
            <Icon name="file-up" size={26} style={{ opacity: .7 }} />
            <div style={{ marginTop: 10, fontSize: 14, color: 'var(--tm-fg-1)' }}>Solte o XML da NF-e aqui ou clique para escolher</div>
            <div style={{ fontSize: 12, marginTop: 4 }}>O arquivo é lido no seu navegador — nada é enviado pra fora.</div>
          </div>
        )}
        <input ref={inputRef} type="file" accept=".xml,text/xml,application/xml" style={{ display: 'none' }}
          onChange={e => lerArquivo(e.target.files && e.target.files[0])} />

        {nota && (<>
          <div className="field-grid-4" style={{ marginBottom: 6 }}>
            <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Emitente</div><div>{nota.emitNome || '—'}</div></div>
            <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>NF-e nº</div><div>{nota.numero || '—'}{nota.serie ? ` / ${nota.serie}` : ''}</div></div>
            <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Emissão</div><div>{nota.dataEmissao ? (fmtDate(nota.dataEmissao) || nota.dataEmissao) : '—'}</div></div>
            <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Total da nota</div><div style={{ fontWeight: 600 }}>R$ {brl(nota.valorTotal)}</div></div>
          </div>

          <div className="field-grid-2" style={{ marginTop: 10 }}>
            <div>
              <SearchableSelect label="Fornecedor (do cadastro)" value={fornecedorId} onChange={v => { setFornecedorId(v); setFornAuto(false); }}
                options={(fornecedores || []).map(f => ({ value: f.id, label: f.nome }))} placeholder="Sem vínculo — só o nome do XML" />
              <div className="muted" style={{ fontSize: 11.5, marginTop: 4 }}>
                {fornAuto ? 'Casado pelo CNPJ do emitente.' : fornecedorId ? 'Escolhido à mão.' : 'Sem vínculo: a nota guarda o nome e o CNPJ do XML (e o de-para não é salvo).'}
              </div>
            </div>
            <Field label="Data de entrada" hint="quando a mercadoria chegou">
              <input className="input" type="date" value={dataEntrada} onChange={e => setDataEntrada(e.target.value)} />
            </Field>
          </div>
          {cnpjBate === false && (
            <div style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: 'var(--tm-warning)', margin: '8px 0' }}>
              <Icon name="alert-triangle" size={15} />
              <span>O CNPJ do emitente ({nota.emitCnpj}) é diferente do cadastro de <b>{fornSel && fornSel.nome}</b>. Confira o fornecedor escolhido.</span>
            </div>
          )}

          <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--tm-fg-4)', margin: '14px 0 6px' }}>
            Itens da nota · casar com os produtos
          </div>
          <table className="tbl" style={{ fontSize: 12.5 }}>
            <thead><tr>
              <th style={{ width: 100, whiteSpace: 'nowrap' }}>Cód. forn.</th>
              <th style={{ minWidth: 160 }}>Descrição na nota</th>
              <th style={{ width: 58 }} className="num right">Qtd</th>
              <th style={{ width: 90, whiteSpace: 'nowrap' }} className="num right">Vlr unit.</th>
              <th style={{ minWidth: 200 }}>Produto (o seu)</th>
              <th style={{ width: 86 }}>Casou por</th>
              <th style={{ width: 74, textAlign: 'center' }}>Entrada?</th>
            </tr></thead>
            <tbody>
              {nota.itens.map(it => {
                const auto = casarAuto(it);
                const pid  = resolvido(it);
                const fora = !!semEntrada[it.cProd];
                return (
                  <tr key={it.cProd + it.n} style={fora ? { opacity: .55 } : null}>
                    <td style={{ whiteSpace: 'nowrap' }}><span className="ref-mono">{it.cProd || '—'}</span></td>
                    <td>{it.xProd || '—'}</td>
                    <td className="num right">{it.qCom}</td>
                    <td className="num right" style={{ whiteSpace: 'nowrap' }}>R$ {brl(it.vUnCom)}</td>
                    <td>
                      <SearchableSelect value={pid} onChange={v => setEscolha(s => ({ ...s, [it.cProd]: v }))}
                        options={prodOpts} placeholder="Buscar produto…" />
                    </td>
                    <td style={{ fontSize: 11 }}>
                      {fora ? <span className="muted">fora</span>
                        : !pid ? <span style={{ color: 'var(--tm-danger)' }}>escolher</span>
                        : escolha[it.cProd] !== undefined ? <span style={{ color: 'var(--tm-info)' }}>você agora</span>
                        : auto.via === 'de-para' ? <span style={{ color: 'var(--tm-success)' }}>de-para</span>
                        : <span style={{ color: 'var(--tm-fg-3)' }}>SKU igual</span>}
                    </td>
                    <td style={{ textAlign: 'center' }}>
                      <input type="checkbox" checked={!fora}
                        onChange={e => setSemEntrada(s => ({ ...s, [it.cProd]: !e.target.checked }))} />
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
          <div style={{ fontSize: 11.5, color: 'var(--tm-fg-4)', marginTop: 10, lineHeight: 1.6 }}>
            Desmarque <b>Entrada?</b> no que não é estoque (frete cobrado como item, serviço, brinde) — o item fica
            registrado na nota, mas não movimenta o estoque.
            {fornecedorId ? <> O de-para de <b>{fornSel && fornSel.nome}</b> é guardado: nas próximas notas dele esses itens casam sozinhos.</> : null}
          </div>
          {erro && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{erro}</div>}
        </>)}
        {!nota && erro && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>{erro}</div>}
      </>)}

      {passo === 'registrada' && salva && (<>
        <div style={{ display: 'flex', gap: 10, alignItems: 'center', padding: '12px 14px', borderRadius: 8,
                      background: 'rgba(91,177,122,0.10)', border: '1px solid var(--tm-success)' }}>
          <Icon name="check-circle" size={18} style={{ color: 'var(--tm-success)' }} />
          <div style={{ fontSize: 13 }}>
            Nota <b>{salva.numero || 's/n'}</b> lançada no hub · os itens marcados entraram no estoque com o custo da nota.
          </div>
        </div>
        {errosMov.length > 0 && (
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>
            <Icon name="alert-triangle" size={15} />
            <span>A entrada de estoque falhou em: <b>{errosMov.join(', ')}</b>. A nota foi salva — lance a entrada desses itens à mão em Movimentações.</span>
          </div>
        )}
        <NENudgeContaPagar nota={salva} fornecedorNome={fornSel && fornSel.nome} />
      </>)}
    </Drawer>
  );
}

// ── Lançamento manual (estilo Bling, enxuto) ─────────────────────────────────
const NE_ITEM_VAZIO = () => ({ produtoId: '', descricao: '', ncm: '', unidade: 'UN', quantidade: '', valorUnitario: '', entrada: true });

function NotaEntradaManualForm({ fornecedores, reloadFornecedores, produtos, onClose, onSalva }) {
  const hoje = window.hojeIso ? window.hojeIso() : new Date().toISOString().slice(0, 10);
  const [fornecedorId, setFornecedorId] = React.useState('');
  const [numero, setNumero]   = React.useState('');
  const [serie, setSerie]     = React.useState('');
  const [dataEmissao, setDataEmissao] = React.useState(hoje);
  const [dataEntrada, setDataEntrada] = React.useState(hoje);
  const [itens, setItens]     = React.useState([NE_ITEM_VAZIO()]);
  const [frete, setFrete]     = React.useState('');
  const [desconto, setDesconto] = React.useState('');
  const [transp, setTransp]   = React.useState({ nome: '', placa: '', ufVeiculo: '' });
  const [vol, setVol]         = React.useState({ quantidade: '', especie: '', pesoBruto: '', pesoLiquido: '' });
  const [formaPagamento, setFormaPagamento] = React.useState('Boleto');
  const [parcelado, setParcelado] = React.useState(false);
  const [parcelas, setParcelas]   = React.useState([]);
  const [observacoes, setObservacoes] = React.useState('');
  const [busy, setBusy]       = React.useState(false);
  const [erro, setErro]       = React.useState('');
  const [passo, setPasso]     = React.useState('editar'); // editar | registrada
  const [salva, setSalva]     = React.useState(null);
  const [errosMov, setErrosMov] = React.useState([]);
  const { contas } = useContasBancarias();

  const prodById = {}; (produtos || []).forEach(p => { prodById[p.id] = p; });
  const prodOpts = (produtos || []).map(p => ({ value: p.id, label: `${p.sku} · ${p.nome}` }));
  const fornSel  = (fornecedores || []).find(f => f.id === fornecedorId) || null;

  const setItem = (i, patch) => setItens(arr => arr.map((it, j) => j === i ? { ...it, ...patch } : it));
  // numBr, NUNCA Number(): "2,10" digitado virava NaN -> 0 em silêncio e o
  // custo entrava zerado (caso real da primeira nota manual)
  const totalItem = (it) => numBr(it.quantidade) * numBr(it.valorUnitario);
  const valorProdutos = itens.reduce((a, it) => a + totalItem(it), 0);
  const valorTotal = Math.round((valorProdutos + numBr(frete) - numBr(desconto)) * 100) / 100;

  const escolherProduto = (i, pid) => {
    const p = prodById[pid];
    setItem(i, { produtoId: pid, descricao: (itens[i].descricao || '').trim() ? itens[i].descricao : (p ? p.nome : '') });
  };

  const registrar = async () => {
    if (busy) return;
    setErro('');
    const linhasValidas = itens.filter(it => numBr(it.quantidade) > 0 || (it.descricao || '').trim() || it.produtoId);
    if (!fornecedorId) { setErro('Escolha o fornecedor (ou cadastre pelo próprio seletor).'); return; }
    if (!numero.trim()) { setErro('Informe o número da nota.'); return; }
    if (!linhasValidas.length) { setErro('A nota precisa de pelo menos um item.'); return; }
    const semProduto = linhasValidas.filter(it => it.entrada && !it.produtoId);
    if (semProduto.length) { setErro(`${semProduto.length} item(ns) com entrada no estoque marcada e sem produto — escolha o produto ou desmarque a entrada.`); return; }
    const semQtd = linhasValidas.filter(it => it.entrada && numBr(it.quantidade) <= 0);
    if (semQtd.length) { setErro('Item com entrada no estoque precisa de quantidade maior que zero.'); return; }
    if (parcelado && parcelas.length) {
      const soma = window.somaParcelas(parcelas);
      if (Math.abs(soma - valorTotal) > 0.005) { setErro(`As parcelas somam R$ ${brl(soma)} e o total da nota é R$ ${brl(valorTotal)}. Ajuste antes de registrar.`); return; }
    }

    setBusy(true);
    try {
      const temTransp = (transp.nome || '').trim() || (transp.placa || '').trim();
      const temVol = String(vol.quantidade || '').trim() || (vol.especie || '').trim() || String(vol.pesoBruto || '').trim();
      const r = await window.tmDb.salvarNotaEntrada({
        fornecedorId, emitenteNome: fornSel ? fornSel.nome : null, emitenteCnpj: fornSel ? (fornSel.cnpj || null) : null,
        numero: numero.trim(), serie: serie.trim() || null, chave: null,
        dataEmissao: dataEmissao || null, dataEntrada: dataEntrada || null,
        valorProdutos, valorFrete: numBr(frete), valorDesconto: numBr(desconto), valorTotal,
        transportador: temTransp ? transp : null, volumes: temVol ? vol : null,
        formaPagamento, parcelas: parcelado ? parcelas : null,
        observacoes: observacoes.trim() || null,
        origem: 'manual', empresaId: window.tmEmpresaId || null,
        criadoPor: (window.tmUserProfile && window.tmUserProfile.nome) || null,
      }, linhasValidas.map(it => {
        const p = prodById[it.produtoId];
        return {
          produtoId: it.produtoId || null, codigoFornecedor: null,
          descricao: (it.descricao || '').trim() || (p ? p.nome : null),
          ncm: (it.ncm || '').trim() || null, unidade: it.unidade || 'UN',
          quantidade: numBr(it.quantidade), valorUnitario: numBr(it.valorUnitario),
          valorTotal: totalItem(it),
        };
      }));
      if (r.error) throw new Error(String(r.error.message || r.error));

      const quem = (window.tmUserProfile && window.tmUserProfile.nome) || 'Fiscal';
      const linhasMov = linhasValidas.filter(it => it.entrada && it.produtoId).map(it => {
        const p = prodById[it.produtoId];
        return p ? { produtoId: p.id, sku: p.sku, quantidade: numBr(it.quantidade), valorUnitario: numBr(it.valorUnitario) } : null;
      }).filter(Boolean);
      setErrosMov(await darEntradaDosItensNE(r.nota, linhasMov, quem));

      setSalva(r.nota); setPasso('registrada');
      if (onSalva) onSalva();
    } catch (e) { setErro(String((e && e.message) || e)); }
    setBusy(false);
  };

  return (
    <Drawer open={true} width={980} title="Lançar nota de entrada"
      subtitle="Nota digitada à mão — pra fornecedor sem XML ou nota antiga"
      onClose={onClose}
      footer={passo === 'editar'
        ? (<><span style={{ flex: 1 }} />
            <Button variant="secondary" size="sm" onClick={onClose}>Cancelar</Button>
            <Button variant="primary" size="sm" icon="check" onClick={registrar} disabled={busy}>{busy ? 'Registrando…' : 'Registrar nota'}</Button></>)
        : (<><span style={{ flex: 1 }} />
            <Button variant="primary" size="sm" onClick={onClose}>Concluir</Button></>)}>

      {passo === 'editar' && (<>
        <NESecao>Remetente</NESecao>
        <div className="field-grid-4">
          <div style={{ gridColumn: 'span 2' }}>
            <FornecedorSelect value={fornecedorId} onChange={setFornecedorId}
              fornecedores={fornecedores} reload={reloadFornecedores} empresaId={window.tmEmpresaId} required />
          </div>
          <Field label="NF nº *"><input className="input" value={numero} onChange={e => setNumero(e.target.value)} placeholder="123456" /></Field>
          <Field label="Série"><input className="input" value={serie} onChange={e => setSerie(e.target.value)} placeholder="1" /></Field>
        </div>
        <div className="field-grid-4" style={{ marginTop: 8 }}>
          <Field label="Data de emissão"><input className="input" type="date" value={dataEmissao} onChange={e => setDataEmissao(e.target.value)} /></Field>
          <Field label="Data de entrada"><input className="input" type="date" value={dataEntrada} onChange={e => setDataEntrada(e.target.value)} /></Field>
        </div>

        <NESecao>Itens</NESecao>
        <table className="tbl" style={{ fontSize: 12.5 }}>
          <thead><tr>
            <th style={{ minWidth: 190 }}>Produto</th>
            <th style={{ minWidth: 150 }}>Descrição na nota</th>
            <th style={{ width: 70 }}>Un</th>
            <th style={{ width: 74 }} className="num right">Qtd</th>
            <th style={{ width: 100, whiteSpace: 'nowrap' }} className="num right">Vlr unit.</th>
            <th style={{ width: 96, whiteSpace: 'nowrap' }} className="num right">Total</th>
            <th style={{ width: 70, textAlign: 'center' }}>Entrada?</th>
            <th style={{ width: 36 }}></th>
          </tr></thead>
          <tbody>
            {itens.map((it, i) => (
              <tr key={i} style={!it.entrada ? { opacity: .6 } : null}>
                <td><SearchableSelect value={it.produtoId} onChange={v => escolherProduto(i, v)} options={prodOpts} placeholder="Buscar produto…" /></td>
                <td><input className="input" value={it.descricao} onChange={e => setItem(i, { descricao: e.target.value })} placeholder="Como está na nota" /></td>
                <td><input className="input" value={it.unidade} onChange={e => setItem(i, { unidade: e.target.value })} /></td>
                <td><input className="input num right" inputMode="decimal" value={it.quantidade} onChange={e => setItem(i, { quantidade: e.target.value })} placeholder="0" /></td>
                <td><input className="input num right" inputMode="decimal" value={it.valorUnitario} onChange={e => setItem(i, { valorUnitario: e.target.value })} placeholder="0,00" /></td>
                <td className="num right" style={{ whiteSpace: 'nowrap' }}>R$ {brl(totalItem(it))}</td>
                <td style={{ textAlign: 'center' }}>
                  <input type="checkbox" checked={!!it.entrada} onChange={e => setItem(i, { entrada: e.target.checked })} />
                </td>
                <td style={{ textAlign: 'center' }}>
                  {itens.length > 1 && (
                    <button onClick={() => setItens(arr => arr.filter((_, j) => j !== i))}
                      style={{ background: 'none', border: 'none', cursor: 'pointer', color: 'var(--tm-fg-4)' }} title="Remover item">
                      <Icon name="x" size={14} />
                    </button>
                  )}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
        <div style={{ marginTop: 8 }}>
          <Button variant="ghost" size="sm" icon="plus" onClick={() => setItens(arr => [...arr, NE_ITEM_VAZIO()])}>Adicionar item</Button>
          <span className="muted" style={{ fontSize: 11.5, marginLeft: 10 }}>Desmarque <b>Entrada?</b> no que não movimenta estoque (serviço, frete como item).</span>
        </div>

        <NESecao>Totais</NESecao>
        <div className="field-grid-4">
          <Field label="Produtos"><input className="input num right" value={`R$ ${brl(valorProdutos)}`} disabled /></Field>
          <Field label="Frete"><input className="input num right" inputMode="decimal" value={frete} onChange={e => setFrete(e.target.value)} placeholder="0,00" /></Field>
          <Field label="Desconto"><input className="input num right" inputMode="decimal" value={desconto} onChange={e => setDesconto(e.target.value)} placeholder="0,00" /></Field>
          <Field label="Total da nota"><input className="input num right" style={{ fontWeight: 600 }} value={`R$ ${brl(valorTotal)}`} disabled /></Field>
        </div>

        <NESecao>Transportador e volumes</NESecao>
        <div className="field-grid-4">
          <div style={{ gridColumn: 'span 2' }}>
            <Field label="Transportador"><input className="input" value={transp.nome} onChange={e => setTransp(t => ({ ...t, nome: e.target.value }))} placeholder="Opcional" /></Field>
          </div>
          <Field label="Placa"><input className="input" value={transp.placa} onChange={e => setTransp(t => ({ ...t, placa: e.target.value }))} /></Field>
          <Field label="UF do veículo"><input className="input" value={transp.ufVeiculo} onChange={e => setTransp(t => ({ ...t, ufVeiculo: e.target.value }))} maxLength={2} /></Field>
        </div>
        <div className="field-grid-4" style={{ marginTop: 8 }}>
          <Field label="Qtd. volumes"><input className="input num right" inputMode="numeric" value={vol.quantidade} onChange={e => setVol(v => ({ ...v, quantidade: e.target.value }))} /></Field>
          <Field label="Espécie"><input className="input" value={vol.especie} onChange={e => setVol(v => ({ ...v, especie: e.target.value }))} placeholder="Caixa, fardo…" /></Field>
          <Field label="Peso bruto (kg)"><input className="input num right" inputMode="decimal" value={vol.pesoBruto} onChange={e => setVol(v => ({ ...v, pesoBruto: e.target.value }))} /></Field>
          <Field label="Peso líquido (kg)"><input className="input num right" inputMode="decimal" value={vol.pesoLiquido} onChange={e => setVol(v => ({ ...v, pesoLiquido: e.target.value }))} /></Field>
        </div>

        <NESecao>Pagamento</NESecao>
        <div className="field-grid-4">
          <Field label="Forma de pagamento">
            <select className="input" value={formaPagamento} onChange={e => setFormaPagamento(e.target.value)}>
              {window.FORMAS_PARCELA.map(f => <option key={f} value={f}>{f}</option>)}
            </select>
          </Field>
          <Field label="Condição">
            <select className="input" value={parcelado ? 'parcelado' : 'avista'} onChange={e => setParcelado(e.target.value === 'parcelado')}>
              <option value="avista">À vista / título único</option>
              <option value="parcelado">Parcelado</option>
            </select>
          </Field>
        </div>
        {parcelado && (
          <div style={{ marginTop: 10 }}>
            <ParcelasEditor parcelas={parcelas} onChange={setParcelas} total={valorTotal}
              contas={contas} dataBase={fmtDate(dataEmissao) || ''} formaPadrao={formaPagamento} />
          </div>
        )}
        <div className="muted" style={{ fontSize: 11.5, marginTop: 6 }}>
          O pagamento fica registrado na nota — o título no financeiro é o próximo passo, sugerido depois de registrar.
        </div>

        <NESecao>Observações</NESecao>
        <textarea className="input" rows={3} value={observacoes} onChange={e => setObservacoes(e.target.value)}
          placeholder="O que for útil lembrar sobre esta nota" style={{ resize: 'vertical' }} />

        {erro && <div style={{ fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 12 }}>{erro}</div>}
      </>)}

      {passo === 'registrada' && salva && (<>
        <div style={{ display: 'flex', gap: 10, alignItems: 'center', padding: '12px 14px', borderRadius: 8,
                      background: 'rgba(91,177,122,0.10)', border: '1px solid var(--tm-success)' }}>
          <Icon name="check-circle" size={18} style={{ color: 'var(--tm-success)' }} />
          <div style={{ fontSize: 13 }}>
            Nota <b>{salva.numero || 's/n'}</b> lançada no hub · os itens com entrada marcada entraram no estoque com o custo da nota.
          </div>
        </div>
        {errosMov.length > 0 && (
          <div style={{ display: 'flex', gap: 8, alignItems: 'center', fontSize: 12.5, color: 'var(--tm-danger)', marginTop: 10 }}>
            <Icon name="alert-triangle" size={15} />
            <span>A entrada de estoque falhou em: <b>{errosMov.join(', ')}</b>. A nota foi salva — lance a entrada desses itens à mão em Movimentações.</span>
          </div>
        )}
        <NENudgeContaPagar nota={salva} fornecedorNome={fornSel && fornSel.nome} />
      </>)}
    </Drawer>
  );
}

// ── Visualização de uma nota lançada ─────────────────────────────────────────
function NotaEntradaView({ nota, prodById, onNav, onClose }) {
  const [itens, setItens] = React.useState(undefined);

  React.useEffect(() => { (async () => {
    setItens(await window.tmDb.loadNotaEntradaItens(nota.id));
  })(); }, [nota.id]);

  const v = neVinculo(nota);
  const linha = (rot, val) => (
    <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>{rot}</div><div>{val || '—'}</div></div>
  );

  return (
    <Drawer open={true} width={920} title={`Nota de entrada · ${nota.numero || 's/n'}${nota.serie ? ` / ${nota.serie}` : ''}`}
      subtitle={nota.fornecedorNome || nota.emitenteNome || ''}
      onClose={onClose}
      footer={<><span style={{ flex: 1 }} /><Button variant="secondary" size="sm" onClick={onClose}>Fechar</Button></>}>

      <div className="field-grid-4">
        {linha('Emitente', nota.fornecedorNome || nota.emitenteNome)}
        {linha('CNPJ', nota.emitenteCnpj)}
        {linha('Emissão', nota.dataEmissao ? (fmtDate(nota.dataEmissao) || nota.dataEmissao) : '')}
        {linha('Entrada', nota.dataEntrada ? (fmtDate(nota.dataEntrada) || nota.dataEntrada) : '')}
      </div>
      <div className="field-grid-4" style={{ marginTop: 10 }}>
        {linha('Produtos', `R$ ${brl(nota.valorProdutos)}`)}
        {linha('Frete', `R$ ${brl(nota.valorFrete)}`)}
        {linha('Desconto', `R$ ${brl(nota.valorDesconto)}`)}
        <div><div style={{ fontSize: 11, color: 'var(--tm-fg-4)' }}>Total</div><div style={{ fontWeight: 600 }}>R$ {brl(nota.valorTotal)}</div></div>
      </div>
      <div style={{ display: 'flex', gap: 8, alignItems: 'center', marginTop: 12, flexWrap: 'wrap' }}>
        <Badge tone={v.tone}>{v.label}{v.ref ? ` · ${v.ref}` : ''}</Badge>
        <Badge tone="neutral">{nota.origem === 'manual' ? 'Digitada' : 'XML'}</Badge>
        {nota.status === 'cancelada' && <Badge tone="danger">Cancelada</Badge>}
        {v.tipo === 'compra' && onNav && <Button variant="ghost" size="sm" icon="arrow-right" onClick={() => onNav('estoque/compras')}>Ver pedidos de compra</Button>}
        {v.tipo === 'industrializacao' && onNav && <Button variant="ghost" size="sm" icon="arrow-right" onClick={() => onNav('estoque/producao')}>Ver ordens de produção</Button>}
      </div>
      {nota.chave && (
        <div style={{ marginTop: 10, fontSize: 11.5, color: 'var(--tm-fg-4)' }}>Chave de acesso<br />
          <span className="ref-mono" style={{ fontSize: 12 }}>{nota.chave}</span></div>
      )}

      <div style={{ fontSize: 10.5, fontWeight: 600, textTransform: 'uppercase', letterSpacing: '.08em', color: 'var(--tm-fg-4)', margin: '16px 0 6px' }}>Itens</div>
      {itens === undefined && <div className="muted" style={{ fontSize: 12.5 }}>Carregando itens…</div>}
      {itens !== undefined && itens.length === 0 && <div className="muted" style={{ fontSize: 12.5 }}>Nota sem itens registrados (lançada antes do hub — os detalhes estão no pedido vinculado).</div>}
      {itens !== undefined && itens.length > 0 && (
        <table className="tbl" style={{ fontSize: 12.5 }}>
          <thead><tr>
            <th style={{ minWidth: 170 }}>Descrição</th><th style={{ width: 130 }}>Produto</th>
            <th style={{ width: 56 }}>Un</th><th style={{ width: 64 }} className="num right">Qtd</th>
            <th style={{ width: 92, whiteSpace: 'nowrap' }} className="num right">Vlr unit.</th>
            <th style={{ width: 92, whiteSpace: 'nowrap' }} className="num right">Total</th>
          </tr></thead>
          <tbody>
            {itens.map(it => {
              const p = it.produtoId ? (prodById || {})[it.produtoId] : null;
              return (
                <tr key={it.id}>
                  <td>{it.descricao || '—'}</td>
                  <td>{p ? <span className="ref-mono">{p.sku}</span> : <span className="muted">sem vínculo</span>}</td>
                  <td>{it.unidade || '—'}</td>
                  <td className="num right">{it.quantidade}</td>
                  <td className="num right" style={{ whiteSpace: 'nowrap' }}>R$ {brl(it.valorUnitario)}</td>
                  <td className="num right" style={{ whiteSpace: 'nowrap' }}>R$ {brl(it.valorTotal)}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      )}

      {nota.observacoes && (
        <div style={{ marginTop: 12, fontSize: 12.5, color: 'var(--tm-fg-3)' }}>
          <b>Observações:</b> {nota.observacoes}
        </div>
      )}

      <NENudgeContaPagar nota={nota} fornecedorNome={nota.fornecedorNome} />
    </Drawer>
  );
}

// ── O hub ────────────────────────────────────────────────────────────────────
function NotasEntradaHub({ onNav }) {
  const [notas, setNotas]     = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [busca, setBusca]     = React.useState('');
  const [filtro, setFiltro]   = React.useState('todas'); // todas | compra | industrializacao | avulsa
  const [drawer, setDrawer]   = React.useState(null);    // {tipo:'xml'|'manual'|'view', nota?}
  const [fornecedores, setFornecedores] = React.useState([]);
  const [produtos, setProdutos] = React.useState([]);

  const load = React.useCallback(async () => {
    setLoading(true);
    setNotas(await window.tmDb.listNotasEntrada());
    setLoading(false);
  }, []);

  const loadCadastros = React.useCallback(async () => {
    if (!window.tmSupabase) return;
    const [f, p] = await Promise.all([
      window.tmSupabase.from('fornecedores').select('id, nome, cnpj').eq('situacao', 'Ativo').order('nome'),
      window.tmSupabase.from('produtos').select('id, sku, nome, custo').order('nome'),
    ]);
    setFornecedores(f.data || []); setProdutos(p.data || []);
  }, []);

  React.useEffect(() => { load(); loadCadastros(); }, [load, loadCadastros]);

  const prodById = {}; produtos.forEach(p => { prodById[p.id] = p; });

  const q = busca.trim().toLowerCase();
  const visiveis = notas.filter(n => {
    if (filtro !== 'todas' && neVinculo(n).tipo !== filtro) return false;
    if (!q) return true;
    return [n.numero, n.fornecedorNome, n.emitenteNome, n.chave, n.pcNumero, n.opNumero]
      .some(x => String(x || '').toLowerCase().indexOf(q) >= 0);
  });

  return (
    <div className="canvas">
      <PageHead title="Notas de Entrada" sub="Toda nota de terceiro que entra: compra, industrialização e avulsa" />
      <NFTabs active="entradas" onNav={onNav} />

      <div className="toolbar" style={{ display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap', marginBottom: 12 }}>
        <input className="input" style={{ maxWidth: 260 }} placeholder="Buscar nº, fornecedor, chave…"
          value={busca} onChange={e => setBusca(e.target.value)} />
        <select className="input" style={{ maxWidth: 190 }} value={filtro} onChange={e => setFiltro(e.target.value)}>
          <option value="todas">Todos os vínculos</option>
          <option value="compra">Compra (PC)</option>
          <option value="industrializacao">Industrialização (OP)</option>
          <option value="avulsa">Avulsa</option>
        </select>
        <span style={{ flex: 1 }} />
        <Button variant="secondary" size="sm" icon="pencil" onClick={() => setDrawer({ tipo: 'manual' })}>Lançar nota manual</Button>
        <Button variant="primary" size="sm" icon="file-up" onClick={() => setDrawer({ tipo: 'xml' })}>Importar XML</Button>
      </div>

      <Card>
        {loading ? (
          <div style={{ padding: '48px 0', textAlign: 'center', color: 'var(--tm-fg-3)', fontSize: 13 }}>Carregando…</div>
        ) : visiveis.length === 0 ? (
          <EmptyState icon="file-down" title={notas.length ? 'Nada com esse filtro' : 'Nenhuma nota de entrada ainda'}
            msg={notas.length ? 'Ajuste a busca ou o filtro de vínculo.' : 'Importe o XML da NF-e do fornecedor ou lance uma nota à mão.'}
            action={!notas.length ? <Button variant="primary" size="sm" icon="file-up" onClick={() => setDrawer({ tipo: 'xml' })}>Importar XML</Button> : null} />
        ) : (
          <table className="tbl">
            <thead><tr>
              <th style={{ width: 92 }}>Entrada</th>
              <th style={{ width: 100 }}>NF nº</th>
              <th style={{ minWidth: 180 }}>Emitente</th>
              <th style={{ width: 190 }}>Vínculo</th>
              <th style={{ width: 110, whiteSpace: 'nowrap' }} className="num right">Total</th>
              <th style={{ width: 84 }}>Origem</th>
            </tr></thead>
            <tbody>
              {visiveis.map(n => {
                const v = neVinculo(n);
                return (
                  <tr key={n.id} style={{ cursor: 'pointer' }} onClick={() => setDrawer({ tipo: 'view', nota: n })}>
                    <td className="muted" style={{ whiteSpace: 'nowrap' }}>{n.dataEntrada ? (fmtDate(n.dataEntrada) || n.dataEntrada) : '—'}</td>
                    <td><span className="ref-mono">{n.numero || 's/n'}</span>{n.serie ? <span className="muted">/{n.serie}</span> : null}</td>
                    <td>{n.fornecedorNome || n.emitenteNome || '—'}
                      {n.status === 'cancelada' && <span style={{ marginLeft: 8 }}><Badge tone="danger">Cancelada</Badge></span>}
                    </td>
                    <td><Badge tone={v.tone}>{v.label}</Badge>{v.ref && <span className="muted" style={{ marginLeft: 6, fontSize: 12 }}>{v.ref}</span>}</td>
                    <td className="num right" style={{ whiteSpace: 'nowrap' }}>{n.valorTotal != null ? `R$ ${brl(n.valorTotal)}` : '—'}</td>
                    <td className="muted" style={{ fontSize: 12 }}>{n.origem === 'manual' ? 'Digitada' : 'XML'}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </Card>

      {drawer && drawer.tipo === 'xml' && (
        <NotaEntradaXmlForm fornecedores={fornecedores} produtos={produtos}
          onClose={() => { setDrawer(null); load(); }} onSalva={load} />
      )}
      {drawer && drawer.tipo === 'manual' && (
        <NotaEntradaManualForm fornecedores={fornecedores} reloadFornecedores={loadCadastros} produtos={produtos}
          onClose={() => { setDrawer(null); load(); }} onSalva={load} />
      )}
      {drawer && drawer.tipo === 'view' && (
        <NotaEntradaView nota={drawer.nota} prodById={prodById} onNav={onNav} onClose={() => setDrawer(null)} />
      )}
    </div>
  );
}

Object.assign(window, { NotasEntradaHub, gerarContaPagarDaNota, titulosDaNotaTag, notaTagDe });
