/* global React, Icon, BRL, NUM, Ticker, Drawer */

const CONCORRENTES_PERFIL = {
  'BIC LICITAÇÕES': {
    cnpj: '02.314.876/0001-22', uf: 'SP', cidade: 'São Paulo', porte: 'Médio porte',
    disputas30d: 47, vitorias30d: 18, hitRate: 38, marketShare: 12,
    categorias: ['Papelaria', 'Material Escritório', 'Escolar'],
    perfil: 'agressivo',
    ultVitoria: 'PE-085/2026 · UFMG · R$ 184k',
    confrontosBTM: { total: 32, ganhei: 19, perdi: 13 },
    comportamento: [
      'Costuma dar lances agressivos nos últimos 30 segundos da rodada.',
      'Em 73% das disputas com a BTM, abandona quando lance fica abaixo de R$ 21,40.',
      'Foco em editais até R$ 500k — raramente disputa lotes maiores.',
      'Histórico de inabilitação por documentação (2 ocorrências nos últimos 12 meses).',
    ],
    historico: [
      { dt: '08/05/26', edital: 'PE-167/2026 · TJ-SP', vencedor: 'BIC', valor: 287000 },
      { dt: '02/05/26', edital: 'PE-142/2026 · UFRJ', vencedor: 'BTM', valor: 412000 },
      { dt: '28/04/26', edital: 'PE-098/2026 · Pref. SP', vencedor: 'BIC', valor: 168400 },
      { dt: '22/04/26', edital: 'PE-051/2026 · IFRS', vencedor: 'BTM', valor: 92800 },
      { dt: '14/04/26', edital: 'PE-088/2026 · Pref. Niterói', vencedor: 'BTM', valor: 132500 },
    ],
  },
  'PAPELARIA NORDESTE': {
    cnpj: '14.870.331/0001-09', uf: 'CE', cidade: 'Fortaleza', porte: 'Pequeno porte (EPP)',
    disputas30d: 22, vitorias30d: 7, hitRate: 32, marketShare: 4,
    categorias: ['Papelaria', 'Escolar'],
    perfil: 'conservador',
    ultVitoria: 'PE-067/2026 · IFCE · R$ 87k',
    confrontosBTM: { total: 11, ganhei: 8, perdi: 3 },
    comportamento: [
      'Lances iniciais conservadores · raramente desce abaixo de 5% do valor de referência.',
      'Não costuma seguir até o fim em disputas longas (média de 4 lances por item).',
      'Beneficia-se de tratamento ME/EPP em editais de até R$ 80k.',
    ],
    historico: [
      { dt: '06/05/26', edital: 'PE-156/2026 · Pref. Fortaleza', vencedor: 'PAP. NORDESTE', valor: 78400 },
      { dt: '29/04/26', edital: 'PE-098/2026 · UFC', vencedor: 'BTM', valor: 142000 },
      { dt: '18/04/26', edital: 'PE-077/2026 · TJ-PE', vencedor: 'PAP. NORDESTE', valor: 56800 },
    ],
  },
  'OFFICE SUL DISTRIB.': {
    cnpj: '07.452.118/0001-66', uf: 'PR', cidade: 'Curitiba', porte: 'Médio porte',
    disputas30d: 34, vitorias30d: 11, hitRate: 32, marketShare: 8,
    categorias: ['Material Escritório', 'Escolar', 'Limpeza'],
    perfil: 'oportunista',
    ultVitoria: 'PE-104/2026 · TJ-PR · R$ 218k',
    confrontosBTM: { total: 18, ganhei: 11, perdi: 7 },
    comportamento: [
      'Atua principalmente nos estados do Sul (PR, SC, RS).',
      'Sai do páreo se margem cair abaixo de 30% — pouca tolerância a guerra de preço.',
      'Costuma cobrir 3 ou 4 itens estratégicos por edital, não disputa lote inteiro.',
    ],
    historico: [
      { dt: '11/05/26', edital: 'PE-188/2026 · UFRGS', vencedor: 'OFFICE SUL', valor: 198400 },
      { dt: '04/05/26', edital: 'PE-122/2026 · IFRS', vencedor: 'BTM', valor: 87000 },
      { dt: '27/04/26', edital: 'PE-066/2026 · TJ-PR', vencedor: 'OFFICE SUL', valor: 256800 },
    ],
  },
  'COMERCIAL OESTE': {
    cnpj: '23.114.998/0001-44', uf: 'GO', cidade: 'Goiânia', porte: 'Pequeno porte (EPP)',
    disputas30d: 18, vitorias30d: 5, hitRate: 28, marketShare: 3,
    categorias: ['Papelaria', 'Material Escritório'],
    perfil: 'recente',
    ultVitoria: 'PE-044/2026 · Pref. Goiânia · R$ 48k',
    confrontosBTM: { total: 6, ganhei: 5, perdi: 1 },
    comportamento: [
      'Fornecedor recente no PNCP (cadastrado há 9 meses).',
      'Lances tímidos · costuma desistir após o 3º lance.',
      'Atua exclusivamente em editais do Centro-Oeste.',
    ],
    historico: [
      { dt: '07/05/26', edital: 'PE-099/2026 · UFG', vencedor: 'BTM', valor: 124000 },
      { dt: '25/04/26', edital: 'PE-044/2026 · Pref. Goiânia', vencedor: 'COMERCIAL O.', valor: 48000 },
    ],
  },
};

function MDisputa({ onNav }) {
  const [disputas, setDisputas] = React.useState([]);
  const [editais, setEditais] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [activeAuctionId, setActiveAuctionId] = React.useState(null);  // disputa.id (uuid)
  const [items, setItems] = React.useState([]);                         // edital_itens
  const [activeItemId, setActiveItemId] = React.useState(null);
  const [allLances, setAllLances] = React.useState([]);                 // lances da disputa atual
  const [fornecedor, setFornecedor] = React.useState(null);
  const [autoLance, setAutoLance] = React.useState(false);
  const [toast, setToast] = React.useState(null);
  const [showAddDisputa, setShowAddDisputa] = React.useState(false);

  const showToast = (msg, ms = 3500) => { setToast(msg); setTimeout(() => setToast(null), ms); };

  const reloadDisputasEditais = React.useCallback(async () => {
    const [rows, eds] = await Promise.all([
      window.dataApi.listDisputas(),
      window.dataApi.listEditais(),
    ]);
    setDisputas(rows);
    setEditais(eds);
    return { rows, eds };
  }, []);

  // Carrega disputas + editais (para listar elegíveis no modal)
  React.useEffect(() => {
    let mounted = true;
    reloadDisputasEditais()
      .then(({ rows }) => {
        if (!mounted) return;
        if (rows.length > 0) setActiveAuctionId(rows[0].id);
        setLoading(false);
      })
      .catch(() => { if (mounted) setLoading(false); });
    return () => { mounted = false; };
  }, [reloadDisputasEditais]);

  const handleAddDisputaFromEdital = async (editalId) => {
    try {
      const nova = await window.dataApi.insertDisputa({ edital_id: editalId });
      try { await window.dataApi.updateEditalStatus(editalId, 'disputa'); } catch (_) { /* trigger histórico cuida */ }
      await reloadDisputasEditais();
      setActiveAuctionId(nova.id);
      setShowAddDisputa(false);
      showToast(`${nova.edital?.numero || editalId} ativado como disputa · monitoramento iniciado`);
    } catch (e) {
      showToast(`Erro ao criar disputa: ${e?.message || e}`, 6000);
    }
  };

  const handleAddDisputaManual = async (form) => {
    try {
      const novoEdital = await window.dataApi.insertEdital({
        numero: form.id,
        orgao: form.orgao,
        uf: form.uf,
        plataforma: form.plataforma,
        valor: 0,
        abertura: form.abertura,
        itens: 0,
        status: 'disputa',
        score: 75,
        match: 'media',
      });
      const nova = await window.dataApi.insertDisputa({ edital_id: novoEdital.id });
      await reloadDisputasEditais();
      setActiveAuctionId(nova.id);
      setShowAddDisputa(false);
      showToast(`Disputa ${form.id} cadastrada manualmente · aguardando abertura`);
    } catch (e) {
      showToast(`Erro ao cadastrar: ${e?.message || e}`, 6000);
    }
  };

  // Carrega itens e lances quando muda de auction
  React.useEffect(() => {
    if (!activeAuctionId) return;
    const disp = disputas.find(d => d.id === activeAuctionId);
    if (!disp?.edital_id) return;

    let mounted = true;
    Promise.all([
      window.dataApi.listEditalItens(disp.edital_id),
      window.dataApi.listLancesByDisputa(activeAuctionId),
    ]).then(([itensList, lancesList]) => {
      if (!mounted) return;
      setItems(itensList);
      setAllLances(lancesList);
      if (itensList.length > 0) setActiveItemId(itensList[0]._raw?.id || itensList[0].id);
    }).catch(() => { if (mounted) { setItems([]); setAllLances([]); } });
    return () => { mounted = false; };
  }, [activeAuctionId, disputas]);

  const disputa = disputas.find(d => d.id === activeAuctionId) || null;
  const editalItem = items.find(i => (i._raw?.id || i.id) === activeItemId) || items[0] || null;

  // Lances do item selecionado (já em ordem desc)
  const lancesDoItem = React.useMemo(() => {
    const eid = editalItem?._raw?.id || editalItem?.id;
    if (!eid) return [];
    return allLances.filter(l => l.edital_item_id === eid);
  }, [allLances, editalItem]);

  // Resumo de cada item (último lance, quem ganha)
  const itemSummary = React.useMemo(() => {
    const map = {};
    items.forEach(it => {
      const eid = it._raw?.id || it.id;
      const meusItens = allLances.filter(l => l.edital_item_id === eid);
      const meu = meusItens.find(l => l.meu_lance);
      const melhor = meusItens.length > 0 ? Math.min(...meusItens.map(l => l.valor)) : null;
      const lider = meusItens.length > 0 ? meusItens.find(l => l.valor === melhor) : null;
      map[eid] = { meu: meu?.valor || null, melhor, ganhando: lider?.meu_lance || false };
    });
    return map;
  }, [items, allLances]);

  // Disputa header counts (derived)
  const dispHeader = React.useMemo(() => {
    if (!disputa || items.length === 0) return null;
    let ganhos = 0, perdidos = 0, disputando = 0;
    items.forEach(it => {
      const eid = it._raw?.id || it.id;
      const sum = itemSummary[eid];
      if (!sum || sum.melhor === null) disputando++;
      else if (sum.ganhando) ganhos++;
      else perdidos++;
    });
    return {
      id: disputa.id,
      edital_numero: disputa.edital?.numero,
      orgao: disputa.edital?.orgao,
      plataforma: disputa.edital?.plataforma,
      uf: disputa.edital?.uf,
      status: disputa.status,
      ganhos, perdidos, disputando,
      total: items.length,
    };
  }, [disputa, items, itemSummary]);

  const enviarLance = async (valor) => {
    if (!valor || valor <= 0 || !editalItem || !activeAuctionId) return;
    try {
      const eid = editalItem._raw?.id || editalItem.id;
      const novoLance = await window.dataApi.insertLance({
        disputa_id: activeAuctionId,
        edital_item_id: eid,
        valor: +valor.toFixed(2),
        autor: 'BTM',
        meu_lance: true,
      });
      setAllLances(prev => [novoLance, ...prev]);
      showToast(`Lance R$ ${valor.toFixed(2)} enviado · BTM`);
    } catch (e) {
      showToast(`Erro ao enviar lance: ${e?.message || e}`, 5000);
    }
  };

  // Auto-lance: a cada 8s
  React.useEffect(() => {
    if (!autoLance || !editalItem) return;
    const eid = editalItem._raw?.id || editalItem.id;
    const intv = setInterval(() => {
      const lances = allLances.filter(l => l.edital_item_id === eid);
      const editalUnit = parseFloat(editalItem._raw?.valor_unitario_estimado) || editalItem.unit || 0;
      const melhor = lances.length > 0 ? Math.min(...lances.map(l => l.valor)) : editalUnit;
      const minSeguro = editalUnit * 0.7;  // proteção: 70% do valor de referência
      const proximo = +(melhor - 0.01).toFixed(2);
      if (proximo > minSeguro) {
        enviarLance(proximo);
      } else {
        setAutoLance(false);
        showToast('Auto-lance desativado · próximo lance ficaria abaixo do mínimo seguro (70% do edital)');
      }
    }, 8000);
    return () => clearInterval(intv);
  }, [autoLance, editalItem, allLances]);

  return (
    <>
      <Ticker />
      <AuctionTabs auctions={disputas} active={activeAuctionId} onSelect={setActiveAuctionId} onAddDisputa={() => setShowAddDisputa(true)} loading={loading} itemSummaryMap={itemSummary} />
      <div style={{ padding: 14, height: 'calc(100vh - 48px - 30px - 50px)', display: 'grid', gridTemplateColumns: '300px 1fr 340px', gap: 12, overflow: 'hidden' }}>
        <ItemsList items={items} disputa={dispHeader} active={activeItemId} onSelect={setActiveItemId} itemSummary={itemSummary} />
        {editalItem ? (
          <CenterDisputa
            item={editalItem}
            lancesDoItem={lancesDoItem}
            summary={itemSummary[editalItem._raw?.id || editalItem.id]}
            disputa={dispHeader}
            onFornecedor={setFornecedor}
            onEnviarLance={enviarLance}
            autoLance={autoLance}
            onToggleAuto={() => { setAutoLance(v => !v); showToast(autoLance ? 'Auto-lance desativado' : 'Auto-lance ativado · cobertura a cada 8s respeitando o mínimo seguro'); }}
          />
        ) : (
          <div className="card" style={{ display: 'grid', placeItems: 'center', color: 'var(--fg-3)', fontSize: 12 }}>
            {loading ? <><span className="spinner" style={{ marginRight: 8 }}></span> Carregando...</> : 'Selecione uma disputa'}
          </div>
        )}
        <ChatPanel itemIdx={editalItem?.numero_item || 0} onToast={showToast} />
      </div>
      {fornecedor && <FornecedorDrawer fornecedor={fornecedor} onClose={() => setFornecedor(null)} />}
      {showAddDisputa && <AddDisputaModal
        onClose={() => setShowAddDisputa(false)}
        editais={editais}
        disputasEditalIds={new Set(disputas.map(d => d.edital_id).filter(Boolean))}
        onPickElegivel={handleAddDisputaFromEdital}
        onSubmitManual={handleAddDisputaManual}
      />}
      {toast && (
        <div className="alert-banner alert-lime" style={{ position: 'fixed', bottom: 22, right: 22, zIndex: 300, maxWidth: 480, boxShadow: '0 12px 32px rgba(0,0,0,0.5)', animation: 'drawer-fade 0.18s ease-out' }}>
          <Icon name="check" size={14} />
          <div style={{ flex: 1 }}>{toast}</div>
          <button className="btn btn-ghost btn-sm" onClick={() => setToast(null)}><Icon name="x" size={11} /></button>
        </div>
      )}
    </>
  );
}

/* ── AUCTION TABS ──────────────────────────────────────────── */
function AuctionTabs({ auctions, active, onSelect, onAddDisputa, loading }) {
  if (loading) {
    return <div style={{ padding: '12px 14px', borderBottom: '1px solid var(--line-1)', background: 'var(--bg-1)', color: 'var(--fg-3)', fontSize: 12 }}>
      <span className="spinner" style={{ marginRight: 8 }}></span> Carregando disputas...
    </div>;
  }
  if (auctions.length === 0) {
    return <div style={{ padding: '12px 14px', borderBottom: '1px solid var(--line-1)', background: 'var(--bg-1)', color: 'var(--fg-3)', fontSize: 12 }}>
      Nenhuma disputa cadastrada.
      <button className="btn btn-ghost btn-sm" onClick={onAddDisputa} style={{ marginLeft: 8 }}><Icon name="plus" size={11} /> Disputa</button>
    </div>;
  }
  return (
    <div style={{ display: 'flex', gap: 0, padding: '0 14px', borderBottom: '1px solid var(--line-1)', background: 'var(--bg-1)', overflowX: 'auto' }}>
      {auctions.map(a => {
        const isActive = a.id === active;
        const num = a.edital?.numero || '—';
        const orgao = a.edital?.orgao || '';
        const plataforma = a.edital?.plataforma || '';
        const uf = a.edital?.uf || '';
        return (
          <div key={a.id} onClick={() => onSelect(a.id)} style={{
            display: 'flex', alignItems: 'center', gap: 10,
            padding: '10px 16px',
            borderBottom: `2px solid ${isActive ? 'var(--lime)' : 'transparent'}`,
            marginBottom: -1,
            cursor: 'pointer',
            opacity: isActive ? 1 : 0.7,
            whiteSpace: 'nowrap',
          }}>
            {a.status === 'live' ? <span className="dot-pulse red" style={{ width: 6, height: 6 }}></span> : <span style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--fg-3)' }}></span>}
            <div>
              <div style={{ fontSize: 11.5, fontWeight: isActive ? 600 : 500, color: isActive ? 'var(--fg-0)' : 'var(--fg-1)' }}>
                {num} <span style={{ fontFamily: 'IBM Plex Mono', fontSize: 10.5, color: 'var(--fg-3)', fontWeight: 400 }}>· {orgao}</span>
              </div>
              <div style={{ fontSize: 10, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono', marginTop: 1 }}>
                {plataforma} · {uf} · <span style={{ color: a.status === 'live' ? 'var(--lime)' : 'var(--fg-3)' }}>{a.status.toUpperCase()}</span>
              </div>
            </div>
          </div>
        );
      })}
      <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', padding: '0 8px' }}>
        <button className="btn btn-ghost btn-sm" title="Adicionar disputa ativa" onClick={onAddDisputa}><Icon name="plus" size={11} /> Disputa</button>
      </div>
    </div>
  );
}

/* ── ITEMS LIST ────────────────────────────────────────────── */
function ItemsList({ items, disputa, active, onSelect, itemSummary }) {
  return (
    <div className="card" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
      <div className="card-head">
        <span className={`dot-pulse ${disputa?.status === 'live' ? 'red' : ''}`} style={disputa?.status !== 'live' ? { background: 'var(--fg-3)' } : undefined}></span>
        <div>
          <div className="t" style={{ marginBottom: 2 }}>{disputa?.edital_numero || '—'} · {(disputa?.status || '').toUpperCase()}</div>
          <div className="s">{disputa?.orgao} · {disputa?.plataforma}</div>
        </div>
      </div>
      <div style={{ padding: '8px 10px', borderBottom: '1px solid var(--line-1)', display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 6, fontSize: 10.5, fontFamily: 'IBM Plex Mono' }}>
        <div><div style={{ color: 'var(--fg-3)' }}>GANHANDO</div><div style={{ color: 'var(--lime)', fontWeight: 600 }}>{disputa?.ganhos ?? 0} / {disputa?.total ?? 0}</div></div>
        <div><div style={{ color: 'var(--fg-3)' }}>SEM LANCE</div><div style={{ color: 'var(--amber)', fontWeight: 600 }}>{disputa?.disputando ?? 0} / {disputa?.total ?? 0}</div></div>
        <div><div style={{ color: 'var(--fg-3)' }}>PERDENDO</div><div style={{ color: 'var(--red)', fontWeight: 600 }}>{disputa?.perdidos ?? 0} / {disputa?.total ?? 0}</div></div>
      </div>
      <div style={{ overflowY: 'auto', flex: 1 }}>
        {items.length === 0 && (
          <div style={{ padding: 22, textAlign: 'center', color: 'var(--fg-3)', fontSize: 11.5 }}>
            Sem itens cadastrados para este edital.
          </div>
        )}
        {items.map(it => {
          const eid = it._raw?.id || it.id;
          const sum = itemSummary[eid];
          return <ItemRow key={eid} item={it} summary={sum} isActive={eid === active} onClick={() => onSelect(eid)} />;
        })}
      </div>
    </div>
  );
}

function ItemRow({ item, summary, isActive, onClick }) {
  let stripeColor = 'var(--fg-4)';
  let label = 'SEM LANCE';
  let labelColor = 'var(--fg-3)';
  if (summary?.melhor !== null && summary?.melhor !== undefined) {
    if (summary.ganhando) { stripeColor = 'var(--lime)'; label = '✓ GANHANDO'; labelColor = 'var(--lime)'; }
    else                  { stripeColor = 'var(--red)';  label = 'PERDENDO';   labelColor = 'var(--red)'; }
  }

  return (
    <div onClick={onClick} className="clickable" style={{
      padding: '10px 12px',
      borderLeft: `3px solid ${stripeColor}`,
      borderBottom: '1px solid var(--line-1)',
      background: isActive ? 'var(--bg-3)' : 'transparent',
      boxShadow: isActive ? 'inset 0 0 0 1px var(--lime-border)' : 'none',
    }}>
      <div className="flex items-center justify-between" style={{ marginBottom: 4 }}>
        <span className="mono" style={{ fontSize: 10.5, color: 'var(--fg-3)' }}>ITEM {String(item.numero_item || 0).padStart(2, '0')}</span>
        <span className="mono" style={{ fontSize: 9.5, color: labelColor, fontWeight: 600 }}>{label}</span>
      </div>
      <div style={{ fontSize: 12, fontWeight: 500, marginBottom: 2 }}>{item.desc}</div>
      <div style={{ fontSize: 10.5, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono', marginBottom: 6 }}>{NUM(item.qtd)} un · ref. {BRL(item.unit)}</div>
      {summary?.meu != null && (
        <div className="flex items-center gap-3" style={{ fontSize: 10.5, fontFamily: 'IBM Plex Mono' }}>
          <span><span style={{ color: 'var(--fg-3)' }}>seu:</span> <span style={{ color: 'var(--fg-0)' }}>{BRL(summary.meu)}</span></span>
          {summary.melhor !== null && <span><span style={{ color: 'var(--fg-3)' }}>melhor:</span> <span style={{ color: summary.ganhando ? 'var(--lime)' : 'var(--red)' }}>{BRL(summary.melhor)}</span></span>}
        </div>
      )}
    </div>
  );
}

/* ── CENTER DISPUTA ────────────────────────────────────────── */
function CenterDisputa({ item, lancesDoItem, summary, disputa, onFornecedor, onEnviarLance, autoLance, onToggleAuto }) {
  // View shape uniforme: traduz edital_item + summary em campos esperados pela UI
  const view = React.useMemo(() => {
    if (!item) return null;
    const eid = item._raw?.id || item.id;
    const editalUnit = parseFloat(item._raw?.valor_unitario_estimado) || item.unit || 0;
    return {
      id: eid,
      idx: item.numero_item || 0,
      desc: item.desc,
      cod: item.btm,
      ncm: item.ncm,
      qtd: item.qtd,
      edital: editalUnit,
      minSeguro: editalUnit * 0.7,
      melhor: summary?.melhor ?? editalUnit,
      meu: summary?.meu ?? null,
      mine: summary?.ganhando || false,
    };
  }, [item, summary]);

  const [meuLance, setMeuLance] = React.useState(0);
  const [tick, setTick] = React.useState(0);

  React.useEffect(() => {
    if (view) setMeuLance(view.meu || view.melhor || view.edital);
  }, [view?.id, disputa?.id]);

  React.useEffect(() => {
    const i = setInterval(() => setTick(t => t + 1), 1000);
    return () => clearInterval(i);
  }, []);

  if (!view) return <div style={{ display: 'grid', placeItems: 'center', color: 'var(--fg-3)' }}>Selecione um item à esquerda</div>;

  const isFechado = disputa?.status === 'encerrada';
  const isLive = disputa?.status === 'live';
  const ganho = isFechado && view.mine;
  const perdido = isFechado && !view.mine && view.melhor < view.edital;
  const concorrentes = useConcorrentes(view, disputa);

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 12, overflow: 'hidden' }}>
      {/* Header item */}
      <div className="card" style={{ flexShrink: 0 }}>
        <div style={{ padding: 14, display: 'flex', alignItems: 'center', gap: 14 }}>
          <div>
            <div className="eyebrow" style={{ margin: 0 }}>
              <span className="mono">ITEM {String(view.idx).padStart(2, '0')} · {isFechado ? (ganho ? 'GANHO' : 'PERDIDO') : view.melhor < view.edital && !view.mine ? 'PERDENDO' : isLive ? 'DISPUTA' : 'AGUARDANDO'}</span>
              {isLive && <><span className="dot-pulse" style={{ width: 6, height: 6 }}></span><span style={{ color: 'var(--lime)' }}>LIVE</span></>}
            </div>
            <div style={{ fontSize: 18, fontWeight: 600, letterSpacing: '-0.01em' }}>{view.desc}</div>
            <div style={{ fontSize: 12, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono' }}>{NUM(view.qtd)} unidades · {view.cod || '—'} · NCM {view.ncm}</div>
          </div>
          <div style={{ marginLeft: 'auto', display: 'flex', gap: 24, alignItems: 'center' }}>
            <BigStat label="EDITAL" value={view.edital.toFixed(2)} color="var(--fg-2)" />
            <BigStat label="MIN. SEGURO" value={view.minSeguro.toFixed(2)} color="var(--amber)" />
            <BigStat label={isFechado ? 'FINAL' : 'MELHOR LANCE'} value={(view.melhor || view.edital).toFixed(2)} color={view.mine ? 'var(--lime)' : 'var(--red)'} emphasis />
          </div>
        </div>
        <div style={{ padding: '0 14px 14px', display: 'flex', alignItems: 'center', gap: 10, fontSize: 11.5, color: 'var(--fg-2)', fontFamily: 'IBM Plex Mono' }}>
          <Icon name="clock" size={11} style={{ color: isLive ? 'var(--amber)' : 'var(--fg-3)' }} />
          <span>TEMPO DE LANCE:</span>
          <span className="mono" style={{ color: isLive ? 'var(--amber)' : 'var(--fg-3)', fontSize: 16, fontWeight: 600 }}>
            {isFechado ? '—' : isLive ? `00:${String(58 - (tick % 60)).padStart(2, '0')}` : 'aguardando'}
          </span>
          <span>·</span>
          <span>{lancesDoItem.length} lance(s) registrados</span>
        </div>
      </div>

      {/* Gráfico de lances */}
      {!isFechado && lancesDoItem.length > 0 && (
        <div className="card" style={{ flexShrink: 0 }}>
          <div className="card-head">
            <Icon name="activity" />
            <div className="t">Histórico de lances</div>
          </div>
          <div style={{ padding: 14, height: 160 }}>
            <BidChart view={view} lances={lancesDoItem} />
          </div>
        </div>
      )}

      {/* Painel de lance */}
      {!isFechado && (
        <div className="card" style={{ flexShrink: 0, background: 'var(--bg-2)', border: '1px solid var(--lime-border)' }}>
          <div style={{ padding: 16 }}>
            <div className="flex items-center gap-3" style={{ marginBottom: 12 }}>
              <span className="badge badge-lime">SEU PRÓXIMO LANCE</span>
              <span style={{ fontSize: 11.5, color: 'var(--fg-2)' }}>· menor lance atual: <strong style={{ color: 'var(--fg-0)' }}>R$ {(view.melhor || view.edital).toFixed(2)}</strong></span>
              <div style={{ marginLeft: 'auto', fontSize: 11, fontFamily: 'IBM Plex Mono', color: 'var(--fg-3)' }}>
                MARGEM: <span style={{ color: meuLance > view.minSeguro ? 'var(--lime)' : 'var(--red)' }}>{meuLance > 0 ? (((meuLance - view.minSeguro) / meuLance) * 100).toFixed(1) : '0.0'}%</span>
              </div>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '1fr auto auto', gap: 10, alignItems: 'center' }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
                <span style={{ fontSize: 26, fontWeight: 600, fontFamily: 'IBM Plex Mono', color: 'var(--fg-3)' }}>R$</span>
                <input
                  className="mono"
                  value={meuLance.toFixed(2)}
                  onChange={e => setMeuLance(parseFloat(e.target.value) || 0)}
                  style={{ background: 'var(--bg-1)', border: '1px solid var(--line-2)', borderRadius: 6, color: 'var(--lime)', fontSize: 32, fontWeight: 600, padding: '6px 14px', width: 180, outline: 'none', fontFamily: 'IBM Plex Mono' }}
                />
                <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                  <button className="btn btn-sm" onClick={() => setMeuLance(v => +(v - 0.01).toFixed(2))}>−R$ 0,01</button>
                  <button className="btn btn-sm" onClick={() => setMeuLance(v => +(v - 0.10).toFixed(2))}>−R$ 0,10</button>
                </div>
              </div>
              <div style={{ width: 1, alignSelf: 'stretch', background: 'var(--line-2)' }}></div>
              <div style={{ display: 'flex', gap: 8 }}>
                <button className="btn btn-primary" style={{ padding: '12px 22px', fontSize: 13 }} onClick={() => onEnviarLance(meuLance)}>
                  <Icon name="bolt" /> ENVIAR LANCE
                </button>
                <button
                  className={autoLance ? 'btn btn-danger' : 'btn'}
                  style={{ padding: '12px 14px' }}
                  onClick={onToggleAuto}
                  title={autoLance ? 'Auto-lance ATIVO · clique para desligar' : 'Ativar auto-lance · sistema cobrirá lances a cada 8s'}
                >
                  {autoLance ? '⏸ AUTO-LANCE ON' : '▶ AUTO-LANCE'}
                </button>
              </div>
            </div>
            {meuLance < view.minSeguro && meuLance > 0 && (
              <div className="alert-banner alert-red" style={{ marginTop: 12 }}>
                <Icon name="warn" size={13} />
                <strong>ALERTA · ABAIXO DO PREÇO MÍNIMO SEGURO</strong> — abaixo de 70% do valor de referência do edital.
              </div>
            )}
          </div>
        </div>
      )}

      {isFechado && (
        <div className={`alert-banner ${ganho ? 'alert-lime' : 'alert-red'}`} style={{ flexShrink: 0 }}>
          <Icon name={ganho ? 'check' : 'x'} size={14} />
          <div style={{ flex: 1 }}>
            <strong>Item {String(view.idx).padStart(2, '0')} {ganho ? 'adjudicado à BTM' : 'perdido'}</strong>
            <div style={{ fontSize: 11.5, color: 'var(--fg-2)', marginTop: 2 }}>
              {ganho && view.meu ? `Lance vencedor: R$ ${view.meu.toFixed(2)} · Total ${BRL(view.meu * view.qtd)}` :
               view.melhor !== view.edital ? `Vencedor a R$ ${view.melhor.toFixed(2)}` : 'Sem disputa'}
            </div>
          </div>
        </div>
      )}

      {/* Histórico real de lances */}
      <div className="card" style={{ flex: 1, overflow: 'hidden', display: 'flex', flexDirection: 'column' }}>
        <div className="card-head">
          <Icon name="users" />
          <div className="t">Histórico de Lances · Item {String(view.idx).padStart(2, '0')}</div>
          <span className="s" style={{ marginLeft: 'auto' }}>{lancesDoItem.length} lance(s)</span>
        </div>
        <div style={{ overflowY: 'auto', flex: 1 }}>
          {lancesDoItem.length === 0 ? (
            <div style={{ padding: 22, textAlign: 'center', color: 'var(--fg-3)', fontSize: 12 }}>
              Sem lances registrados ainda. Use o painel acima pra enviar o primeiro.
            </div>
          ) : (
            <table className="tbl">
              <thead>
                <tr>
                  <th style={{ width: 60 }}>Pos</th>
                  <th>Autor</th>
                  <th style={{ width: 100, textAlign: 'right' }}>Lance</th>
                  <th style={{ width: 110, textAlign: 'right' }}>Total</th>
                  <th style={{ width: 90 }}>Hora</th>
                </tr>
              </thead>
              <tbody>
                {lancesDoItem
                  .slice()
                  .sort((a, b) => a.valor - b.valor)
                  .map((l, idx) => {
                    const isMelhor = idx === 0;
                    return (
                      <tr key={l.id} style={{ background: l.meu_lance ? 'var(--lime-soft)' : 'transparent' }}>
                        <td><span className={`badge ${isMelhor ? 'badge-lime' : ''}`}>{idx + 1}º</span></td>
                        <td>
                          <strong>{l.autor}</strong>{l.meu_lance && <span style={{ color: 'var(--fg-3)' }}> (você)</span>}
                          {l.cnpj_autor && <div style={{ fontSize: 10.5, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono' }}>{l.cnpj_autor}</div>}
                        </td>
                        <td className="num-col" style={{ color: isMelhor ? 'var(--lime)' : 'var(--fg-1)', fontWeight: isMelhor ? 600 : 400 }}>R$ {l.valor.toFixed(2)}</td>
                        <td className="num-col">{BRL(l.valor * view.qtd)}</td>
                        <td className="mono" style={{ fontSize: 11, color: 'var(--fg-3)' }}>{new Date(l.ocorrido_em).toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit', second: '2-digit' })}</td>
                      </tr>
                    );
                  })}
              </tbody>
            </table>
          )}
        </div>
      </div>
    </div>
  );
}

function useConcorrentes(view, disputa) {
  // mantido para compat — futuramente vem de tabela de concorrentes
  return [];
}

function BigStat({ label, value, color, emphasis }) {
  return (
    <div style={{ textAlign: 'right' }}>
      <div className="field-label">{label}</div>
      <div className="mono" style={{ fontSize: emphasis ? 24 : 18, fontWeight: 600, color, letterSpacing: '-0.02em' }}>R$ {value}</div>
    </div>
  );
}

function BidChart({ view, lances }) {
  // ordena cronologicamente
  const sorted = [...lances].sort((a, b) => new Date(a.ocorrido_em) - new Date(b.ocorrido_em));
  const meusLances  = sorted.filter(l => l.meu_lance).map(l => l.valor);
  const outrosLances = sorted.filter(l => !l.meu_lance).map(l => l.valor);
  const edital = view.edital;
  const W = 600, H = 130;
  const allVals = [...sorted.map(l => l.valor), edital];
  if (allVals.length < 2) {
    return <div style={{ color: 'var(--fg-3)', fontSize: 12, display: 'grid', placeItems: 'center', height: '100%' }}>
      Poucos lances ainda · gráfico aparece a partir de 2 lances
    </div>;
  }
  const min = Math.min(...allVals) * 0.98;
  const max = Math.max(...allVals) * 1.02;
  const r = max - min || 1;
  const toPath = (arr) => arr.length > 1
    ? arr.map((v, i) => `${i === 0 ? 'M' : 'L'} ${(i / (arr.length - 1)) * W} ${H - ((v - min) / r) * H}`).join(' ')
    : '';
  return (
    <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" style={{ width: '100%', height: '100%' }}>
      {[0, 25, 50, 75, 100].map(p => (
        <line key={p} x1="0" x2={W} y1={H * p / 100} y2={H * p / 100} stroke="var(--line-1)" strokeWidth="0.5" />
      ))}
      <line x1="0" x2={W} y1={H - ((edital - min) / r) * H} y2={H - ((edital - min) / r) * H} stroke="var(--amber)" strokeWidth="1" strokeDasharray="4 4" />
      <text x={W - 4} y={H - ((edital - min) / r) * H - 4} fill="var(--amber)" fontSize="9" textAnchor="end" fontFamily="IBM Plex Mono">EDITAL R$ {edital.toFixed(2)}</text>
      {outrosLances.length > 1 && <path d={toPath(outrosLances)} stroke="var(--red)" strokeWidth="1.5" fill="none" />}
      {meusLances.length > 1 && <path d={toPath(meusLances)} stroke="var(--lime)" strokeWidth="2" fill="none" />}
    </svg>
  );
}

/* ── CHAT PANEL ────────────────────────────────────────────── */
const TEMPLATES_CHAT = [
  { l: 'Confirmar recebimento', t: 'Recebido, pregoeiro. Estamos analisando.' },
  { l: 'Confirmar amostras', t: 'Confirmado, pregoeiro. Amostras serão enviadas ainda hoje via Sedex 10.' },
  { l: 'Solicitar prorrogação', t: 'Solicitamos respeitosamente a prorrogação do prazo em 24h para apresentação de documento complementar.' },
  { l: 'Disponível para esclarec.', t: 'Estamos à disposição para quaisquer esclarecimentos via chat ou pelo e-mail contato@btmsigma.com.' },
  { l: 'Capacidade técnica', t: 'BTM atende integralmente a especificação técnica. Catálogo de produtos disponível para consulta na pasta do edital.' },
];

function ChatPanel({ itemIdx, onToast }) {
  const [msgs, setMsgs] = React.useState([]);
  const [input, setInput] = React.useState('');
  const [showTemplates, setShowTemplates] = React.useState(false);
  const [alertSonoro, setAlertSonoro] = React.useState(true);
  const fileInputRef = React.useRef(null);
  const scrollRef = React.useRef(null);

  // Chat real do pregoeiro virá das plataformas (PNCP/Comprasnet) via integração.
  // Por enquanto, mensagens locais apenas (digitadas pela Mariana).

  React.useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [msgs.length]);

  const enviar = () => {
    if (!input.trim()) return;
    const tm = new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
    setMsgs([...msgs, { from: 'btm', t: input.trim(), tm }]);
    setInput('');
    onToast && onToast('Mensagem enviada ao pregoeiro');
  };

  const handleKey = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      enviar();
    }
  };

  const handleAnexar = (e) => {
    const file = e.target.files?.[0];
    if (!file) return;
    const tm = new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit', second: '2-digit' });
    setMsgs([...msgs, { from: 'btm', t: '', att: file.name, tm }]);
    onToast && onToast(`Anexo "${file.name}" enviado ao pregoeiro`);
    e.target.value = '';
  };

  const usarTemplate = (t) => {
    setInput(t.t);
    setShowTemplates(false);
  };

  return (
    <div className="card" style={{ display: 'flex', flexDirection: 'column', overflow: 'hidden', position: 'relative' }}>
      <div className="card-head">
        <Icon name="mail" />
        <div className="t">Chat do Pregoeiro · Item {String(itemIdx).padStart(2, '0')}</div>
        <span className="dot-pulse" style={{ width: 6, height: 6, marginLeft: 'auto' }}></span>
      </div>
      <div ref={scrollRef} style={{ flex: 1, overflowY: 'auto', padding: 10, display: 'flex', flexDirection: 'column', gap: 6 }}>
        {msgs.map((m, i) => <ChatMessage key={i} m={m} />)}
      </div>
      <div style={{ padding: 10, borderTop: '1px solid var(--line-1)', position: 'relative' }}>
        {showTemplates && (
          <div style={{ position: 'absolute', bottom: '100%', left: 10, right: 10, background: 'var(--bg-1)', border: '1px solid var(--line-2)', borderRadius: 6, marginBottom: 4, boxShadow: '0 -8px 24px rgba(0,0,0,0.4)', zIndex: 10 }}>
            <div style={{ padding: '8px 10px', borderBottom: '1px solid var(--line-1)', display: 'flex', alignItems: 'center' }}>
              <span style={{ fontSize: 11, fontFamily: 'IBM Plex Mono', color: 'var(--fg-3)' }}>TEMPLATES RÁPIDOS</span>
              <button className="btn btn-ghost btn-sm" style={{ marginLeft: 'auto' }} onClick={() => setShowTemplates(false)}><Icon name="x" size={10} /></button>
            </div>
            <div style={{ maxHeight: 220, overflowY: 'auto' }}>
              {TEMPLATES_CHAT.map((tp, i) => (
                <div key={i} className="clickable" onClick={() => usarTemplate(tp)} style={{ padding: '8px 10px', borderBottom: i < TEMPLATES_CHAT.length - 1 ? '1px solid var(--line-1)' : 'none', fontSize: 11.5 }}>
                  <div style={{ fontWeight: 600, color: 'var(--lime)', marginBottom: 2 }}>{tp.l}</div>
                  <div style={{ color: 'var(--fg-2)', fontSize: 11, fontStyle: 'italic' }}>"{tp.t}"</div>
                </div>
              ))}
            </div>
          </div>
        )}
        <textarea
          className="input"
          placeholder="Mensagem ao pregoeiro... (Enter envia, Shift+Enter quebra linha)"
          style={{ resize: 'none', minHeight: 56 }}
          value={input}
          onChange={e => setInput(e.target.value)}
          onKeyDown={handleKey}
        />
        <input type="file" ref={fileInputRef} style={{ display: 'none' }} onChange={handleAnexar} />
        <div className="flex items-center gap-2" style={{ marginTop: 6 }}>
          <button className="btn btn-ghost btn-sm" onClick={() => fileInputRef.current?.click()} title="Anexar arquivo"><Icon name="paperclip" size={11} /></button>
          <button className="btn btn-ghost btn-sm" onClick={() => setShowTemplates(v => !v)} style={{ fontSize: 10.5, color: 'var(--fg-3)' }}>
            <Icon name="bolt" size={11} /> Templates rápidos
          </button>
          <button className="btn btn-primary btn-sm" style={{ marginLeft: 'auto' }} onClick={enviar} disabled={!input.trim()}>Enviar</button>
        </div>
      </div>
      <div style={{ padding: '8px 12px', borderTop: '1px solid var(--line-1)', display: 'flex', alignItems: 'center', gap: 8, background: 'var(--bg-2)' }}>
        {alertSonoro && <span className="dot-pulse" style={{ width: 6, height: 6 }}></span>}
        <span style={{ fontSize: 11, color: 'var(--fg-2)' }}>Alerta sonoro · superação de lance e menções</span>
        <div className={`toggle${alertSonoro ? ' on' : ''}`} style={{ marginLeft: 'auto' }} onClick={() => setAlertSonoro(v => !v)}></div>
      </div>
    </div>
  );
}

function ChatMessage({ m }) {
  if (m.from === 'sys') {
    return (
      <div style={{ alignSelf: 'center', fontSize: 10.5, color: m.win ? 'var(--lime)' : 'var(--fg-3)', fontFamily: 'IBM Plex Mono', padding: '4px 10px', background: 'var(--bg-2)', borderRadius: 999 }}>
        {m.tm} · {m.t}
      </div>
    );
  }
  if (m.from === 'btm') {
    return (
      <div style={{ alignSelf: 'flex-end', maxWidth: '85%' }}>
        <div style={{ fontSize: 9.5, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono', textAlign: 'right', marginBottom: 2 }}>BTM · {m.tm}</div>
        <div style={{ background: 'var(--lime-soft)', border: '1px solid var(--lime-border)', padding: '6px 10px', borderRadius: 6, fontSize: 12, color: 'var(--lime)' }}>
          {m.t && <div>{m.t}</div>}
          {m.att && <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: m.t ? 4 : 0, padding: '4px 8px', background: 'var(--bg-2)', borderRadius: 4, color: 'var(--fg-1)' }}>
            <Icon name="paperclip" size={11} style={{ color: 'var(--cyan)' }} />
            <span style={{ fontFamily: 'IBM Plex Mono', fontSize: 11 }}>{m.att}</span>
          </div>}
        </div>
      </div>
    );
  }
  return (
    <div style={{ maxWidth: '90%' }}>
      <div style={{ fontSize: 9.5, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono', marginBottom: 2 }}>{m.name} · {m.tm}</div>
      <div style={{ background: m.mention ? 'rgba(245,181,68,0.08)' : 'var(--bg-2)', border: m.mention ? '1px solid rgba(245,181,68,0.3)' : '1px solid var(--line-1)', padding: '6px 10px', borderRadius: 6, fontSize: 12 }}>{m.t}</div>
    </div>
  );
}

/* ── FORNECEDOR DRAWER ─────────────────────────────────────── */
function FornecedorDrawer({ fornecedor, onClose }) {
  const [tab, setTab] = React.useState('perfil');
  const p = CONCORRENTES_PERFIL[fornecedor];
  if (!p) return null;

  const winRate = ((p.confrontosBTM.ganhei / p.confrontosBTM.total) * 100).toFixed(0);

  return (
    <Drawer
      open={true}
      onClose={onClose}
      eyebrow={<><span>Perfil de concorrente</span><span className="chip">M04</span><span className={`badge ${p.perfil === 'agressivo' ? 'badge-red' : p.perfil === 'oportunista' ? 'badge-amber' : p.perfil === 'conservador' ? 'badge-cyan' : ''}`}>{p.perfil.toUpperCase()}</span></>}
      title={<span style={{ fontWeight: 600 }}>{fornecedor}</span>}
      subtitle={`${p.cnpj} · ${p.cidade}/${p.uf} · ${p.porte}`}
      headRight={
        <div style={{ textAlign: 'right' }}>
          <div className="mono" style={{ fontSize: 10.5, color: 'var(--fg-3)' }}>VS BTM (12m)</div>
          <div className="mono" style={{ fontSize: 14, fontWeight: 600, color: winRate >= 60 ? 'var(--lime)' : winRate >= 40 ? 'var(--amber)' : 'var(--red)' }}>{winRate}% vitória</div>
        </div>
      }
      tabs={[
        { id: 'perfil', label: 'Perfil' },
        { id: 'hist', label: 'Histórico', count: p.historico.length },
        { id: 'comp', label: 'Comportamento' },
      ]}
      activeTab={tab}
      onTabChange={setTab}
      footer={
        <>
          <button className="btn"><Icon name="mail" /> Anotar inteligência</button>
          <button className="btn"><Icon name="eye" /> Ver no PNCP</button>
          <button className="btn btn-primary" style={{ flex: 1, justifyContent: 'center' }}>
            <Icon name="bolt" /> Acompanhar este fornecedor
          </button>
        </>
      }
    >
      {tab === 'perfil' && (
        <div style={{ padding: 18 }}>
          <div className="grid-4" style={{ marginBottom: 22 }}>
            <PerfilStat label="DISPUTAS (30D)" value={p.disputas30d} />
            <PerfilStat label="VITÓRIAS (30D)" value={p.vitorias30d} cls="lime" />
            <PerfilStat label="HIT RATE" value={p.hitRate + '%'} cls={p.hitRate >= 40 ? 'lime' : p.hitRate >= 30 ? 'amber' : 'red'} />
            <PerfilStat label="MARKET SHARE" value={p.marketShare + '%'} sub="categoria papelaria" />
          </div>

          <div className="field-label" style={{ marginBottom: 8 }}>CONFRONTOS DIRETOS COM BTM (12 MESES)</div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 10, marginBottom: 22 }}>
            <PerfilStat label="TOTAL" value={p.confrontosBTM.total} />
            <PerfilStat label="BTM GANHOU" value={p.confrontosBTM.ganhei} cls="lime" />
            <PerfilStat label="BTM PERDEU" value={p.confrontosBTM.perdi} cls={p.confrontosBTM.perdi > 0 ? 'red' : ''} />
          </div>

          <div className="field-label" style={{ marginBottom: 8 }}>CATEGORIAS DE ATUAÇÃO</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 22 }}>
            {p.categorias.map(c => <div key={c} className="filter-chip active">{c}</div>)}
          </div>

          <div className="field-label" style={{ marginBottom: 8 }}>ÚLTIMA VITÓRIA</div>
          <div style={{ padding: 12, background: 'var(--bg-2)', border: '1px solid var(--line-1)', borderRadius: 6, fontSize: 12.5 }}>{p.ultVitoria}</div>
        </div>
      )}

      {tab === 'hist' && (
        <table className="tbl">
          <thead>
            <tr>
              <th>Data</th>
              <th>Edital</th>
              <th>Vencedor</th>
              <th style={{ textAlign: 'right' }}>Valor</th>
            </tr>
          </thead>
          <tbody>
            {p.historico.map((h, i) => {
              const isBtm = h.vencedor === 'BTM';
              return (
                <tr key={i}>
                  <td className="mono" style={{ fontSize: 11.5 }}>{h.dt}</td>
                  <td className="id-col" style={{ color: 'var(--fg-1)' }}>{h.edital}</td>
                  <td>
                    <span className={`badge ${isBtm ? 'badge-lime' : 'badge-red'}`}>
                      {isBtm ? '✓ BTM' : '✕ ' + h.vencedor}
                    </span>
                  </td>
                  <td className="num-col" style={{ color: 'var(--lime)' }}>{BRL(h.valor)}</td>
                </tr>
              );
            })}
          </tbody>
        </table>
      )}

      {tab === 'comp' && (
        <div style={{ padding: 18 }}>
          <div className="field-label" style={{ marginBottom: 10 }}>PADRÕES OBSERVADOS</div>
          <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
            {p.comportamento.map((c, i) => (
              <div key={i} className="alert-banner alert-cyan">
                <Icon name="info" size={13} />
                {c}
              </div>
            ))}
          </div>
          <div className="alert-banner alert-amber" style={{ marginTop: 16 }}>
            <Icon name="warn" size={13} />
            <div>
              <strong>Inteligência de disputa</strong>
              <div style={{ fontSize: 11.5, color: 'var(--fg-2)', marginTop: 2 }}>
                Padrões aprendidos pela análise histórica. Use como referência, não como certeza — fornecedores mudam estratégia.
              </div>
            </div>
          </div>
        </div>
      )}
    </Drawer>
  );
}

function PerfilStat({ label, value, sub, cls }) {
  const color = cls === 'lime' ? 'var(--lime)' : cls === 'amber' ? 'var(--amber)' : cls === 'red' ? 'var(--red)' : 'var(--fg-0)';
  return (
    <div style={{ padding: 12, background: 'var(--bg-2)', border: '1px solid var(--line-1)', borderRadius: 6 }}>
      <div className="field-label">{label}</div>
      <div className="mono" style={{ fontSize: 22, fontWeight: 600, color, marginTop: 4, lineHeight: 1 }}>{value}</div>
      {sub && <div style={{ fontSize: 10.5, color: 'var(--fg-3)', marginTop: 4 }}>{sub}</div>}
    </div>
  );
}

/* ── ADD DISPUTA MODAL ─────────────────────────────────────── */
function AddDisputaModal({ onClose, editais = [], disputasEditalIds, onPickElegivel, onSubmitManual }) {
  const [aba, setAba] = React.useState('elegiveis');
  const [manualForm, setManualForm] = React.useState({
    id: 'PE-' + String(Math.floor(Math.random() * 900) + 100) + '/2026',
    orgao: '',
    plataforma: 'PNCP',
    uf: 'RJ',
    abertura: '',
  });
  const [erro, setErro] = React.useState(null);
  const [submitting, setSubmitting] = React.useState(false);

  const elegiveis = React.useMemo(() => {
    const ids = disputasEditalIds || new Set();
    return editais
      .filter(e => ['novo', 'analise', 'precificacao'].includes(e.status))
      .filter(e => !ids.has(e.id))
      .sort((a, b) => new Date(a.abertura || 0) - new Date(b.abertura || 0));
  }, [editais, disputasEditalIds]);

  const setM = (k, v) => setManualForm({ ...manualForm, [k]: v });

  const pickElegivel = async (editalId) => {
    if (submitting) return;
    setSubmitting(true);
    try { await onPickElegivel(editalId); } finally { setSubmitting(false); }
  };

  const submitManual = async () => {
    if (submitting) return;
    if (!manualForm.orgao || !manualForm.abertura) {
      setErro('Preencha Órgão e Data/hora de abertura');
      return;
    }
    setErro(null);
    setSubmitting(true);
    try { await onSubmitManual(manualForm); } finally { setSubmitting(false); }
  };

  return (
    <div style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,0.7)', display: 'grid', placeItems: 'center', zIndex: 200, backdropFilter: 'blur(2px)' }} onClick={onClose}>
      <div style={{ background: 'var(--bg-1)', border: '1px solid var(--line-2)', borderRadius: 10, width: 640, maxHeight: '85vh', overflow: 'auto' }} onClick={e => e.stopPropagation()}>
        <div className="card-head">
          <Icon name="plus" />
          <div className="t">Adicionar disputa ativa</div>
          <div className="s">monitorar nova licitação em tempo real</div>
          <button className="tb-btn" style={{ marginLeft: 'auto' }} onClick={onClose}><Icon name="x" /></button>
        </div>

        <div className="tabs" style={{ padding: '0 14px' }}>
          <div className={`tab${aba === 'elegiveis' ? ' active' : ''}`} onClick={() => setAba('elegiveis')}>
            Editais elegíveis <span className="count">{elegiveis.length}</span>
          </div>
          <div className={`tab${aba === 'manual' ? ' active' : ''}`} onClick={() => setAba('manual')}>
            Cadastrar manualmente
          </div>
        </div>

        {aba === 'elegiveis' && (
          <div style={{ padding: 18 }}>
            <div className="alert-banner alert-cyan" style={{ marginBottom: 14 }}>
              <Icon name="info" size={13} />
              <div>
                <strong>Editais prontos para entrar em disputa</strong>
                <div style={{ fontSize: 11.5, color: 'var(--fg-2)', marginTop: 2 }}>
                  Lista de editais nos status <span style={{ color: 'var(--lime)' }}>NOVO</span>, <span style={{ color: 'var(--cyan)' }}>ANÁLISE</span> ou <span style={{ color: 'var(--amber)' }}>PRECIFICAÇÃO</span> que ainda não estão em disputa ativa.
                </div>
              </div>
            </div>

            {elegiveis.length === 0 ? (
              <div style={{ padding: 32, textAlign: 'center', color: 'var(--fg-3)' }}>
                Nenhum edital elegível no momento. Cadastre um edital em <strong>M01 Prospecção</strong> ou use a aba <strong>Cadastrar manualmente</strong>.
              </div>
            ) : (
              <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
                {elegiveis.map(e => (
                  <div key={e.id} className="clickable" onClick={() => pickElegivel(e.id)} style={{ padding: 12, background: 'var(--bg-2)', border: '1px solid var(--line-1)', borderRadius: 6, display: 'grid', gridTemplateColumns: '1fr auto', gap: 12, alignItems: 'center', opacity: submitting ? 0.6 : 1, pointerEvents: submitting ? 'none' : 'auto' }}>
                    <div>
                      <div className="mono" style={{ fontSize: 13, fontWeight: 600, color: 'var(--fg-0)' }}>{e.numero} · {e.orgao}</div>
                      <div style={{ fontSize: 11, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono', marginTop: 2 }}>{e.plataforma} · {e.uf} · {e.itens} itens · abertura {e.abertura ? new Date(e.abertura).toLocaleString('pt-BR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' }) : '—'}</div>
                    </div>
                    <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end', gap: 4 }}>
                      <span className="mono" style={{ fontSize: 12, color: 'var(--lime)', fontWeight: 600 }}>{BRL(e.valor)}</span>
                      <span className="badge">{(e.status || '').toUpperCase()}</span>
                    </div>
                  </div>
                ))}
              </div>
            )}
          </div>
        )}

        {aba === 'manual' && (
          <div style={{ padding: 18, display: 'flex', flexDirection: 'column', gap: 14 }}>
            <div className="alert-banner alert-amber">
              <Icon name="warn" size={13} />
              <div>
                <strong>Use apenas em casos excepcionais</strong>
                <div style={{ fontSize: 11.5, color: 'var(--fg-2)', marginTop: 2 }}>
                  O fluxo padrão é capturar o edital via M01 Prospecção e seguir até disputa. Use esta opção apenas se a sessão já está aberta e o edital não está no sistema.
                </div>
              </div>
            </div>

            <div className="grid-2">
              <div>
                <div className="field-label">NÚMERO DO EDITAL <span style={{ color: 'var(--red)' }}>*</span></div>
                <input className="input mono" value={manualForm.id} onChange={e => setM('id', e.target.value)} />
              </div>
              <div>
                <div className="field-label">PLATAFORMA</div>
                <select className="input" value={manualForm.plataforma} onChange={e => setM('plataforma', e.target.value)}>
                  <option>PNCP</option>
                  <option>Comprasnet</option>
                  <option>LICITANET</option>
                  <option>AMMLICITA</option>
                  <option>LICITAR</option>
                  <option>BLL</option>
                </select>
              </div>
            </div>

            <div>
              <div className="field-label">ÓRGÃO <span style={{ color: 'var(--red)' }}>*</span></div>
              <input className="input" value={manualForm.orgao} onChange={e => setM('orgao', e.target.value)} placeholder="Ex: SEFAZ-RJ" />
            </div>

            <div className="grid-2">
              <div>
                <div className="field-label">UF</div>
                <select className="input" value={manualForm.uf} onChange={e => setM('uf', e.target.value)}>
                  {['AC', 'AL', 'AM', 'AP', 'BA', 'CE', 'DF', 'ES', 'GO', 'MA', 'MG', 'MS', 'MT', 'PA', 'PB', 'PE', 'PI', 'PR', 'RJ', 'RN', 'RO', 'RR', 'RS', 'SC', 'SE', 'SP', 'TO'].map(uf => <option key={uf}>{uf}</option>)}
                </select>
              </div>
              <div>
                <div className="field-label">DATA/HORA DA SESSÃO <span style={{ color: 'var(--red)' }}>*</span></div>
                <input className="input mono" type="datetime-local" value={manualForm.abertura} onChange={e => setM('abertura', e.target.value)} />
              </div>
            </div>

            {erro && <div className="alert-banner alert-red"><Icon name="warn" size={13} /> {erro}</div>}
          </div>
        )}

        <div style={{ padding: 14, borderTop: '1px solid var(--line-1)', display: 'flex', justifyContent: 'flex-end', gap: 8 }}>
          <button className="btn" onClick={onClose} disabled={submitting}>Cancelar</button>
          {aba === 'manual' && <button className="btn btn-primary" onClick={submitManual} disabled={submitting}>
            {submitting ? <><span className="spinner" style={{ marginRight: 6 }}></span> Cadastrando...</> : <><Icon name="check" /> Cadastrar e ativar disputa</>}
          </button>}
        </div>
      </div>
    </div>
  );
}

window.MDisputa = MDisputa;
