/* global React, Icon, Sparkline, Section, BRL, Ticker, KANBAN_LIC */
const { useState: uS, useEffect: uE, useMemo: uM, useRef: uR } = React;

function MDashboard({ onNav }) {
  const [now, setNow] = uS(new Date());
  const [stats, setStats] = uS(null);
  const [loading, setLoading] = uS(true);

  uE(() => { const i = setInterval(() => setNow(new Date()), 1000); return () => clearInterval(i); }, []);

  uE(() => {
    let mounted = true;
    window.dataApi.getDashboardStats()
      .then(s => { if (mounted) { setStats(s); setLoading(false); } })
      .catch(() => { if (mounted) setLoading(false); });
    return () => { mounted = false; };
  }, []);

  const hour = now.getHours();
  const greeting = hour < 12 ? 'Bom dia' : hour < 18 ? 'Boa tarde' : 'Boa noite';
  const tt = String(now.getHours()).padStart(2, '0') + ':' + String(now.getMinutes()).padStart(2, '0') + ':' + String(now.getSeconds()).padStart(2, '0');

  // Métricas derivadas (memoizadas)
  const derived = uM(() => {
    const editais = stats?.editais || [];
    const todayStr = new Date().toISOString().slice(0, 10);
    const futuros = editais.filter(e => new Date(e.abertura) > now).sort((a, b) => new Date(a.abertura) - new Date(b.abertura));
    const proximo = futuros[0] || null;
    const aderentes24h = editais.filter(e => {
      const created = new Date(e.created_at);
      return (now - created) / 1000 / 3600 < 36;
    }).length;
    const pregoesHoje = editais.filter(e => new Date(e.abertura).toISOString().slice(0, 10) === todayStr).length;
    const ativos = editais.filter(e => !['descartado', 'ganho'].includes(e.status)).length;
    const emDisputaHoje = editais.filter(e => e.status === 'disputa' && new Date(e.abertura).toISOString().slice(0, 10) === todayStr).length;
    const carteira = editais.filter(e => e.status === 'ganho').reduce((s, e) => s + (parseFloat(e.valor) || 0), 0);
    return { editais, proximo, aderentes24h, pregoesHoje, ativos, emDisputaHoje, carteira };
  }, [stats, now]);

  // Countdown ao próximo pregão real
  const proxAbertura = derived.proximo ? new Date(derived.proximo.abertura) : null;
  const diff = proxAbertura ? Math.max(0, Math.floor((proxAbertura - now) / 1000)) : 0;
  const ch = String(Math.floor(diff / 3600)).padStart(2, '0');
  const cm = String(Math.floor((diff % 3600) / 60)).padStart(2, '0');
  const cs = String(diff % 60).padStart(2, '0');

  return (
    <>
      <Ticker />
      <div className="page">
        {/* HERO */}
        <div className="card" style={{ marginBottom: 14, padding: 0, overflow: 'hidden', background: 'linear-gradient(135deg, rgba(212,247,82,0.06) 0%, var(--bg-1) 60%)' }}>
          <div style={{ padding: '18px 22px', display: 'grid', gridTemplateColumns: '1.4fr 1fr 1fr 1fr', gap: 28, alignItems: 'center' }}>
            <div>
              <div className="eyebrow">
                <span>Painel · {now.toLocaleDateString('pt-BR', { day: '2-digit', month: 'short', year: 'numeric' }).replace('.', '')}</span>
                <span className="chip">M00</span>
                <span className="mono" style={{ color: 'var(--lime)' }}>● AO VIVO {tt}</span>
              </div>
              <h1 className="page-title" style={{ marginTop: 8, marginBottom: 4 }}>{greeting}, {(stats && stats.editais.length === 0) ? 'pronto pra começar' : ((window.sglUser?.displayName || '').split(' ')[0] || 'tudo certo')}.</h1>
              <p className="page-sub" style={{ margin: 0 }}>
                {loading ? 'Carregando dados...' : (
                  <>
                    <span style={{ color: 'var(--lime)' }}>{derived.aderentes24h} {derived.aderentes24h === 1 ? 'edital' : 'editais'}</span> {derived.aderentes24h === 1 ? 'adicionado' : 'adicionados'} nas últimas 36h · <span style={{ color: 'var(--amber)' }}>{derived.pregoesHoje} {derived.pregoesHoje === 1 ? 'pregão hoje' : 'pregões hoje'}</span>
                  </>
                )}
              </p>
            </div>
            {derived.proximo ? (
              <CountdownBlock
                label="PRÓX. PREGÃO"
                h={ch} m={cm} s={cs}
                sub={`${derived.proximo.numero} ${derived.proximo.orgao} · ${BRL(derived.proximo.valor)}`}
                onClick={() => onNav('disputa')}
              />
            ) : (
              <div style={{ borderLeft: '1px solid var(--line-1)', paddingLeft: 20 }}>
                <div className="field-label">PRÓX. PREGÃO</div>
                <div className="mono" style={{ fontSize: 18, color: 'var(--fg-3)', marginTop: 6 }}>—</div>
                <div className="mono" style={{ fontSize: 10.5, color: 'var(--fg-3)', marginTop: 4 }}>Nenhum pregão agendado</div>
              </div>
            )}
            <PlaceholderStat label="HIT RATE 30D" note="Aguarda hist. de disputas" onClick={() => onNav('auditoria')} />
            <PlaceholderStat label="LUCRO MTD" note="Aguarda M07 Financeiro" onClick={() => onNav('financeiro')} />
          </div>
        </div>

        {/* KPI ROW */}
        <div className="grid-4" style={{ marginBottom: 14 }}>
          <KpiCard label="EDITAIS ATIVOS" value={loading ? '...' : String(derived.ativos).padStart(2, '0')} delta="status ≠ ganho/descartado" deltaCls="up" trend={[derived.ativos]} onClick={() => onNav('prospeccao')} />
          <KpiCard label="EM DISPUTA · HOJE" value={loading ? '...' : String(derived.emDisputaHoje).padStart(2, '0')} delta="abertura hoje" deltaCls="amber" trend={[derived.emDisputaHoje]} color="cyan" onClick={() => onNav('disputa')} />
          <KpiCard label="MARGEM MÉDIA 30D" value="—" delta="Aguarda M03 Precificação" deltaCls="" trend={[0]} onClick={() => onNav('precificacao')} placeholder />
          <KpiCard label="VALOR EM CARTEIRA" value={loading ? '...' : BRL(derived.carteira)} delta="soma editais ganhos" trend={[derived.carteira]} onClick={() => onNav('financeiro')} />
        </div>

        {/* MAIN GRID — Disputa AO VIVO + Revenue + AI */}
        <div style={{ display: 'grid', gridTemplateColumns: '1.2fr 1fr 360px', gap: 14, marginBottom: 14 }}>
          <LiveDisputaCard onNav={onNav} />
          <RevenueChart onNav={onNav} />
          <AiInsightsCard onNav={onNav} />
        </div>

        {/* SECOND ROW — Agenda + Pipeline funnel + Top performers */}
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 14, marginBottom: 14 }}>
          <AgendaCard onNav={onNav} editais={derived.editais} />
          <PipelineFunnel onNav={onNav} editais={derived.editais} />
          <TopPerformersCard onNav={onNav} editais={derived.editais} fornecedores={stats?.fornecedores || []} produtos={stats?.produtos || []} />
        </div>

        {/* THIRD ROW — Heatmap BR + Margem por categoria + Certidões */}
        <div style={{ display: 'grid', gridTemplateColumns: '1.3fr 1fr 1fr', gap: 14, marginBottom: 14 }}>
          <BrasilHeatmap onNav={onNav} editais={derived.editais} />
          <MargemCategoria onNav={onNav} />
          <CertidoesCard onNav={onNav} />
        </div>

        {/* KANBAN */}
        <Section title="Pipeline de Licitações" sub="KANBAN · 6 STATUS" padTop={8}
          right={<button className="btn btn-ghost btn-sm" onClick={() => onNav('prospeccao')}>Abrir módulo <Icon name="arrowR" size={11} /></button>}>
          <KanbanLicitacao onNav={onNav} editais={derived.editais} />
        </Section>
      </div>
    </>
  );
}

/* ─────────────────────────────────────────────────────────── */
function AnimNum({ to }) {
  const [v, setV] = uS(0);
  uE(() => {
    let start = 0; const dur = 800; const t0 = performance.now();
    const tick = (t) => { const k = Math.min(1, (t - t0) / dur); setV(Math.round(start + (to - start) * (1 - Math.pow(1 - k, 3)))); if (k < 1) requestAnimationFrame(tick); };
    requestAnimationFrame(tick);
  }, [to]);
  return <span>{String(v).padStart(2, '0')}</span>;
}

function CountdownBlock({ label, h, m, s, sub, onClick }) {
  return (
    <div className={onClick ? 'clickable' : ''} role={onClick ? 'button' : undefined} tabIndex={onClick ? 0 : undefined} onClick={onClick} onKeyDown={onClick ? (e => (e.key === 'Enter' || e.key === ' ') && onClick()) : undefined} style={{ borderLeft: '1px solid var(--line-1)', paddingLeft: 20, borderRadius: 4 }}>
      <div className="field-label">{label}</div>
      <div className="mono" style={{ fontSize: 26, fontWeight: 600, color: 'var(--lime)', lineHeight: 1.1, letterSpacing: '-0.02em', marginTop: 4 }}>{h}:{m}:<span style={{ color: 'var(--lime-2)' }}>{s}</span></div>
      <div className="mono" style={{ fontSize: 10.5, color: 'var(--fg-3)', marginTop: 4 }}>{sub}</div>
    </div>
  );
}
function MiniStat({ label, v, sub, sk, cls, onClick }) {
  return (
    <div className={onClick ? 'clickable' : ''} role={onClick ? 'button' : undefined} tabIndex={onClick ? 0 : undefined} onClick={onClick} onKeyDown={onClick ? (e => (e.key === 'Enter' || e.key === ' ') && onClick()) : undefined} style={{ borderLeft: '1px solid var(--line-1)', paddingLeft: 20, borderRadius: 4 }}>
      <div className="field-label">{label}</div>
      <div className="mono" style={{ fontSize: 24, fontWeight: 600, color: cls === 'lime' ? 'var(--lime)' : 'var(--fg-0)', lineHeight: 1.1, marginTop: 4 }}>{v}</div>
      <div style={{ marginTop: 4 }}><Sparkline data={sk} color={cls === 'lime' ? 'lime' : 'cyan'} /></div>
      <div className="mono" style={{ fontSize: 10, color: 'var(--fg-3)', marginTop: 2 }}>{sub}</div>
    </div>
  );
}
function KpiCard({ label, value, delta, deltaCls, trend, color = 'lime', onClick, placeholder }) {
  return (
    <div className={`card${onClick ? ' clickable' : ''}`} role={onClick ? 'button' : undefined} tabIndex={onClick ? 0 : undefined} onClick={onClick} onKeyDown={onClick ? (e => (e.key === 'Enter' || e.key === ' ') && onClick()) : undefined} style={placeholder ? { opacity: 0.55 } : undefined}>
      <div className="card-body" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start' }}>
        <div>
          <div className="kpi">
            <div className="label">{label}</div>
            <div className="value">{value}</div>
            <div className="delta" style={{ color: deltaCls === 'amber' ? 'var(--amber)' : deltaCls === 'up' ? 'var(--lime)' : 'var(--fg-2)' }}>{deltaCls === 'up' && '↑'} {delta}</div>
          </div>
        </div>
        {!placeholder && trend && trend.length > 1 && <Sparkline data={trend} color={color} />}
      </div>
    </div>
  );
}

function PlaceholderStat({ label, note, onClick }) {
  return (
    <div className={onClick ? 'clickable' : ''} role={onClick ? 'button' : undefined} tabIndex={onClick ? 0 : undefined} onClick={onClick} onKeyDown={onClick ? (e => (e.key === 'Enter' || e.key === ' ') && onClick()) : undefined} style={{ borderLeft: '1px solid var(--line-1)', paddingLeft: 20, borderRadius: 4, opacity: 0.55 }}>
      <div className="field-label">{label}</div>
      <div className="mono" style={{ fontSize: 22, fontWeight: 600, color: 'var(--fg-3)', lineHeight: 1.1, marginTop: 4 }}>—</div>
      <div className="mono" style={{ fontSize: 10, color: 'var(--fg-3)', marginTop: 6 }}>{note}</div>
    </div>
  );
}

/* ── LIVE DISPUTA (placeholder até ter disputa ativa) ─────── */
function LiveDisputaCard({ onNav }) {
  return (
    <div className="card clickable" role="button" tabIndex={0} onClick={() => onNav('disputa')} onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onNav('disputa')}>
      <div className="card-head">
        <Icon name="zap" />
        <div className="t">Disputa ao vivo</div>
        <span className="badge" style={{ marginLeft: 'auto', background: 'var(--bg-3)', color: 'var(--fg-3)' }}>nenhuma ativa</span>
      </div>
      <div style={{ padding: 28, textAlign: 'center' }}>
        <Icon name="zap" size={28} style={{ color: 'var(--fg-3)', marginBottom: 12 }} />
        <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 4 }}>Nenhuma disputa ativa no momento</div>
        <div style={{ fontSize: 11.5, color: 'var(--fg-3)', marginBottom: 16 }}>Abra o M04 para iniciar uma disputa a partir de um edital elegível.</div>
        <button className="btn btn-sm" onClick={e => { e.stopPropagation(); onNav('disputa'); }}><Icon name="arrowR" size={11} /> Ir para M04</button>
      </div>
    </div>
  );
}

/* ── REVENUE CHART (placeholder até M07 ter série temporal) ── */
function RevenueChart({ onNav }) {
  return (
    <div className="card clickable" role="button" tabIndex={0} onClick={() => onNav('financeiro')} onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onNav('financeiro')}>
      <div className="card-head">
        <Icon name="chart" />
        <div className="t">Receita × Custo</div>
        <span className="badge" style={{ marginLeft: 'auto', background: 'var(--bg-3)', color: 'var(--fg-3)' }}>aguarda hist. M07</span>
      </div>
      <div style={{ padding: 28, textAlign: 'center' }}>
        <Icon name="chart" size={28} style={{ color: 'var(--fg-3)', marginBottom: 12 }} />
        <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 4 }}>Histórico não disponível</div>
        <div style={{ fontSize: 11.5, color: 'var(--fg-3)', marginBottom: 16 }}>O gráfico será gerado conforme as NFs forem emitidas e os títulos liquidados.</div>
        <button className="btn btn-sm" onClick={e => { e.stopPropagation(); onNav('financeiro'); }}><Icon name="arrowR" size={11} /> Abrir M07</button>
      </div>
    </div>
  );
}

/* ── AI INSIGHTS (placeholder até OpenAI estar integrado) ──── */
function AiInsightsCard({ onNav }) {
  return (
    <div className="card clickable" role="button" tabIndex={0} onClick={() => onNav('ia')} onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onNav('ia')}>
      <div className="card-head">
        <Icon name="cpu" />
        <div className="t">IA · Diagnóstico do dia</div>
        <span className="badge" style={{ marginLeft: 'auto', background: 'var(--bg-3)', color: 'var(--fg-3)' }}>aguarda OpenAI</span>
      </div>
      <div style={{ padding: 28, textAlign: 'center' }}>
        <Icon name="cpu" size={28} style={{ color: 'var(--fg-3)', marginBottom: 12 }} />
        <div style={{ fontSize: 13, fontWeight: 500, marginBottom: 4 }}>IA ainda não conectada</div>
        <div style={{ fontSize: 11.5, color: 'var(--fg-3)', marginBottom: 16 }}>Configure a OpenAI em M13 para receber diagnósticos automáticos diários.</div>
        <button className="btn btn-sm" onClick={e => { e.stopPropagation(); onNav('config'); }}><Icon name="settings" size={11} /> M13 Configurações</button>
      </div>
    </div>
  );
}
function AICard({ tone, title, body, onClick }) {
  const cols = { red: 'var(--red)', amber: 'var(--amber)', cyan: 'var(--cyan)', lime: 'var(--lime)' };
  const bgs = { red: 'rgba(255,93,93,0.06)', amber: 'rgba(255,176,32,0.06)', cyan: 'rgba(106,215,229,0.06)', lime: 'rgba(212,247,82,0.06)' };
  return (
    <div className={onClick ? 'clickable' : ''} role={onClick ? 'button' : undefined} tabIndex={onClick ? 0 : undefined} onClick={onClick ? (e => { e.stopPropagation(); onClick(); }) : undefined} onKeyDown={onClick ? (e => (e.key === 'Enter' || e.key === ' ') && (e.stopPropagation(), onClick())) : undefined} style={{ background: bgs[tone], border: `1px solid ${cols[tone]}33`, borderLeft: `2px solid ${cols[tone]}`, padding: '8px 10px', borderRadius: 4 }}>
      <div style={{ fontSize: 11.5, fontWeight: 600, color: cols[tone] }}>{title}</div>
      <div style={{ fontSize: 11, color: 'var(--fg-2)', lineHeight: 1.4, marginTop: 2 }}>{body}</div>
    </div>
  );
}

/* ── AGENDA ──────────────────────────────────────────────── */
function AgendaCard({ onNav, editais }) {
  const todayStr = new Date().toISOString().slice(0, 10);
  const now = new Date();
  const items = (editais || [])
    .filter(e => new Date(e.abertura).toISOString().slice(0, 10) === todayStr)
    .sort((a, b) => new Date(a.abertura) - new Date(b.abertura))
    .map(e => {
      const ab = new Date(e.abertura);
      const h = String(ab.getHours()).padStart(2, '0') + ':' + String(ab.getMinutes()).padStart(2, '0');
      const done = ab < now;
      const hot = (ab - now) / 1000 / 60 < 60 && (ab - now) > 0;
      const toneByStatus = { novo: 'cyan', analise: 'cyan', precificacao: 'amber', disputa: 'red', ganho: 'lime', descartado: 'fg' };
      return { h, t: e.numero, s: `${e.orgao} · ${BRL(e.valor)}`, tone: toneByStatus[e.status] || 'fg', done, hot };
    });
  const todayLabel = now.toLocaleDateString('pt-BR', { day: '2-digit', month: '2-digit' });
  return (
    <div className="card">
      <div className="card-head"><Icon name="cal" /><div className="t">Agenda · hoje {todayLabel}</div><span className="mono" style={{ marginLeft: 'auto', fontSize: 10.5, color: 'var(--fg-3)' }}>{items.length} {items.length === 1 ? 'EVENTO' : 'EVENTOS'}</span></div>
      <div style={{ padding: '4px 0' }}>
        {items.length === 0 && (
          <div style={{ padding: 24, textAlign: 'center', color: 'var(--fg-3)', fontSize: 11.5 }}>
            Nenhum pregão agendado para hoje.
          </div>
        )}
        {items.map((it, i) => {
          const cols = { cyan: 'var(--cyan)', amber: 'var(--amber)', red: 'var(--red)', lime: 'var(--lime)', fg: 'var(--fg-3)' };
          return (
            <div key={i} onClick={() => onNav('prospeccao')} style={{ display: 'grid', gridTemplateColumns: '54px 1fr 16px', gap: 8, padding: '10px 14px', borderBottom: i < items.length - 1 ? '1px solid var(--line-1)' : 'none', alignItems: 'center', cursor: 'pointer', opacity: it.done ? 0.4 : 1 }}>
              <span className="mono" style={{ fontSize: 11, color: cols[it.tone], fontWeight: 600 }}>{it.h}</span>
              <div>
                <div className="flex items-center gap-2">
                  <span style={{ fontSize: 12, fontWeight: 500, color: 'var(--fg-0)', textDecoration: it.done ? 'line-through' : 'none' }}>{it.t}</span>
                  {it.hot && <span className="dot-pulse red" style={{ width: 5, height: 5 }}></span>}
                </div>
                <div style={{ fontSize: 10.5, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono' }}>{it.s}</div>
              </div>
              <Icon name="chevR" size={11} style={{ color: 'var(--fg-3)' }} />
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ── PIPELINE FUNNEL ─────────────────────────────────────── */
function PipelineFunnel({ onNav, editais }) {
  const list = editais || [];
  const stages = [
    { n: 'Prospec.', v: list.filter(e => e.status === 'novo').length, c: 'var(--fg-2)', mod: 'prospeccao' },
    { n: 'Análise', v: list.filter(e => e.status === 'analise').length, c: 'var(--cyan)', mod: 'ocr' },
    { n: 'Precific.', v: list.filter(e => e.status === 'precificacao').length, c: 'var(--lime-2)', mod: 'precificacao' },
    { n: 'Disputa', v: list.filter(e => e.status === 'disputa').length, c: 'var(--lime)', mod: 'disputa' },
    { n: 'Vitória', v: list.filter(e => e.status === 'ganho').length, c: 'var(--lime)', mod: 'empenhos' },
    { n: 'Empenho', v: 0, c: 'var(--fg-3)', mod: 'empenhos' },
  ];
  const max = Math.max(...stages.map(s => s.v), 1);
  const total = list.length;
  const conv = total > 0 ? ((stages[4].v / total) * 100).toFixed(1) : '0.0';
  return (
    <div className="card">
      <div className="card-head"><Icon name="filter" /><div className="t">Funil · editais por status</div><span className="mono" style={{ marginLeft: 'auto', fontSize: 10.5, color: 'var(--lime)' }}>{conv}% VITÓRIA</span></div>
      <div style={{ padding: 16 }}>
        {stages.map((s, i) => {
          const w = (s.v / max) * 100;
          return (
            <div key={s.n} className="clickable" role="button" tabIndex={0} onClick={() => onNav(s.mod)} onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onNav(s.mod)} style={{ marginBottom: 8, padding: '2px 4px', borderRadius: 4 }}>
              <div className="flex items-center" style={{ justifyContent: 'space-between', marginBottom: 4 }}>
                <span style={{ fontSize: 11, color: 'var(--fg-2)', fontFamily: 'IBM Plex Mono' }}>{s.n}</span>
                <span className="mono" style={{ fontSize: 11, fontWeight: 600, color: s.c }}>{s.v}</span>
              </div>
              <div style={{ height: 18, background: 'var(--bg-2)', borderRadius: 2, overflow: 'hidden', position: 'relative' }}>
                <div style={{ width: w + '%', height: '100%', background: s.c, opacity: 0.85, transition: 'width 1s ease-out' }}></div>
                {i > 0 && <span style={{ position: 'absolute', right: 6, top: 2, fontSize: 9.5, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono' }}>{((s.v / stages[i - 1].v) * 100).toFixed(0)}%</span>}
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ── TOP PERFORMERS ──────────────────────────────────────── */
function TopPerformersCard({ onNav, editais, fornecedores, produtos }) {
  const [tab, setTab] = uS('clientes');

  const clientes = uM(() => {
    const map = {};
    (editais || []).forEach(e => {
      if (!map[e.orgao]) map[e.orgao] = { n: e.orgao, v: 0, q: 0 };
      map[e.orgao].v += parseFloat(e.valor) || 0;
      map[e.orgao].q += 1;
    });
    return Object.values(map).sort((a, b) => b.v - a.v).slice(0, 5);
  }, [editais]);

  const fornec = uM(() => {
    // ranking por número de produtos associados (proxy de relacionamento)
    const map = {};
    (produtos || []).forEach(p => {
      if (!p.fornecedor_id) return;
      if (!map[p.fornecedor_id]) {
        const f = (fornecedores || []).find(x => x.id === p.fornecedor_id);
        map[p.fornecedor_id] = { n: f?.nome || '—', v: 0, q: 0 };
      }
      map[p.fornecedor_id].v += (p.custo || 0) * (p.st || 0);
      map[p.fornecedor_id].q += 1;
    });
    return Object.values(map).sort((a, b) => b.v - a.v).slice(0, 5);
  }, [produtos, fornecedores]);

  const items = tab === 'clientes' ? clientes : fornec;
  const max = items[0]?.v || 1;
  return (
    <div className="card">
      <div className="card-head"><Icon name="chart" /><div className="t">Top {tab === 'clientes' ? 'Clientes' : 'Fornecedores'} · 90d</div>
        <div className="segmented" style={{ marginLeft: 'auto' }}>
          <div className={`seg ${tab === 'clientes' ? 'active' : ''}`} onClick={() => setTab('clientes')}>CLIENTES</div>
          <div className={`seg ${tab === 'fornec' ? 'active' : ''}`} onClick={() => setTab('fornec')}>FORNEC.</div>
        </div>
      </div>
      <div style={{ padding: 14 }}>
        {items.length === 0 && (
          <div style={{ padding: 22, textAlign: 'center', color: 'var(--fg-3)', fontSize: 11.5 }}>
            {tab === 'clientes' ? 'Nenhum edital cadastrado ainda.' : 'Nenhum produto vinculado a fornecedor.'}
          </div>
        )}
        {items.map((it, i) => {
          const w = (it.v / max) * 100;
          const target = tab === 'clientes' ? 'prospeccao' : 'pdv';
          return (
            <div key={it.n} className="clickable" role="button" tabIndex={0} onClick={() => onNav(target)} onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onNav(target)} style={{ marginBottom: 10, padding: '4px 6px', borderRadius: 4 }}>
              <div className="flex items-center" style={{ justifyContent: 'space-between', marginBottom: 3 }}>
                <span style={{ fontSize: 11.5, color: 'var(--fg-0)' }}>{i + 1}. {it.n}</span>
                <span className="mono" style={{ fontSize: 11, color: 'var(--lime)', fontWeight: 600 }}>{BRL(it.v)}</span>
              </div>
              <div style={{ height: 4, background: 'var(--bg-2)', borderRadius: 2, overflow: 'hidden' }}><div style={{ width: w + '%', height: '100%', background: 'var(--lime)', opacity: 0.7 }}></div></div>
              <div className="flex items-center gap-3" style={{ marginTop: 3, fontSize: 10, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono' }}>
                <span>{it.q} {tab === 'clientes' ? 'editais' : 'produtos'}</span>
                <span>·</span>
                <span>{tab === 'clientes' ? `valor total` : `volume R$`}</span>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ── BRASIL HEATMAP ──────────────────────────────────────── */
function BrasilHeatmap({ onNav, editais }) {
  const list = editais || [];
  const counts = {};
  list.forEach(e => { counts[e.uf] = (counts[e.uf] || 0) + 1; });
  const ALL_UFS = ['AC','AL','AP','AM','BA','CE','DF','ES','GO','MA','MT','MS','MG','PA','PB','PR','PE','PI','RJ','RN','RS','RO','RR','SC','SP','SE','TO'];
  const ufs = ALL_UFS.map(u => ({ u, v: counts[u] || 0 }));
  const max = Math.max(...ufs.map(x => x.v), 1);
  const total = list.length;
  const ufsAtivas = ufs.filter(x => x.v > 0).length;
  return (
    <div className="card">
      <div className="card-head"><Icon name="map" /><div className="t">Distribuição geográfica · editais</div><span className="mono" style={{ marginLeft: 'auto', fontSize: 10.5, color: 'var(--fg-3)' }}>{ufsAtivas} UFs · {total} EDITAIS</span></div>
      <div style={{ padding: 14, display: 'grid', gridTemplateColumns: 'repeat(9, 1fr)', gap: 4 }}>
        {ufs.map(uf => {
          const intensity = uf.v / max;
          const isHot = uf.v > 30;
          const canClick = uf.v > 0;
          return (
            <div
              key={uf.u}
              className={canClick ? 'clickable' : ''}
              role={canClick ? 'button' : undefined}
              tabIndex={canClick ? 0 : undefined}
              title={canClick ? `${uf.u} · ${uf.v} editais` : uf.u}
              onClick={canClick ? () => onNav('prospeccao') : undefined}
              onKeyDown={canClick ? (e => (e.key === 'Enter' || e.key === ' ') && onNav('prospeccao')) : undefined}
              style={{ aspectRatio: '1', borderRadius: 3, background: uf.v === 0 ? 'var(--bg-2)' : `rgba(212, 247, 82, ${0.1 + intensity * 0.7})`, border: '1px solid var(--line-1)', display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', position: 'relative' }}>
              <span style={{ fontSize: 10.5, color: isHot ? 'var(--bg-0)' : uf.v > 0 ? 'var(--fg-0)' : 'var(--fg-3)', fontWeight: 600, fontFamily: 'IBM Plex Mono' }}>{uf.u}</span>
              <span style={{ fontSize: 9, color: isHot ? 'var(--bg-0)' : 'var(--fg-3)', fontFamily: 'IBM Plex Mono' }}>{uf.v || '·'}</span>
            </div>
          );
        })}
      </div>
      <div style={{ padding: '0 14px 14px', display: 'flex', alignItems: 'center', gap: 8 }}>
        <span style={{ fontSize: 10, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono' }}>0</span>
        <div style={{ flex: 1, height: 6, borderRadius: 3, background: 'linear-gradient(to right, rgba(212,247,82,0.1), rgba(212,247,82,0.8))' }}></div>
        <span style={{ fontSize: 10, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono' }}>{max}</span>
      </div>
    </div>
  );
}

/* ── MARGEM POR CATEGORIA ────────────────────────────────── */
function MargemCategoria({ onNav }) {
  const cats = [
    { n: 'Papelaria', m: 41.2, v: 184 },
    { n: 'Escritório', m: 38.4, v: 248 },
    { n: 'Arquivamento', m: 36.8, v: 92 },
    { n: 'Escolar', m: 34.1, v: 142 },
    { n: 'Brinquedos', m: 28.6, v: 48 },
    { n: 'Tintas/EPI', m: 24.2, v: 18 },
  ];
  return (
    <div className="card clickable" role="button" tabIndex={0} onClick={() => onNav('precificacao')} onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onNav('precificacao')}>
      <div className="card-head"><Icon name="dollar" /><div className="t">Margem × Volume por categoria</div><span className="badge" style={{ marginLeft: 'auto', background: 'var(--bg-3)', color: 'var(--fg-3)' }}>DEMO · aguarda M03</span></div>
      <div style={{ padding: 16 }}>
        <svg viewBox="0 0 240 180" style={{ width: '100%', height: 180 }}>
          {[0, 0.25, 0.5, 0.75, 1].map(p => <line key={p} x1="30" x2="230" y1={20 + 140 * p} y2={20 + 140 * p} stroke="var(--line-1)" strokeWidth="0.5" />)}
          {[0, 0.5, 1].map(p => <line key={p} x1={30 + 200 * p} x2={30 + 200 * p} y1="20" y2="160" stroke="var(--line-1)" strokeWidth="0.5" />)}
          {cats.map(c => {
            const x = 30 + (c.v / 260) * 200;
            const y = 160 - ((c.m - 20) / 30) * 140;
            const r = 5 + (c.v / 260) * 14;
            return (
              <g key={c.n}>
                <circle cx={x} cy={y} r={r} fill="var(--lime)" opacity="0.5" stroke="var(--lime)" strokeWidth="1" />
                <text x={x} y={y - r - 3} fontSize="8.5" fill="var(--fg-1)" textAnchor="middle" fontFamily="IBM Plex Mono">{c.n}</text>
                <text x={x} y={y + 3} fontSize="9" fill="var(--bg-0)" textAnchor="middle" fontWeight="600" fontFamily="IBM Plex Mono">{c.m.toFixed(0)}%</text>
              </g>
            );
          })}
          <text x="130" y="178" fontSize="9" fill="var(--fg-3)" textAnchor="middle" fontFamily="IBM Plex Mono">→ Volume (un. × 10³)</text>
          <text x="14" y="90" fontSize="9" fill="var(--fg-3)" textAnchor="middle" fontFamily="IBM Plex Mono" transform="rotate(-90 14 90)">Margem (%)</text>
        </svg>
      </div>
    </div>
  );
}

/* ── CERTIDÕES ───────────────────────────────────────────── */
function CertidoesCard({ onNav }) {
  const [certs, setCerts] = uS(null);
  uE(() => {
    let mounted = true;
    window.dataApi.listCertidoes()
      .then(rows => { if (mounted) setCerts(rows); })
      .catch(() => { if (mounted) setCerts([]); });
    return () => { mounted = false; };
  }, []);

  return (
    <div className="card">
      <div className="card-head"><Icon name="check" /><div className="t">Certidões · habilitação</div><span className="s" style={{ marginLeft: 'auto' }}>{certs ? `${certs.filter(c => c.status === 'critico' || c.status === 'vencida').length} crítica(s)` : '...'}</span></div>
      <div>
        {certs === null && (
          <div style={{ padding: 24, textAlign: 'center', color: 'var(--fg-3)', fontSize: 12 }}>
            <span className="spinner" style={{ marginRight: 8 }}></span> Carregando certidões...
          </div>
        )}
        {certs && certs.length === 0 && (
          <div style={{ padding: 24, textAlign: 'center', color: 'var(--fg-3)', fontSize: 12 }}>
            Nenhuma certidão cadastrada.
          </div>
        )}
        {(certs || []).slice(0, 8).map(c => {
          const color = c.status === 'vencida' ? 'var(--red)' : c.status === 'critico' ? 'var(--red)' : c.status === 'alerta' ? 'var(--amber)' : 'var(--lime)';
          const pct = Math.max(2, Math.min(100, (180 - c.dias) / 180 * 100));
          return (
            <div key={c.id} className="clickable" role="button" tabIndex={0} onClick={() => onNav('auditoria')} onKeyDown={e => (e.key === 'Enter' || e.key === ' ') && onNav('auditoria')} style={{ display: 'grid', gridTemplateColumns: '1fr 70px 50px', gap: 10, padding: '8px 14px', borderBottom: '1px solid var(--line-1)', alignItems: 'center' }}>
              <div>
                <div style={{ fontSize: 11.5, color: 'var(--fg-0)' }}>{c.nome}</div>
                <div style={{ fontSize: 10, color: 'var(--fg-3)', fontFamily: 'IBM Plex Mono' }}>{c.orgao}</div>
              </div>
              <div style={{ height: 5, background: 'var(--bg-2)', borderRadius: 2, overflow: 'hidden' }}><div style={{ width: pct + '%', height: '100%', background: color }}></div></div>
              <div className="mono" style={{ fontSize: 11, color, textAlign: 'right', fontWeight: 600 }}>{c.dias < 0 ? `+${Math.abs(c.dias)}d` : `${c.dias}d`}</div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

/* ── KANBAN ──────────────────────────────────────────────── */
function KanbanLicitacao({ onNav, editais }) {
  const list = editais || [];
  const colMap = {
    prospec: list.filter(e => e.status === 'novo'),
    analise: list.filter(e => e.status === 'analise'),
    precif: list.filter(e => e.status === 'precificacao'),
    disputa: list.filter(e => e.status === 'disputa'),
    ganhos: list.filter(e => e.status === 'ganho'),
    descart: list.filter(e => e.status === 'descartado'),
  };
  return (
    <div className="kanban">
      {KANBAN_LIC.map(col => (
        <div key={col.id} className="kan-col">
          <div className="kan-head">
            <span className="dot" style={{ background: col.color }}></span>
            {col.label}
            <span className="ct">{colMap[col.id]?.length || 0}</span>
          </div>
          <div className="kan-body">
            {(colMap[col.id] || []).map(e => (
              <div key={e.id} className="kan-card" onClick={() => onNav('prospeccao')}>
                <div className="id">{e.numero}</div>
                <div className="ttl">{e.orgao}</div>
                <div className="meta">
                  <span>{e.uf}</span><span>·</span><span>{e.itens || '—'} itens</span>
                  <span className="val">{BRL(e.valor)}</span>
                </div>
              </div>
            ))}
            {(colMap[col.id] || []).length === 0 && (
              <div style={{ padding: 14, textAlign: 'center', fontSize: 10.5, color: 'var(--fg-3)' }}>—</div>
            )}
          </div>
        </div>
      ))}
    </div>
  );
}

window.MDashboard = MDashboard;
