/* ============================================================
   cotacoes-fornecedor.jsx — Cotações a Fornecedor (todas categorias)
   Substitui a antiga "Cotações China" (mock, tabela órfã `cotacoes`).
   Lista real de cotacoes_elevador_fornecedor — hoje só Glarie/elevador
   está implementado, mas a tela já cobre qualquer categoria/fornecedor
   futuro (escada rolante, esteira, quadro de comando, porta, cabine).

   Ciclo de status mostrado na tela:
   rascunho/enviado/visualizado → "Aguardando" (fornecedor ainda não respondeu)
   respondido                   → "Recebida"
   em_analise                   → time decidiu seguir com a compra
   aprovada                     → confirmação final de compra
   window.CotacoesFornecedorPage / window.CotacaoFornecedorDetalhe
   rotas: "cotacoes-fornecedor" / "cotacao-fornecedor-detail"
   ============================================================ */

/* fmtDate/fmtDateLong (primitives.jsx) são pra campos de DATA pura
   (concatenam "T12:00:00" pra evitar off-by-one de fuso) — usados aqui
   em cima de sent_at/viewed_at/etc., que já são TIMESTAMP completo,
   viravam "2026-08-05T19:00:47+00:00T12:00:00" e new Date() disso é
   Invalid Date. Helper próprio pra timestamp de verdade. */
function fmtTimestamp(ts) {
  if (!ts) return '—';
  const d = new Date(ts);
  if (isNaN(d.getTime())) return '—';
  return d.toLocaleDateString('pt-BR');
}
/* Grupo "Aguardando" vem de CotacaoElevadorFornecedorStore.STATUS_GROUP_LABEL
   (fonte única — antes esse array vivia só aqui, precificacao-elevador.jsx
   tinha sua própria cópia do rótulo agrupado). */
const CF_AGUARDANDO = (window.CotacaoElevadorFornecedorStore
  ? Object.keys(window.CotacaoElevadorFornecedorStore.STATUS_GROUP_LABEL).filter(
      (k) => window.CotacaoElevadorFornecedorStore.STATUS_GROUP_LABEL[k] === 'Aguardando')
  : ['rascunho', 'enviado', 'visualizado']);
const CF_TABS = [
  { key: 'todos', label: 'Todos' },
  { key: 'aguardando', label: 'Aguardando' },
  { key: 'respondido', label: 'Recebida' },
  { key: 'em_analise', label: 'Em análise' },
  { key: 'aprovada', label: 'Aprovada' },
];

function cfCategoriaLabel(valor) {
  const store = window.CotacaoElevadorFornecedorStore;
  return store.CATEGORIAS_PRODUTO.find((c) => c.value === valor)?.label || valor;
}

function cfPredioLabel(cot) {
  const fe = cot.formularios_elevador;
  if (!fe) return '—';
  const cidadeUf = [fe.local_obra_cidade, fe.local_obra_estado].filter(Boolean).join('/');
  return fe.clientes?.razao_social || cidadeUf || '—';
}

/* Código completo por equipamento (Master ID Fase 1) — numero_documento da
   cotação (já é base+revisão) + índice do ativo, ex.: VPEL-EL0902-A-1. */
function CfUnidadesMasterId({ cot }) {
  const store = window.CotacaoElevadorFornecedorStore;
  const unidades = cot.dados_envio?.unidades || [];
  if (!unidades.length) return <span className="muted">—</span>;
  return (
    <div className="stack" style={{ gap: 6 }}>
      {unidades.map((u) => (
        <div key={u.unidade_id} className="row gap-2" style={{ justifyContent: 'space-between' }}>
          <span>{u.identificador}</span>
          <span className="mono small">{store.assetMasterId(cot, u.indice_ativo) || '—'}</span>
        </div>
      ))}
    </div>
  );
}

function CotacoesFornecedorPage({ setRoute, setSubsel }) {
  const store = window.CotacaoElevadorFornecedorStore;
  const [rows, setRows] = React.useState(null);
  const [tab, setTab] = React.useState('todos');
  const [fFornecedor, setFFornecedor] = React.useState('Todos');
  const [fCategoria, setFCategoria] = React.useState('Todos');
  // Seleção p/ exclusão em lote — exige justificativa antes de excluir de
  // verdade (pedido do usuário, 27/08). Ver excluirComMotivo (soft delete).
  const [selecionadas, setSelecionadas] = React.useState(() => new Set());
  const [showExcluir, setShowExcluir] = React.useState(false);
  const [motivoExclusao, setMotivoExclusao] = React.useState('');
  const [excluindo, setExcluindo] = React.useState(false);

  const carregar = React.useCallback(async () => {
    try {
      const data = await store.listarTodas();
      setRows(data);
    } catch (e) {
      window.toast?.('Erro ao carregar cotações: ' + e.message, 'error');
      setRows([]);
    }
  }, []);
  React.useEffect(() => { carregar(); }, [carregar]);

  const toggleSelecionada = (id) => setSelecionadas((prev) => {
    const next = new Set(prev);
    if (next.has(id)) next.delete(id); else next.add(id);
    return next;
  });

  const confirmarExclusao = async () => {
    if (!motivoExclusao.trim()) return window.toast?.('Informe o motivo da exclusão.', 'warning');
    setExcluindo(true);
    try {
      for (const id of selecionadas) await store.excluirComMotivo(id, motivoExclusao);
      window.toast?.(`${selecionadas.size} cotação(ões) excluída(s).`, 'success');
      setSelecionadas(new Set());
      setMotivoExclusao('');
      setShowExcluir(false);
      await carregar();
    } catch (e) {
      window.toast?.('Erro ao excluir: ' + e.message, 'error');
    } finally {
      setExcluindo(false);
    }
  };

  const fornecedores = React.useMemo(() => (rows ? [...new Set(rows.map((r) => r.fornecedor))] : []), [rows]);

  const filtradas = React.useMemo(() => {
    if (!rows) return [];
    return rows.filter((r) => {
      if (tab === 'aguardando' && !CF_AGUARDANDO.includes(r.status)) return false;
      if (tab !== 'todos' && tab !== 'aguardando' && r.status !== tab) return false;
      if (fFornecedor !== 'Todos' && r.fornecedor !== fFornecedor) return false;
      if (fCategoria !== 'Todos' && r.categoria_produto !== fCategoria) return false;
      return true;
    });
  }, [rows, tab, fFornecedor, fCategoria]);

  if (rows === null) return <div style={{ textAlign: 'center', padding: '60px 0', color: 'var(--fg3)', fontSize: 13 }}>Carregando…</div>;

  const kpi = (pred) => rows.filter(pred).length;
  const contagemTab = (key) => key === 'todos' ? rows.length : key === 'aguardando' ? kpi((r) => CF_AGUARDANDO.includes(r.status)) : kpi((r) => r.status === key);

  return (
    <div className="page fade-in">
      <div className="page-head">
        <div className="page-head__l">
          <div className="page-head__eyebrow"><span className="vp-rule"/>Comercial</div>
          <h1 className="page-head__title">Cotações a Fornecedor</h1>
          <p className="page-head__sub">Solicitações técnicas enviadas aos fornecedores (Glarie e próximos) — cada linha vem de um envio real do Formulário de Elevadores.</p>
        </div>
      </div>

      <div className="grid-4" style={{ marginBottom: 20 }}>
        <KPI label="Aguardando" value={kpi((r) => CF_AGUARDANDO.includes(r.status))} sub="fornecedor ainda não respondeu" icon="clock"/>
        <KPI label="Recebidas" value={kpi((r) => r.status === 'respondido')} sub="prontas p/ decisão" icon="package"/>
        <KPI label="Em análise" value={kpi((r) => r.status === 'em_analise')} sub="decidimos seguir com a compra" icon="trending"/>
        <KPI label="Aprovadas" value={kpi((r) => r.status === 'aprovada')} sub="compra confirmada" icon="check"/>
      </div>

      <div style={{ display: 'flex', gap: 10, alignItems: 'center', marginBottom: 12, flexWrap: 'wrap' }}>
        <select className="input" style={{ maxWidth: 220 }} value={fFornecedor} onChange={(e) => setFFornecedor(e.target.value)}>
          <option value="Todos">Todos os fornecedores</option>
          {fornecedores.map((f) => <option key={f} value={f}>{f}</option>)}
        </select>
        <select className="input" style={{ maxWidth: 220 }} value={fCategoria} onChange={(e) => setFCategoria(e.target.value)}>
          <option value="Todos">Todas as categorias</option>
          {store.CATEGORIAS_PRODUTO.map((c) => <option key={c.value} value={c.value}>{c.label}</option>)}
        </select>
        <span className="small" style={{ color: 'var(--fg3)' }}>{filtradas.length} cotação(ões)</span>
      </div>

      <div style={{ display: 'flex', gap: 6, marginBottom: 12, flexWrap: 'wrap' }}>
        {CF_TABS.map((t) => (
          <Button key={t.key} size="sm" variant={tab === t.key ? 'primary' : 'ghost'} onClick={() => setTab(t.key)}>
            {t.label} <span style={{ opacity: .7 }}>({contagemTab(t.key)})</span>
          </Button>
        ))}
      </div>

      {selecionadas.size > 0 && (
        <div className="row gap-2" style={{ marginBottom: 10, padding: '8px 12px', background: 'var(--vp-gray-50)', border: '1px solid var(--border)', alignItems: 'center' }}>
          <span className="small" style={{ fontWeight: 600 }}>{selecionadas.size} selecionada(s)</span>
          <div className="spacer"/>
          <Button variant="outline" size="sm" onClick={() => setSelecionadas(new Set())}>Limpar seleção</Button>
          <Button variant="danger" size="sm" icon="trash" onClick={() => setShowExcluir(true)}>Excluir selecionadas</Button>
        </div>
      )}

      <Card title="Cotações enviadas" sub="Clique numa linha para abrir o detalhe e as tratativas">
      <div className="table-wrap" style={{ border: 0 }}>
        <table className="t pcp-grid">
          <thead><tr>
            <th style={{ width: 32 }}>
              <input type="checkbox" aria-label="Selecionar todas"
                checked={filtradas.length > 0 && filtradas.every((c) => selecionadas.has(c.id))}
                onChange={(e) => setSelecionadas(e.target.checked ? new Set(filtradas.map((c) => c.id)) : new Set())}/>
            </th>
            <th>Nº Documento</th>
            <th>Nº Cotação</th>
            <th>Prédio / Cliente</th>
            <th>Fornecedor</th>
            <th>Categoria</th>
            <th>Enviado em</th>
            <th>Status</th>
            <th></th>
          </tr></thead>
          <tbody>
            {filtradas.length === 0 && (
              <tr><td colSpan={99} style={{ textAlign: 'center', padding: '48px 0', color: 'var(--fg3)', fontSize: 13 }}>
                Nenhum registro encontrado com os filtros atuais.
              </td></tr>
            )}
            {filtradas.map((c) => (
              <tr key={c.id} style={{ cursor: 'pointer' }} onClick={() => { setSubsel(c); setRoute('cotacao-fornecedor-detail'); }}>
                <td onClick={(e) => e.stopPropagation()}>
                  <input type="checkbox" aria-label={`Selecionar ${c.numero_documento}`}
                    checked={selecionadas.has(c.id)} onChange={() => toggleSelecionada(c.id)}/>
                </td>
                <td style={{ whiteSpace: 'nowrap' }}><span className="mono" style={{ fontSize: 11, color: 'var(--fg3)' }}>{c.numero_documento}</span></td>
                <td style={{ whiteSpace: 'nowrap' }}><span className="mono small">{(() => {
                  const n = c.dados_envio?.header?.numero_cotacao ?? c.formularios_elevador?.numero_cotacao;
                  return n != null ? window.MasterIdEngine.etapaId('cotacao', n) : '—';
                })()}</span></td>
                <td style={{ maxWidth: 240 }}>
                  <div className="cell-main" style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={cfPredioLabel(c)}>{cfPredioLabel(c)}</div>
                  <div className="cell-sub">{c.formularios_elevador?.local_obra_cidade ? `${c.formularios_elevador.local_obra_cidade}/${c.formularios_elevador.local_obra_estado || ''}` : ''}</div>
                </td>
                <td style={{ whiteSpace: 'nowrap' }}>{c.fornecedor}</td>
                <td>{cfCategoriaLabel(c.categoria_produto)}</td>
                <td style={{ whiteSpace: 'nowrap' }}><span className="cell-num">{fmtTimestamp(c.sent_at)}</span></td>
                <td style={{ whiteSpace: 'nowrap' }}><FECefStatusChip status={c.status}/></td>
                <td><Button variant="ghost" size="sm" icon="chevRight" title="Abrir" aria-label="Abrir">Abrir</Button></td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      </Card>

      {showExcluir && (
        <Modal title={`Excluir ${selecionadas.size} cotação(ões)`}
          onClose={() => { if (!excluindo) { setShowExcluir(false); setMotivoExclusao(''); } }}
          width={480}
          footer={<>
            <Button variant="ghost" onClick={() => { setShowExcluir(false); setMotivoExclusao(''); }} disabled={excluindo}>Cancelar</Button>
            <Button variant="danger" onClick={confirmarExclusao} disabled={excluindo || !motivoExclusao.trim()}>
              {excluindo ? 'Excluindo…' : 'Confirmar exclusão'}
            </Button>
          </>}>
          <div className="stack" style={{ gap: 10 }}>
            <p className="small" style={{ margin: 0 }}>
              A cotação sai da listagem, mas os dados ficam preservados (auditoria) — inclusive se já tiver
              precificação, tratativas ou projeto vinculados. Esta ação não pode ser desfeita pela tela.
            </p>
            <div className="stack" style={{ gap: 4 }}>
              <label className="up-eyebrow muted">Motivo da exclusão *</label>
              <textarea className="input" rows={4} value={motivoExclusao}
                onChange={(e) => setMotivoExclusao(e.target.value)}
                placeholder="Ex.: cotação duplicada, fornecedor errado, formulário cancelado…" autoFocus/>
            </div>
          </div>
        </Modal>
      )}
    </div>
  );
}

/* ---------- Tratativas: histórico ÚNICO da conversa com o fornecedor desta cotação.
   07/10 — MÃO DUPLA com o Inbox (Geral → Inbox):
   • SAÍDA: cada mensagem escrita aqui é gravada em tratativas_cotacao E enviada por e-mail ao
     fornecedor (send-email), ficando também no Inbox (Enviados, rótulo "Tratativa").
   • ENTRADA: o que chega no Inbox ligado a esta cotação (resposta do fornecedor, e-mails
     enviados/respondidos pelo Inbox) aparece aqui, na ordem do tempo, ao lado das mensagens.
   • Eventos da própria cotação (enviada, visualizada, respondida pelo formulário) entram na
     mesma linha do tempo. Tudo só leitura, exceto as mensagens novas escritas aqui.
   A tabela das mensagens (tratativas_cotacao) e a do Inbox (emails_projeto) continuam separadas;
   a ligação é a referencia_id (= id desta cotação) e, quando só há 1 fornecedor, o Nº da cotação.
   Nunca se mistura e-mail de outro fornecedor nem do cliente (regra em TratativasStore.listarEmails). */
function irParaRota(caminho) {
  try { window.history.pushState({}, '', caminho); window.dispatchEvent(new PopStateEvent('popstate')); } catch (e) { window.location.assign(caminho); }
}

function CfTratativas({ cotacaoFornecedorId, numeroCotacao, cot }) {
  const store = window.TratativasStore;
  const [msgs, setMsgs] = React.useState([]);
  const [emails, setEmails] = React.useState([]);
  const [hist, setHist] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [texto, setTexto] = React.useState("");
  const [anexos, setAnexos] = React.useState([]);
  const [enviando, setEnviando] = React.useState(false);
  const [uploading, setUploading] = React.useState(false);
  const [aberto, setAberto] = React.useState({});
  const [aviso, setAviso] = React.useState(null);
  const [docsAberto, setDocsAberto] = React.useState(false);
  const formularioId = cot && cot.formulario_elevador_id;

  const reload = React.useCallback(async (silencioso) => {
    if (!silencioso) setLoading(true);
    const [m, e, h] = await Promise.all([
      store.listarPorCotacao(cotacaoFornecedorId),
      store.listarEmails({ cotacaoFornecedorId, numeroCotacao, formularioId }),
      store.listarHistoricoInterno({ cotacaoFornecedorId, numeroCotacao }),
    ]);
    setMsgs(m); setEmails(e); setHist(h); setLoading(false);
  }, [cotacaoFornecedorId, numeroCotacao, formularioId]);
  React.useEffect(() => { reload(); }, [reload]);
  // E-mail novo chega pelo Inbox (cron a cada 10 min) → atualiza sozinho sem piscar a tela.
  React.useEffect(() => {
    const t = setInterval(() => { if (!document.hidden) reload(true); }, 60000);
    const onVis = () => { if (!document.hidden) reload(true); };
    document.addEventListener('visibilitychange', onVis);
    return () => { clearInterval(t); document.removeEventListener('visibilitychange', onVis); };
  }, [reload]);

  const onFiles = async (fileList) => {
    const files = Array.from(fileList || []);
    if (!files.length) return;
    setUploading(true);
    const novos = [];
    for (const file of files) {
      try { novos.push(await store.uploadAnexo(cotacaoFornecedorId, file)); }
      catch (e) { window.toast("Falha no upload: " + e.message, "error"); }
    }
    setAnexos(a => [...a, ...novos]);
    setUploading(false);
  };

  const mostrarResultado = (r) => {
    const em = r && r.__email;
    if (em && em.ok) setAviso({ ok: true, txt: 'Registrado e enviado por e-mail para ' + em.para.join(', ') + '. A resposta dele chega aqui e no Inbox.' });
    else setAviso({ ok: false, txt: 'Mensagem registrada, mas o e-mail NÃO foi enviado' + (em && em.motivo ? ': ' + em.motivo : '.') + ' Avise o fornecedor por outro canal.' });
  };
  const documentosLiberados = !!cot && ['em_analise', 'aprovada'].includes(cot.status);

  const enviar = async () => {
    setEnviando(true);
    try {
      const r = await store.enviar({ cotacaoFornecedorId, numeroCotacao, mensagem: texto, anexos });
      setTexto(""); setAnexos([]);
      mostrarResultado(r);
      await reload(true);
    } catch (e) { window.toast("Erro: " + e.message, "error"); }
    setEnviando(false);
  };

  // Linha do tempo única: mensagens + e-mails do Inbox + eventos da cotação.
  const itens = React.useMemo(() => {
    const lista = [];
    msgs.forEach(m => lista.push({ k: 'msg:' + m.id, tipo: 'msg', quando: m.created_at, m }));
    emails.forEach(e => lista.push({ k: 'em:' + e.id, tipo: 'email', quando: e.data_mensagem, e }));
    // Histórico interno (preço, decisões, eventos com QUEM fez) — vem do vp_logs/eventos_fluxo/decisoes_gerenciais.
    hist.forEach(h => lista.push({ k: h.k, tipo: 'hist', quando: h.quando, h }));
    if (cot) {
      // Eventos "de calendário" da própria cotação só entram quando o histórico não tem o equivalente (cotação antiga).
      const temEvento = (re) => hist.some(h => h.tipo === 'evento' && re.test(h.titulo || ''));
      const canal = cot.channel === 'email' ? 'por e-mail' : cot.channel === 'whatsapp' ? 'por WhatsApp' : cot.channel === 'link' ? 'por link' : '';
      if (cot.sent_at && !temEvento(/enviada/i)) lista.push({ k: 'ev:sent', tipo: 'evento', quando: cot.sent_at, txt: 'Cotação enviada ao fornecedor' + (canal ? ' ' + canal : '') });
      if (cot.viewed_at) lista.push({ k: 'ev:viewed', tipo: 'evento', quando: cot.viewed_at, txt: 'Fornecedor abriu a cotação' });
      if (cot.responded_at && !temEvento(/respondeu/i)) lista.push({ k: 'ev:resp', tipo: 'evento', quando: cot.responded_at, txt: 'Fornecedor respondeu pelo formulário do link' });
    }
    return lista.filter(i => i.quando).sort((a, b) => new Date(a.quando) - new Date(b.quando));
  }, [msgs, emails, hist, cot]);

  if (loading) return <div style={{ textAlign: "center", padding: "40px 0", color: "var(--fg3)", fontSize: 13 }}>Carregando…</div>;

  const nomeEmail = (e) => (e.direcao === 'entrada' ? (e.de_nome || e.de_email || 'Fornecedor') : 'VerticalParts');
  return (
    <Card title="Tratativas" sub="Histórico único desta cotação com o fornecedor: mensagens (saem por e-mail e ficam no Inbox), e-mails do Inbox ligados a ela, mudanças de preço, decisões internas e eventos — tudo em ordem de data. Responda direto aqui.">
      <div className="stack" style={{ gap: 10, maxHeight: 520, overflowY: "auto", padding: "4px 2px" }}>
        {itens.length === 0 && <div className="muted small" style={{ padding: "16px 0", textAlign: "center" }}>Nenhuma mensagem ainda.</div>}
        {itens.map(it => {
          if (it.tipo === 'evento') {
            return (
              <div key={it.k} className="row sb muted small" style={{ padding: "2px 6px", borderLeft: "3px solid var(--border)" }}>
                <span>{it.txt}</span><span className="mono">{fmtTimestamp(it.quando)}</span>
              </div>
            );
          }
          if (it.tipo === 'hist') {
            const h = it.h;
            const cor = h.tipo === 'preco' ? '#b45309' : h.tipo === 'decisao' ? '#7c3aed' : 'var(--border)';
            const rotulo = h.tipo === 'preco' ? 'Preço' : h.tipo === 'decisao' ? 'Decisão' : h.tipo === 'evento' ? 'Evento' : 'Registro';
            return (
              <div key={it.k} style={{ padding: "4px 8px", borderLeft: "3px solid " + cor, background: h.tipo === 'preco' || h.tipo === 'decisao' ? "var(--bg2, #fafafa)" : "transparent" }}>
                <div className="row sb" style={{ gap: 6, flexWrap: "wrap" }}>
                  <span style={{ fontSize: 12.5 }}>
                    <span className="badge" style={{ fontSize: 10, marginRight: 6 }}>{rotulo}</span>
                    <b>{h.titulo}</b>{h.quem ? <span className="muted"> · {h.quem}</span> : null}
                  </span>
                  <span className="muted small mono">{fmtTimestamp(h.quando)}</span>
                </div>
                {h.linhas && h.linhas.length > 0 && (
                  <ul style={{ margin: "4px 0 0 18px", padding: 0, fontSize: 12.5 }}>{h.linhas.map((l, i) => <li key={i}>{l}</li>)}</ul>
                )}
                {h.detalhe && <div className="muted small" style={{ marginTop: 2, whiteSpace: "pre-wrap" }}>Motivo: {h.detalhe}</div>}
              </div>
            );
          }
          if (it.tipo === 'email') {
            const e = it.e; const entrada = e.direcao === 'entrada'; const open = !!aberto[e.id];
            const corpo = String(e.corpo_texto || '').trim();
            return (
              <div key={it.k} style={{ border: "1px solid var(--border)", borderLeft: "3px solid " + (entrada ? "var(--vp-info, #2563eb)" : "var(--fg3)"), padding: "8px 10px", borderRadius: 4, background: entrada ? "var(--bg2, #f7f9ff)" : "transparent" }}>
                <div className="row sb" style={{ marginBottom: 4, flexWrap: "wrap", gap: 6 }}>
                  <span className="row gap-2" style={{ alignItems: "center" }}>
                    <Icon.mail size={12}/>
                    <b style={{ fontSize: 12 }}>{nomeEmail(e)}</b>
                    <span className="badge badge--info" style={{ fontSize: 10 }}>{entrada ? 'E-mail recebido (Inbox)' : 'E-mail enviado (Inbox)'}</span>
                  </span>
                  <span className="muted small mono">{fmtTimestamp(e.data_mensagem)}</span>
                </div>
                <div style={{ fontSize: 12.5, fontWeight: 600 }}>{e.assunto || '(sem assunto)'}</div>
                {corpo && <div style={{ fontSize: 13, whiteSpace: "pre-wrap", marginTop: 4 }}>{open || corpo.length <= 400 ? corpo : corpo.slice(0, 400) + '…'}</div>}
                <div className="row gap-2" style={{ marginTop: 6 }}>
                  {corpo.length > 400 && <button className="btn btn--ghost btn--sm" onClick={() => setAberto(a => ({ ...a, [e.id]: !open }))}>{open ? 'Mostrar menos' : 'Ler tudo'}</button>}
                  <button className="btn btn--ghost btn--sm" onClick={() => irParaRota('/geral/inbox/' + e.id)}>Abrir no Inbox</button>
                </div>
              </div>
            );
          }
          const m = it.m;
          return (
            <div key={it.k} style={{ border: "1px solid var(--border)", padding: "8px 10px", borderRadius: 4 }}>
              <div className="row sb" style={{ marginBottom: 4 }}>
                <span className="row gap-2" style={{ alignItems: "center" }}>
                  <b style={{ fontSize: 12 }}>{m.autor}</b>
                  <span className="badge" style={{ fontSize: 10 }}>Tratativa</span>
                </span>
                <span className="muted small mono">{fmtTimestamp(m.created_at)}</span>
              </div>
              {m.mensagem && <div style={{ fontSize: 13, whiteSpace: "pre-wrap" }}>{m.mensagem}</div>}
              {(m.anexos || []).length > 0 && (
                <div className="row gap-2" style={{ flexWrap: "wrap", marginTop: 6 }}>
                  {m.anexos.map((a, i) => (
                    <a key={i} href={a.url} target="_blank" rel="noreferrer" className="row gap-2"
                      style={{ border: "1px solid var(--border)", padding: "4px 8px", fontSize: 12, alignItems: "center" }}>
                      <Icon.fileText size={13}/>{a.nome}
                    </a>
                  ))}
                </div>
              )}
            </div>
          );
        })}
      </div>
      {aviso && (
        <div style={{ marginTop: 10, padding: "8px 10px", fontSize: 12, border: "1px solid " + (aviso.ok ? "#86efac" : "#fbb039"), background: aviso.ok ? "#f0fdf4" : "#fff8e6", color: aviso.ok ? "#166534" : "#8a5a00" }}>
          {aviso.ok ? '✓ ' : '⚠ '}{aviso.txt}
        </div>
      )}
      <div className="stack" style={{ gap: 6, marginTop: 12, borderTop: "1px solid var(--border)", paddingTop: 12 }}>
        <textarea className="input" rows={2} value={texto} onChange={e => setTexto(e.target.value)}
          placeholder="Escreva para o fornecedor — a mensagem fica registrada aqui e é enviada por e-mail…" style={{ resize: "vertical", fontFamily: "inherit" }}/>
        {anexos.length > 0 && (
          <div className="row gap-2" style={{ flexWrap: "wrap" }}>
            {anexos.map((a, i) => (
              <div key={i} className="row gap-2" style={{ border: "1px solid var(--border)", padding: "4px 8px", fontSize: 12, alignItems: "center" }}>
                <Icon.fileText size={13}/>{a.nome}
                <button onClick={() => setAnexos(prev => prev.filter((_, idx) => idx !== i))} style={{ border: "none", background: "transparent", cursor: "pointer", color: "var(--fg3)" }}><Icon.x size={12}/></button>
              </div>
            ))}
          </div>
        )}
        <div className="row sb">
          <div className="row gap-2">
            <label style={{ display: "inline-flex", alignItems: "center", gap: 6, width: "fit-content", cursor: "pointer", border: "1px solid var(--border)", padding: "6px 12px", fontSize: 12, fontWeight: 600, background: "#fff" }}>
              <Icon.upload size={12}/> {uploading ? "Enviando…" : "Anexar arquivo"}
              <input type="file" multiple style={{ display: "none" }} onChange={e => onFiles(e.target.files)}/>
            </label>
            <Button variant="outline" icon="fileText" disabled={!documentosLiberados || !window.CfEnviarDocumentosModal}
              title={documentosLiberados ? 'Envia a cotação do fornecedor, o Projeto de Instalação assinado e as ID-TAGs numa só mensagem' : 'Disponível depois de "Decidir comprar"'}
              onClick={() => setDocsAberto(true)}>Enviar documentos ao fornecedor</Button>
          </div>
          <Button variant="primary" icon="send" disabled={enviando || uploading} onClick={enviar}>{enviando ? "Enviando…" : "Enviar"}</Button>
        </div>
      </div>
      {docsAberto && window.CfEnviarDocumentosModal && (
        <window.CfEnviarDocumentosModal cot={cot} numeroCotacao={numeroCotacao} onClose={() => setDocsAberto(false)}
          onEnviado={(r) => { mostrarResultado(r); reload(true); }}/>
      )}
    </Card>
  );
}

function CotacaoFornecedorDetalhe({ cot: cotInicial, setRoute }) {
  const store = window.CotacaoElevadorFornecedorStore;
  const [cot, setCot] = React.useState(cotInicial);
  const [verResp, setVerResp] = React.useState(false);
  const [busy, setBusy] = React.useState(false);
  const [tab, setTab] = window.useRouteTab('cotacao-fornecedor-detail', 'detalhes', ['detalhes', 'tratativas'], true);
  // Pré-condições financeiras da decisão de compra (contrato assinado + sinal
  // pago + aval), avaliadas na carga. Sem isso, o botão "Decidir comprar"
  // parecia clicável mas falhava só num toast — e a linha do tempo mostrava
  // "Decidido comprar em —" sem explicar por quê (achado E2E #4).
  const [gate, setGate] = React.useState(null);
  React.useEffect(() => {
    let vivo = true;
    if (!cot || cot.status !== 'respondido' || !window.AvalFinanceiroStore) { setGate(null); return; }
    const numeroCotacao = cot.dados_envio?.header?.numero_cotacao;
    window.AvalFinanceiroStore.podeIniciarCompra(numeroCotacao)
      .then((g) => { if (vivo) setGate(g); })
      .catch(() => { if (vivo) setGate(null); });
    return () => { vivo = false; };
  }, [cot]);
  const bloqueadoDecisao = cot && cot.status === 'respondido' && gate && !gate.ok;

  if (!cot) {
    return <EmptyStateRedirect
      icon="globe"
      title="Nenhuma cotação selecionada"
      message="Escolha uma cotação na listagem para ver a resposta do fornecedor, o link público e decidir a compra."
      ctaLabel="Ir para Cotações a Fornecedor"
      onCta={() => setRoute('cotacoes-fornecedor')}/>;
  }

  const url = store.cotacaoUrl(cot.token);
  const temResposta = ['respondido', 'em_analise', 'aprovada'].includes(cot.status);

  async function decidirComprar() {
    setBusy(true);
    try {
      const atualizado = await store.decidirComprar(cot.id);
      setCot(atualizado);
      window.toast('Cotação movida para Em análise.', 'success');
    } catch (e) { window.toast('Erro: ' + e.message, 'error'); }
    setBusy(false);
  }
  async function aprovar() {
    setBusy(true);
    try {
      const atualizado = await store.aprovar(cot.id);
      setCot(atualizado);
      window.toast('Compra aprovada!', 'success');
    } catch (e) { window.toast('Erro: ' + e.message, 'error'); }
    setBusy(false);
  }

  return (
    <div className="page fade-in">
      <div className="row" style={{ marginBottom: 14 }}>
        <Button variant="ghost" size="sm" icon="chevLeft" onClick={() => setRoute('cotacoes-fornecedor')}>Voltar para Cotações a Fornecedor</Button>
      </div>
      <div className="page-head">
        <div className="page-head__l">
          <div className="page-head__eyebrow"><span className="vp-rule"/>{cot.numero_documento} · {cot.fornecedor}</div>
          <h1 className="page-head__title">{cfPredioLabel(cot)}</h1>
          <div className="row gap-3" style={{ marginTop: 4 }}>
            <FECefStatusChip status={cot.status}/>
            <span className="muted small">{cfCategoriaLabel(cot.categoria_produto)}</span>
            {cot.sent_at && <span className="muted small">Enviado em {fmtTimestamp(cot.sent_at)}</span>}
          </div>
        </div>
        <div className="page-head__r">
          <Button variant="outline" icon="copy" onClick={() => { navigator.clipboard?.writeText(url).then(() => window.toast('Link copiado!', 'success')).catch(() => window.toast('Link: ' + url, 'info')); }}>Copiar link público</Button>
          {temResposta && <Button variant="outline" icon="fileText" onClick={() => setVerResp(true)}>Ver resposta do fornecedor</Button>}
          {cot.status === 'respondido' && <Button variant="primary" icon="check" disabled={busy || bloqueadoDecisao} title={bloqueadoDecisao ? gate.motivo : undefined} onClick={decidirComprar}>{busy ? 'Salvando…' : 'Decidir comprar'}</Button>}
          {cot.status === 'em_analise' && <Button variant="primary" icon="check" disabled={busy} onClick={aprovar}>{busy ? 'Salvando…' : 'Aprovar compra'}</Button>}
          {cot.status === 'aprovada' && <Button variant="ghost" icon="check" disabled>Compra aprovada ✓</Button>}
        </div>
      </div>

      {/* 07/10 — o motivo do bloqueio ficava só na aba "Detalhes"; quem estava em "Tratativas" via o botão
          desabilitado sem explicação. Agora aparece acima das abas, nas duas. */}
      {bloqueadoDecisao && (
        <Card style={{ marginBottom: 16 }} sharp={false}>
          <div className="alert warning" style={{ margin: 0 }}>
            <Icon.warning/>
            <div style={{ flex: 1 }}>
              <div className="alert__title">Ainda não é possível decidir a compra</div>
              <div className="alert__sub" style={{ marginTop: 2 }}>{gate.motivo}</div>
              {Array.isArray(gate.checagens) && gate.checagens.length > 0 && (
                <ul style={{ margin: "6px 0 0", padding: 0, listStyle: "none", fontSize: 12.5 }}>
                  {gate.checagens.map((ck) => (
                    <li key={ck.rotulo} style={{ color: ck.ok ? "#166534" : "#8a5a00" }}>{ck.ok ? "✓" : "○"} {ck.rotulo} — {ck.ok ? "OK" : "pendente"}</li>
                  ))}
                </ul>
              )}
            </div>
          </div>
        </Card>
      )}

      <div className="tbar">
        <div className="seg">
          <button className={tab === 'detalhes' ? 'is-active' : ''} onClick={() => setTab('detalhes')}>Detalhes</button>
          <button className={tab === 'tratativas' ? 'is-active' : ''} onClick={() => setTab('tratativas')}>Tratativas</button>
        </div>
      </div>

      {tab === 'detalhes' && <>
        <Card style={{ marginBottom: 16 }} sharp={false}>
          <div className="alert info" style={{ margin: 0 }}>
            <Icon.link2/>
            <div style={{ flex: 1 }}>
              <div className="alert__title">Link público enviado ao fornecedor</div>
              <div className="alert__sub mono" style={{ fontSize: 12, marginTop: 2 }}>{url}</div>
            </div>
          </div>
        </Card>

        {!temResposta && (
          <Card sub="Ainda não há resposta registrada para esta cotação.">
            <div style={{ padding: '24px 0', textAlign: 'center', color: 'var(--fg3)', fontSize: 13 }}>
              Aguardando o fornecedor preencher o formulário técnico pelo link público.
            </div>
          </Card>
        )}

        <div className="split--wide split">
          <Card title="Dados enviados">
            <KvBlock label="Fornecedor" value={cot.fornecedor}/>
            <KvBlock label="Categoria" value={cfCategoriaLabel(cot.categoria_produto)}/>
            <KvBlock label="Nº Cotação (cliente)" value={cot.dados_envio?.header?.numero_cotacao != null ? window.MasterIdEngine.etapaId('cotacao', cot.dados_envio.header.numero_cotacao) : '—'} mono/>
            <KvBlock label="Equipamentos (Master ID)" value={<CfUnidadesMasterId cot={cot}/>}/>
          </Card>
          <Card title="Linha do tempo">
            <KvBlock label="Enviado em" value={fmtTimestamp(cot.sent_at)}/>
            <KvBlock label="Visualizado em" value={fmtTimestamp(cot.viewed_at)}/>
            <KvBlock label="Respondido em" value={fmtTimestamp(cot.responded_at)}/>
            <KvBlock label="Decidido comprar em" value={cot.decidido_em ? fmtTimestamp(cot.decidido_em) : (bloqueadoDecisao ? 'Bloqueado — faltam avais (veja o aviso no topo)' : '—')}/>
            <KvBlock label="Aprovado em" value={fmtTimestamp(cot.aprovado_em)}/>
          </Card>
        </div>
      </>}

      {tab === 'tratativas' && (
        <CfTratativas cotacaoFornecedorId={cot.id} cot={cot} numeroCotacao={cot.dados_envio?.header?.numero_cotacao ?? (window.MasterIdEngine?.parseNumeroCotacao?.(cot.numero_documento) ?? null)}/>
      )}

      {verResp && <FECotacaoRespostaModal cot={cot} onClose={() => setVerResp(false)}/>}
    </div>
  );
}

Object.assign(window, { CotacoesFornecedorPage, CotacaoFornecedorDetalhe });
