/* Comercial · Business Plan / Pipeline Completo
 * ========================================================================
 * Pipeline Gestor (FM real) + BP Primavera (mock até task #25).
 * Quando vendedorId disponível, carrega dados reais do FM.
 * Métricas de vendas (VENDAS_YTD, BP, SPIN, etc.) ficam **** até Primavera.
 * ======================================================================== */

// ── Pipeline hook (servidor faz cache 10min) ──────────────────────────────────
const usePipelineBP = (vendedorId) => {
  const [state, setState] = React.useState({ data: null, loading: false, error: null });
  React.useEffect(() => {
    if (!vendedorId) return;
    setState(s => ({ ...s, loading: true, error: null }));
    fetch(`/api/pipeline/${vendedorId}`)
      .then(r => r.json())
      .then(json => { if (json.error) throw new Error(json.error); setState({ data: json, loading: false, error: null }); })
      .catch(err => setState({ data: null, loading: false, error: err.message }));
  }, [vendedorId]);
  return state;
};

// ============================================================================
// DADOS (Mimaki PT · Daniel Silva · 2026) — extraídos do dashboard Primavera
// ============================================================================
const BP_MESES = ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'];

// null = mês futuro (ainda não aconteceu)
const BP_MATRIZ = {
  spin:          [47, 48, 90, 39, null, null, null, null, null, null, null, null],
  optmkt:        [44, 21, 42,  9, null, null, null, null, null, null, null, null],
  optcom:        [41, 38, 88, 36, null, null, null, null, null, null, null, null],
  opmanagerfs:   [2138118, 1518148, 4031432, 1732890, null, null, null, null, null, null, null, null],
  bp:            [260000, 265000, 305000, 320000, 330000, 325000, 325000, 220000, 325000, 330000, 330000, 325000],
  fsfacturar:    [null,   null,   null,   302850, null, null, null, null, null, null, null, null],
  vendas:        [204870, 211830, 418501, 88093, null, null, null, null, null, null, null, null],
};

// Desvio mensal (vendas - BP) — só meses com vendas
const BP_DESVIO = BP_MATRIZ.vendas.map((v, i) => v == null ? null : v - BP_MATRIZ.bp[i]);

// Mês actual (Abr fechado, ou seja, estamos no fim de Abril)
const BP_MES_ACTUAL = 4; // Abril = index 3 (1-indexed = 4)
const BP_ANO = 2026;

// ============================================================================
// HELPERS
// ============================================================================
const fmtK = (n) => {
  if (n == null) return '—';
  const abs = Math.abs(n);
  if (abs >= 1000000) return (n / 1000000).toFixed(2).replace('.', ',') + 'M';
  if (abs >= 1000) return Math.round(n / 1000) + 'k';
  return String(n);
};
const fmtEur = (n) => n == null ? '—' : '€' + fmtK(n);
const fmtN = (n) => n == null ? '—' : new Intl.NumberFormat('pt-PT').format(n);

// Cor de desvio para as células vendas/bp
const desvioColor = (v) => {
  if (v == null) return null;
  if (v >= 0) return 'var(--dgd-green-700)';
  const pct = Math.min(Math.abs(v) / 300000, 1);
  // de âmbar a vermelho
  return `rgba(240, ${Math.round(120 - pct * 70)}, ${Math.round(80 - pct * 40)}, 1)`;
};

// ============================================================================
// CÁLCULOS DERIVADOS
// ============================================================================
const sumYTD = (arr) => arr.slice(0, BP_MES_ACTUAL).reduce((a, b) => a + (b || 0), 0);
const sumFull = (arr) => arr.reduce((a, b) => a + (b || 0), 0);

const VENDAS_YTD = sumYTD(BP_MATRIZ.vendas);            // 923 294
const BP_YTD = sumYTD(BP_MATRIZ.bp);                    // 1 150 000
const BP_ANUAL = sumFull(BP_MATRIZ.bp);                 // 3 660 000
const DESVIO_YTD = VENDAS_YTD - BP_YTD;                 // -226 706
const PROJECTADO_ANO = (VENDAS_YTD / BP_MES_ACTUAL) * 12; // extrapolação linear
const DESVIO_PROJECTADO = PROJECTADO_ANO - BP_ANUAL;    // -2,7M
const PCT_BP = VENDAS_YTD / BP_ANUAL;                   // ~25%
const PCT_TEMPO = BP_MES_ACTUAL / 12;                   // 33%

const OP_PIPELINE = BP_MATRIZ.opmanagerfs[BP_MES_ACTUAL - 1]; // 1,73M actual
const OP_TOTAL_GERADO = sumYTD(BP_MATRIZ.optcom) + sumYTD(BP_MATRIZ.optmkt); // 319 OPs
const VENDAS_CONTAGEM = 52; // ticket médio 18k → ~52 vendas
const TICKET_MEDIO = VENDAS_YTD / VENDAS_CONTAGEM;      // 17 755
const CONVERSAO = VENDAS_YTD / (OP_PIPELINE * 4);       // grosseiro — contra pipeline médio
const VELOCIDADE_DIAS = 47; // mock — dias médios OP → Venda
const OPS_POR_MES = Math.round(OP_TOTAL_GERADO / BP_MES_ACTUAL); // 80

// Gap a recuperar em 8 meses restantes
const GAP_RECUPERAR = Math.abs(DESVIO_PROJECTADO); // 2,7M
const MESES_RESTANTES = 12 - BP_MES_ACTUAL;        // 8
const VENDAS_POR_MES_NECESSARIO = GAP_RECUPERAR / MESES_RESTANTES;

// ============================================================================
// HERO — números grandes + barra progresso anual
// ============================================================================
const BPHero = ({ pipelineData }) => {
  const isLive = !!pipelineData?.byStage;
  const livePipelineTotal = isLive ? pipelineData.byStage.reduce((s, x) => s + x.value, 0) : null;
  const liveOpsTotal      = isLive ? pipelineData.total : null;
  const liveActive        = isLive ? pipelineData.active : null;

  const cell = (label, value, sub, color, note) => (
    <div style={{ flex: 1, padding: '14px 18px', borderRight: '1px solid var(--dgd-border-1)' }}>
      <div style={{ fontSize: 9.5, color: 'var(--dgd-fg-3)', letterSpacing: '0.1em', fontFamily: 'var(--dgd-font-mono)', marginBottom: 4 }}>
        {label}{note && <span style={{ color: 'var(--dgd-pumpkin-700)', marginLeft: 6 }}>{note}</span>}
      </div>
      <div className="font-display" style={{ fontSize: 24, fontWeight: 600, color: color || 'var(--dgd-fg-1)', letterSpacing: '-0.01em', lineHeight: 1 }}>{value}</div>
      {sub && <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-2)', marginTop: 3 }}>{sub}</div>}
    </div>
  );

  return (
    <div>
      {/* cabeçalho compacto */}
      <div style={{ display: 'flex', alignItems: 'baseline', gap: 14, marginBottom: 10 }}>
        <div>
          <div style={{ fontSize: 10, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', letterSpacing: '0.1em' }}>COMERCIAL · PIPELINE {BP_ANO}</div>
          <h2 className="font-display" style={{ margin: '2px 0 0', fontSize: 22, fontWeight: 600, letterSpacing: '-0.01em' }}>
            Pipeline Gestor
            {isLive && <span style={{ fontSize: 13, fontWeight: 400, color: 'var(--dgd-green-700)', marginLeft: 10 }}>· dados reais</span>}
          </h2>
        </div>
        <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 6, padding: '3px 9px', borderRadius: 999, background: 'color-mix(in oklch, var(--dgd-pumpkin-700) 12%, transparent)', color: 'var(--dgd-pumpkin-700)', fontSize: 10.5, fontWeight: 600, letterSpacing: '0.04em' }}>
          <span style={{ width: 5, height: 5, borderRadius: '50%', background: 'var(--dgd-pumpkin-700)' }} /> BP PRIMAVERA PENDENTE
        </div>
      </div>

      {/* strip de KPIs */}
      <div style={{ display: 'flex', background: 'var(--dgd-bg-surface)', border: '1px solid var(--dgd-border-1)', borderRadius: 10, overflow: 'hidden' }}>
        {cell('PIPELINE TOTAL', isLive ? fmtEur(livePipelineTotal) : '****', isLive ? `${liveOpsTotal} OPs · Gestor` : 'a carregar…', isLive ? 'var(--dgd-primary-700)' : 'var(--dgd-fg-3)')}
        {cell('OPs ACTIVAS', isLive ? String(liveActive) : '****', isLive ? `de ${liveOpsTotal} total` : null, null)}
        {cell('VENDAS YTD', '****', 'Primavera — task #25', 'var(--dgd-fg-3)', 'PENDENTE')}
        {cell('BP YTD', '****', 'Primavera — task #25', 'var(--dgd-fg-3)', 'PENDENTE')}
        <div style={{ flex: 1, padding: '14px 18px' }}>
          <div style={{ fontSize: 9.5, color: 'var(--dgd-fg-3)', letterSpacing: '0.1em', fontFamily: 'var(--dgd-font-mono)', marginBottom: 4 }}>GAP ANUAL</div>
          <div className="font-display" style={{ fontSize: 24, fontWeight: 600, color: 'var(--dgd-fg-3)', letterSpacing: '-0.01em', lineHeight: 1 }}>****</div>
          <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-3)', marginTop: 3 }}>Primavera — task #25</div>
        </div>
      </div>

      {/* barra progresso anual */}
      <div style={{ marginTop: 10 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 10.5, color: 'var(--dgd-fg-2)', marginBottom: 5, fontFamily: 'var(--dgd-font-mono)' }}>
          <span>PROGRESSO ANUAL · {Math.round(PCT_TEMPO * 100)}% do ano decorrido</span>
          <span style={{ color: 'var(--dgd-fg-3)' }}>Vendas vs BP ****% · aguarda Primavera</span>
        </div>
        <div style={{ position: 'relative', height: 8, background: 'var(--dgd-bg-surface)', borderRadius: 4, border: '1px solid var(--dgd-border-1)', overflow: 'hidden' }}>
          <div style={{ position: 'absolute', left: `${PCT_TEMPO * 100}%`, top: -3, bottom: -3, width: 2, background: 'var(--dgd-fg-1)', opacity: 0.7 }} />
        </div>
        <div style={{ fontSize: 10, color: 'var(--dgd-fg-3)', marginTop: 4 }}>
          O marker preto = {Math.round(PCT_TEMPO * 100)}% do ano (Maio). Vendas reais em falta — aguarda integração Primavera (task #25).
        </div>
      </div>
    </div>
  );
};

// ============================================================================
// MATRIZ 12m × 6 métricas — estilo Primavera mas com cor e hover
// ============================================================================
const BPMatriz = () => {
  const linhas = [
    { key: 'spin',        label: 'SPIN',        hint: 'Visitas comerciais',          type: 'n' },
    { key: 'optmkt',      label: 'OPTMKT',      hint: 'OPs geradas por Marketing',    type: 'n' },
    { key: 'optcom',      label: 'OPTCOM',      hint: 'OPs geradas por Comercial',    type: 'n' },
    { key: 'opmanagerfs', label: 'OPMANAGERFS', hint: 'Pipeline em gestão',           type: 'e' },
    { key: 'bp',          label: 'BP',          hint: 'Objectivo mensal',             type: 'e', accent: true },
    { key: 'fsfacturar',  label: 'FSFACTURAR',  hint: 'Em processamento',             type: 'e' },
    { key: 'vendas',      label: 'VENDAS',      hint: 'Vendas realizadas',            type: 'e', accent: true },
  ];
  const cellStyle = (isCurrent, isFuture) => ({
    padding: '8px 6px',
    textAlign: 'right',
    fontFamily: 'var(--dgd-font-mono)',
    fontSize: 11,
    borderLeft: '1px solid var(--dgd-border-2)',
    background: isCurrent ? 'color-mix(in oklch, var(--accent) 8%, transparent)' : isFuture ? 'color-mix(in oklch, var(--dgd-bg-surface) 50%, transparent)' : 'transparent',
    color: isFuture ? 'var(--dgd-fg-3)' : 'var(--dgd-fg-1)',
  });

  return (
    <div style={{ border: '1px solid var(--dgd-border-1)', borderRadius: 10, overflow: 'hidden', background: 'var(--dgd-bg-surface)' }}>
      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
        <thead>
          <tr style={{ background: 'var(--dgd-bg-app)' }}>
            <th style={{ textAlign: 'left', padding: '8px 12px', fontSize: 10, color: 'var(--dgd-fg-3)', letterSpacing: '0.08em', fontFamily: 'var(--dgd-font-mono)', fontWeight: 600, width: 140 }}>MÉTRICA</th>
            {BP_MESES.map((m, i) => (
              <th key={m} style={{
                padding: '8px 6px', fontSize: 10, color: (i + 1 === BP_MES_ACTUAL) ? 'var(--accent)' : 'var(--dgd-fg-3)',
                letterSpacing: '0.08em', fontFamily: 'var(--dgd-font-mono)', fontWeight: 600, textAlign: 'right',
                borderLeft: '1px solid var(--dgd-border-2)',
                background: (i + 1 === BP_MES_ACTUAL) ? 'color-mix(in oklch, var(--accent) 10%, transparent)' : 'transparent',
              }}>{m.toUpperCase()}</th>
            ))}
            <th style={{ padding: '8px 10px', fontSize: 10, color: 'var(--dgd-fg-1)', letterSpacing: '0.08em', fontFamily: 'var(--dgd-font-mono)', fontWeight: 700, textAlign: 'right', borderLeft: '1px solid var(--dgd-border-1)', background: 'var(--dgd-bg-app)' }}>TOTAL</th>
          </tr>
        </thead>
        <tbody>
          {linhas.map((l) => {
            const vals = BP_MATRIZ[l.key];
            const total = sumFull(vals);
            return (
              <tr key={l.key} style={{ borderTop: '1px solid var(--dgd-border-2)', background: l.accent ? 'color-mix(in oklch, var(--dgd-bg-app) 40%, transparent)' : 'transparent' }}>
                <td style={{ padding: '10px 12px' }}>
                  <div style={{ fontSize: 11.5, fontWeight: 600, color: 'var(--dgd-fg-1)' }}>{l.label}</div>
                  <div style={{ fontSize: 10, color: 'var(--dgd-fg-2)', marginTop: 1 }}>{l.hint}</div>
                </td>
                {vals.map((v, i) => {
                  const isCurrent = (i + 1) === BP_MES_ACTUAL;
                  const isFuture = i >= BP_MES_ACTUAL;
                  return (
                    <td key={i} style={cellStyle(isCurrent, isFuture)}>
                      {v == null ? '' : (l.type === 'e' ? fmtK(v) : fmtN(v))}
                    </td>
                  );
                })}
                <td style={{ padding: '10px', textAlign: 'right', fontFamily: 'var(--dgd-font-mono)', fontSize: 12, fontWeight: 600, color: 'var(--dgd-fg-1)', background: 'color-mix(in oklch, var(--dgd-bg-app) 60%, transparent)', borderLeft: '1px solid var(--dgd-border-1)' }}>
                  {l.type === 'e' ? fmtK(total) : fmtN(total)}
                </td>
              </tr>
            );
          })}
          {/* Linha BP DESVIO calculada */}
          <tr style={{ borderTop: '1px solid var(--dgd-border-1)', background: 'color-mix(in oklch, var(--dgd-red-700) 6%, transparent)' }}>
            <td style={{ padding: '10px 12px' }}>
              <div style={{ fontSize: 11.5, fontWeight: 700, color: 'var(--dgd-red-700)' }}>BP DESVIO</div>
              <div style={{ fontSize: 10, color: 'var(--dgd-fg-2)', marginTop: 1 }}>Acumulado</div>
            </td>
            {(() => {
              // desvio acumulado: cada mês soma vendas-BP até aí; após mês actual, extrapola
              let acc = 0;
              return BP_DESVIO.map((d, i) => {
                const isCurrent = (i + 1) === BP_MES_ACTUAL;
                const isFuture = i >= BP_MES_ACTUAL;
                if (d != null) acc += d;
                else {
                  // projecção: usar desvio médio YTD
                  const medioMensal = DESVIO_YTD / BP_MES_ACTUAL;
                  acc += medioMensal - BP_MATRIZ.bp[i] + (VENDAS_YTD / BP_MES_ACTUAL);
                }
                const val = acc;
                return (
                  <td key={i} style={{
                    ...cellStyle(isCurrent, isFuture),
                    color: val >= 0 ? 'var(--dgd-green-700)' : desvioColor(val),
                    fontWeight: 600,
                  }}>
                    {fmtK(Math.round(val))}
                  </td>
                );
              });
            })()}
            <td style={{ padding: '10px', textAlign: 'right', fontFamily: 'var(--dgd-font-mono)', fontSize: 12, fontWeight: 700, color: 'var(--dgd-red-700)', background: 'color-mix(in oklch, var(--dgd-red-700) 10%, transparent)', borderLeft: '1px solid var(--dgd-border-1)' }}>
              {fmtK(Math.round(DESVIO_PROJECTADO))}
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  );
};

// ============================================================================
// KPIs DERIVADOS
// ============================================================================
const BPKpisDerivados = () => {
  const kpis = [
    { label: 'Conversão', value: '9,8%', sub: 'Média equipa: 14%', trend: 'down', detail: 'Vendas / Pipeline. Abaixo da média.' },
    { label: 'Velocidade', value: `${VELOCIDADE_DIAS}d`, sub: 'OP → Venda', trend: 'flat', detail: 'Dias médios. Em linha.' },
    { label: 'Ticket médio', value: fmtEur(Math.round(TICKET_MEDIO)), sub: '52 vendas YTD', trend: 'up', detail: 'Subiu €1.2k vs 2025.' },
    { label: 'OPs / mês', value: OPS_POR_MES, sub: 'Meta: 100', trend: 'down', detail: 'OPTCOM + OPTMKT. Abaixo meta.' },
  ];
  const trendColor = { up: 'var(--dgd-green-700)', down: 'var(--dgd-red-700)', flat: 'var(--dgd-fg-2)' };
  const trendGlyph = { up: '↗', down: '↘', flat: '→' };
  return (
    <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 10 }}>
      {kpis.map((k) => (
        <div key={k.label} style={{ padding: '14px 16px', background: 'var(--dgd-bg-surface)', border: '1px solid var(--dgd-border-1)', borderRadius: 10 }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 6 }}>
            <div style={{ fontSize: 10, color: 'var(--dgd-fg-3)', letterSpacing: '0.08em', fontFamily: 'var(--dgd-font-mono)' }}>{k.label.toUpperCase()}</div>
            <div style={{ fontSize: 13, color: trendColor[k.trend], lineHeight: 1 }}>{trendGlyph[k.trend]}</div>
          </div>
          <div className="font-display" style={{ fontSize: 24, fontWeight: 600, letterSpacing: '-0.01em', lineHeight: 1 }}>{k.value}</div>
          <div style={{ fontSize: 11, color: 'var(--dgd-fg-2)', marginTop: 4 }}>{k.sub}</div>
          <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-3)', marginTop: 6, lineHeight: 1.5 }}>{k.detail}</div>
        </div>
      ))}
    </div>
  );
};

// ============================================================================
// ANÁLISE DIGI — insights automáticos
// ============================================================================
const BPAnaliseDigi = () => {
  const insights = [
    {
      icon: '⚠', kind: 'warn',
      title: 'Anomalia detectada em Abril',
      body: 'SPIN caiu 57% (90→39), OPTMKT caiu 78% (42→9), vendas caíram 79% (€419k→€88k). Quebra simultânea em 4 métricas — normalmente significa férias, baixa ou licença. Queres que te diga o que explica?',
      action: 'Investigar Abril',
    },
    {
      icon: '▽', kind: 'warn',
      title: 'Conversão pipeline → venda está em 9,8%',
      body: 'Média da equipa Mimaki Ibérica: 14%. Estás 40% abaixo. Não é problema de volume (319 OPs em 4 meses) — é de fecho. 47 OPs em "proposta enviada" há >30 dias precisam de follow-up já.',
      action: 'Ver OPs paradas',
    },
    {
      icon: '●', kind: 'ok',
      title: 'Março foi o único mês acima do BP',
      body: '90 visitas SPIN em Março (vs média 45) → €419k vendas (vs BP €305k). Correlação directa: dobrar SPIN dobra vendas. Se manténs SPIN≥80/mês até Dezembro, recuperas €1.1M do gap.',
      action: 'Ver plano SPIN',
    },
  ];
  const kindColor = { warn: 'var(--dgd-pumpkin-700)', ok: 'var(--dgd-green-700)', info: 'var(--accent)' };
  return (
    <div style={{ background: 'var(--dgd-bg-surface)', border: '1px solid var(--dgd-border-1)', borderRadius: 10, overflow: 'hidden' }}>
      <div style={{ padding: '12px 16px', borderBottom: '1px solid var(--dgd-border-1)', display: 'flex', alignItems: 'center', gap: 10 }}>
        <span className="ai-chip"><span className="ai-dot" />Digi</span>
        <div style={{ fontSize: 12, color: 'var(--dgd-fg-2)' }}>Analisei os 12 meses. Encontrei 3 padrões relevantes.</div>
      </div>
      {insights.map((it, i) => (
        <div key={i} style={{ padding: '14px 16px', borderTop: i > 0 ? '1px solid var(--dgd-border-2)' : 'none', display: 'flex', gap: 12, alignItems: 'flex-start' }}>
          <div style={{
            width: 24, height: 24, borderRadius: 6, flexShrink: 0,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            background: `color-mix(in oklch, ${kindColor[it.kind]} 18%, transparent)`,
            color: kindColor[it.kind], fontSize: 13, fontWeight: 700,
          }}>{it.icon}</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--dgd-fg-1)', marginBottom: 3 }}>{it.title}</div>
            <div style={{ fontSize: 12, color: 'var(--dgd-fg-2)', lineHeight: 1.6 }}>{it.body}</div>
          </div>
          <button className="btn" style={{ flexShrink: 0, fontSize: 11, padding: '6px 10px' }}>{it.action}</button>
        </div>
      ))}
    </div>
  );
};

// ============================================================================
// PLANO RECUPERAÇÃO — 4 blocos somando ao gap
// ============================================================================
const BP_PLANO_CARTEIRA = [
  { nome: 'Gráfica Central, Lda', ultima: '11m', potencial: 95000, marca: 'Mimaki UCJV', razao: 'Ciclo médio 8m · vencido' },
  { nome: 'Olimpo Print',        ultima: '14m', potencial: 120000, marca: 'Mimaki CJV200', razao: 'Equipamento EOL previsto' },
  { nome: 'Rótulos Norte, SA',    ultima: '9m',  potencial: 68000, marca: 'Mimaki UJV200', razao: 'Expansão sinalizada no LinkedIn' },
  { nome: 'Digital Trends',       ultima: '10m', potencial: 82000, marca: 'Mimaki JV330', razao: 'Contactou em Fev · sem follow-up' },
  { nome: 'Artes Gráficas Lda',   ultima: '13m', potencial: 55000, marca: 'Mimaki CJV150', razao: 'Ciclo médio 12m · vencido' },
  { nome: 'Sinal+ Ibérica',       ultima: '8m',  potencial: 145000, marca: 'Mimaki UJF-7151', razao: 'Segunda máquina prevista' },
  { nome: 'Tipografia Moderna',   ultima: '12m', potencial: 70000, marca: 'Mimaki UCJV300', razao: 'Contrato manutenção expira Mai' },
  { nome: '+ 5 clientes',         ultima: '—',   potencial: 45000, marca: '—',             razao: 'Probabilidade >60%' },
];
const BP_PLANO_OPS = [
  { cliente: 'Printcolor SL',      valor: 48000, diasParado: 52, fase: 'Proposta enviada', marca: 'Mimaki' },
  { cliente: 'Gráfica do Sul',     valor: 95000, diasParado: 41, fase: 'Proposta enviada', marca: 'Mimaki' },
  { cliente: 'Adesivos Express',   valor: 32000, diasParado: 38, fase: 'Proposta revista', marca: 'Mimaki' },
  { cliente: 'Vinyl Lab',          valor: 110000, diasParado: 33, fase: 'Proposta enviada', marca: 'Mimaki' },
  { cliente: 'Comunicação Visual', valor: 58000, diasParado: 45, fase: 'Em negociação',    marca: 'Mimaki' },
  { cliente: '+ 42 OPs',           valor: 77000, diasParado: 31, fase: 'Várias fases',      marca: 'Mimaki' },
];
const BP_PLANO_PROSPEC = [
  { empresa: 'Rotulados Barcelona, SL', cidade: 'Barcelona',    score: 9, capex: 85000 },
  { empresa: 'Impresión Madrid Digital', cidade: 'Madrid',       score: 9, capex: 120000 },
  { empresa: 'Gráficas del Levante',     cidade: 'Valência',     score: 8, capex: 75000 },
  { empresa: 'Serigrafía Andaluza',      cidade: 'Sevilha',      score: 8, capex: 95000 },
  { empresa: 'Print Solutions Ibérica',  cidade: 'Barcelona',    score: 8, capex: 65000 },
  { empresa: 'Diseño e Impresión Norte', cidade: 'Bilbau',       score: 8, capex: 110000 },
];

const PlanoBlocoCarteira = () => {
  const total = BP_PLANO_CARTEIRA.reduce((a, b) => a + b.potencial, 0);
  return (
    <div style={{ background: 'var(--dgd-bg-surface)', border: '1px solid var(--dgd-border-1)', borderRadius: 10, overflow: 'hidden' }}>
      <div style={{ padding: '12px 14px', borderBottom: '1px solid var(--dgd-border-1)', display: 'flex', alignItems: 'center', gap: 10 }}>
        <div style={{ width: 28, height: 28, borderRadius: 7, background: 'color-mix(in oklch, var(--accent) 18%, transparent)', color: 'var(--accent)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, fontWeight: 700 }}>1</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 12.5, fontWeight: 600 }}>Carteira · recompras prováveis</div>
          <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-2)', marginTop: 1 }}>12 clientes com probabilidade recompra &gt;70%</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div className="font-display" style={{ fontSize: 18, fontWeight: 600, color: 'var(--dgd-green-700)' }}>{fmtEur(total)}</div>
          <div style={{ fontSize: 10, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)' }}>RECUPERÁVEL</div>
        </div>
      </div>
      <div>
        {BP_PLANO_CARTEIRA.map((c, i) => (
          <div key={i} style={{ padding: '9px 14px', borderTop: i > 0 ? '1px solid var(--dgd-border-2)' : 'none', display: 'grid', gridTemplateColumns: '1.4fr 0.8fr 0.5fr 0.7fr', alignItems: 'center', gap: 10, fontSize: 11.5 }}>
            <div>
              <div style={{ fontWeight: 600 }}>{c.nome}</div>
              <div style={{ fontSize: 10, color: 'var(--dgd-fg-2)', marginTop: 1 }}>{c.razao}</div>
            </div>
            <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-2)' }}>{c.marca}</div>
            <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-2)', fontFamily: 'var(--dgd-font-mono)' }}>última {c.ultima}</div>
            <div style={{ textAlign: 'right', fontFamily: 'var(--dgd-font-mono)', fontWeight: 600, color: 'var(--dgd-fg-1)' }}>{fmtEur(c.potencial)}</div>
          </div>
        ))}
      </div>
      <div style={{ padding: '10px 14px', borderTop: '1px solid var(--dgd-border-1)', display: 'flex', gap: 8 }}>
        <button className="btn btn-primary" style={{ fontSize: 11, padding: '6px 12px' }}>Abordar todos →</button>
        <button className="btn" style={{ fontSize: 11, padding: '6px 12px' }}>Ver na Carteira</button>
      </div>
    </div>
  );
};

const PlanoBlocoOPs = () => {
  const total = BP_PLANO_OPS.reduce((a, b) => a + b.valor, 0);
  return (
    <div style={{ background: 'var(--dgd-bg-surface)', border: '1px solid var(--dgd-border-1)', borderRadius: 10, overflow: 'hidden' }}>
      <div style={{ padding: '12px 14px', borderBottom: '1px solid var(--dgd-border-1)', display: 'flex', alignItems: 'center', gap: 10 }}>
        <div style={{ width: 28, height: 28, borderRadius: 7, background: 'color-mix(in oklch, var(--dgd-pumpkin-700) 18%, transparent)', color: 'var(--dgd-pumpkin-700)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, fontWeight: 700 }}>2</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 12.5, fontWeight: 600 }}>OPs em risco · precisam de follow-up</div>
          <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-2)', marginTop: 1 }}>47 OPs em "proposta enviada" há mais de 30 dias</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div className="font-display" style={{ fontSize: 18, fontWeight: 600, color: 'var(--dgd-pumpkin-700)' }}>{fmtEur(total)}</div>
          <div style={{ fontSize: 10, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)' }}>POR FECHAR</div>
        </div>
      </div>
      <div>
        {BP_PLANO_OPS.map((o, i) => (
          <div key={i} style={{ padding: '9px 14px', borderTop: i > 0 ? '1px solid var(--dgd-border-2)' : 'none', display: 'grid', gridTemplateColumns: '1.3fr 1fr 0.6fr 0.7fr', alignItems: 'center', gap: 10, fontSize: 11.5 }}>
            <div style={{ fontWeight: 600 }}>{o.cliente}</div>
            <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-2)' }}>{o.fase}</div>
            <div style={{ fontSize: 10.5, color: 'var(--dgd-red-700)', fontFamily: 'var(--dgd-font-mono)' }}>{o.diasParado}d parado</div>
            <div style={{ textAlign: 'right', fontFamily: 'var(--dgd-font-mono)', fontWeight: 600 }}>{fmtEur(o.valor)}</div>
          </div>
        ))}
      </div>
      <div style={{ padding: '10px 14px', borderTop: '1px solid var(--dgd-border-1)', display: 'flex', gap: 8 }}>
        <button className="btn btn-primary" style={{ fontSize: 11, padding: '6px 12px' }}>Follow-up automático →</button>
        <button className="btn" style={{ fontSize: 11, padding: '6px 12px' }}>Ver no Primavera</button>
      </div>
    </div>
  );
};

const PlanoBlocoProspec = () => {
  const total = BP_PLANO_PROSPEC.reduce((a, b) => a + b.capex, 0);
  return (
    <div style={{ background: 'var(--dgd-bg-surface)', border: '1px solid var(--dgd-border-1)', borderRadius: 10, overflow: 'hidden' }}>
      <div style={{ padding: '12px 14px', borderBottom: '1px solid var(--dgd-border-1)', display: 'flex', alignItems: 'center', gap: 10 }}>
        <div style={{ width: 28, height: 28, borderRadius: 7, background: 'color-mix(in oklch, var(--dgd-green-700) 18%, transparent)', color: 'var(--dgd-green-700)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, fontWeight: 700 }}>3</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 12.5, fontWeight: 600 }}>Prospecção ES · leads match directo</div>
          <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-2)', marginTop: 1 }}>8 leads quentes (score 8–9) compatíveis com Mimaki</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div className="font-display" style={{ fontSize: 18, fontWeight: 600, color: 'var(--dgd-green-700)' }}>{fmtEur(total)}</div>
          <div style={{ fontSize: 10, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)' }}>POTENCIAL</div>
        </div>
      </div>
      <div>
        {BP_PLANO_PROSPEC.map((p, i) => (
          <div key={i} style={{ padding: '9px 14px', borderTop: i > 0 ? '1px solid var(--dgd-border-2)' : 'none', display: 'grid', gridTemplateColumns: '1.4fr 0.8fr 0.5fr 0.7fr', alignItems: 'center', gap: 10, fontSize: 11.5 }}>
            <div style={{ fontWeight: 600 }}>{p.empresa}</div>
            <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-2)' }}>{p.cidade}</div>
            <div>
              <span style={{ padding: '1px 6px', borderRadius: 3, background: 'color-mix(in oklch, var(--dgd-green-700) 18%, transparent)', color: 'var(--dgd-green-700)', fontSize: 10, fontWeight: 700, fontFamily: 'var(--dgd-font-mono)' }}>{p.score}/10</span>
            </div>
            <div style={{ textAlign: 'right', fontFamily: 'var(--dgd-font-mono)', fontWeight: 600 }}>{fmtEur(p.capex)}</div>
          </div>
        ))}
      </div>
      <div style={{ padding: '10px 14px', borderTop: '1px solid var(--dgd-border-1)', display: 'flex', gap: 8 }}>
        <button className="btn btn-primary" style={{ fontSize: 11, padding: '6px 12px' }}>Ver leads →</button>
        <button className="btn" style={{ fontSize: 11, padding: '6px 12px' }}>Preparar campanha</button>
      </div>
    </div>
  );
};

const PlanoBlocoGap = () => {
  const recuperado = BP_PLANO_CARTEIRA.reduce((a, b) => a + b.potencial, 0)
                   + BP_PLANO_OPS.reduce((a, b) => a + b.valor, 0)
                   + BP_PLANO_PROSPEC.reduce((a, b) => a + b.capex, 0);
  const gap = GAP_RECUPERAR - recuperado;
  const pct = recuperado / GAP_RECUPERAR;
  return (
    <div style={{ background: 'var(--dgd-bg-surface)', border: '1px solid var(--dgd-border-1)', borderRadius: 10, padding: 16 }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
        <div style={{ width: 28, height: 28, borderRadius: 7, background: 'color-mix(in oklch, var(--dgd-red-700) 18%, transparent)', color: 'var(--dgd-red-700)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 13, fontWeight: 700 }}>4</div>
        <div style={{ flex: 1 }}>
          <div style={{ fontSize: 12.5, fontWeight: 600 }}>Gap residual</div>
          <div style={{ fontSize: 10.5, color: 'var(--dgd-fg-2)', marginTop: 1 }}>O que sobra depois dos 3 planos acima</div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div className="font-display" style={{ fontSize: 20, fontWeight: 600, color: gap > 0 ? 'var(--dgd-red-700)' : 'var(--dgd-green-700)' }}>{fmtEur(Math.abs(gap))}</div>
          <div style={{ fontSize: 10, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)' }}>{gap > 0 ? 'A ENCONTRAR' : 'EXCEDENTE'}</div>
        </div>
      </div>

      {/* barra visual */}
      <div style={{ position: 'relative', height: 28, background: 'var(--dgd-bg-app)', border: '1px solid var(--dgd-border-1)', borderRadius: 6, overflow: 'hidden', display: 'flex', marginBottom: 10 }}>
        <div style={{ width: `${(BP_PLANO_CARTEIRA.reduce((a,b)=>a+b.potencial,0)/GAP_RECUPERAR)*100}%`, background: 'var(--accent)', opacity: 0.8, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 10, fontWeight: 700, color: 'white' }}>Carteira</div>
        <div style={{ width: `${(BP_PLANO_OPS.reduce((a,b)=>a+b.valor,0)/GAP_RECUPERAR)*100}%`, background: 'var(--dgd-pumpkin-700)', opacity: 0.8, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 10, fontWeight: 700, color: 'white' }}>OPs</div>
        <div style={{ width: `${(BP_PLANO_PROSPEC.reduce((a,b)=>a+b.capex,0)/GAP_RECUPERAR)*100}%`, background: 'var(--dgd-green-700)', opacity: 0.8, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 10, fontWeight: 700, color: 'white' }}>Prospec</div>
        <div style={{ flex: 1, background: 'repeating-linear-gradient(45deg, transparent, transparent 6px, color-mix(in oklch, var(--dgd-red-700) 20%, transparent) 6px, color-mix(in oklch, var(--dgd-red-700) 20%, transparent) 12px)', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 10, fontWeight: 700, color: 'var(--dgd-red-700)' }}>Gap</div>
      </div>

      <div style={{ fontSize: 12, color: 'var(--dgd-fg-2)', lineHeight: 1.65, marginTop: 10 }}>
        <span className="ai-chip" style={{ display: 'inline-flex', marginRight: 8, verticalAlign: 'middle' }}><span className="ai-dot" />Digi</span>
        Identifiquei {fmtEur(recuperado)} de gap recuperável concreto. Os restantes <strong style={{ color: 'var(--dgd-red-700)' }}>{fmtEur(gap)}</strong> não têm plano definido ainda. Sugiro: <strong style={{ color: 'var(--dgd-fg-1)' }}>campanha outbound para 32 clientes inactivos há &gt;18m</strong> + <strong style={{ color: 'var(--dgd-fg-1)' }}>aumentar SPIN para 80 visitas/mês</strong> (vs média actual {Math.round(sumYTD(BP_MATRIZ.spin)/BP_MES_ACTUAL)}). Queres que prepare?
      </div>

      <div style={{ display: 'flex', gap: 8, marginTop: 12 }}>
        <button className="btn btn-primary" style={{ fontSize: 11, padding: '7px 14px' }}>Preparar campanha outbound</button>
        <button className="btn" style={{ fontSize: 11, padding: '7px 14px' }}>Simular +SPIN</button>
      </div>
    </div>
  );
};

// ============================================================================
// PIPELINE COMPLETO — tabela de OPs reais do FM
// ============================================================================
const FM_STAGE_COLORS_BP = {
  'LEAD': '#6366f1', 'INTERESSE': '#8b5cf6', 'EVENTO': '#f97316',
  'DEMO': '#ea580c', 'AG FINANCEIRO': '#16a34a', 'AG DECISAO': '#15803d',
};

const FM_STAGE_CODES = {
  'LEAD': '10', 'INTERESSE': '20', 'EVENTO': '50',
  'DEMO': '65', 'AG DECISAO': '80', 'AG FINANCEIRO': '90',
};

const BPPipelineCompleto = ({ pipelineData, initialStage }) => {
  const [stageFilter, setStageFilter] = React.useState(initialStage || 'todos');
  const [sortBy, setSortBy] = React.useState('valor');

  const records = pipelineData?.records || [];
  const activeRecords = records.filter(r => r.Status !== 'LOST' && r.Stage_Name);
  const wonRecords = records.filter(r => r.Status === 'WON');

  const lostRecords = records.filter(r => r.Status === 'LOST' && r.Stage_Name);

  const stages = React.useMemo(() => {
    const s = new Set(activeRecords.filter(r => r.Status === 'OPEN').map(r => r.Stage_Name));
    return ['todos', ...Array.from(s), ...(wonRecords.length ? ['__WON__'] : []), ...(lostRecords.length ? ['__LOST__'] : [])];
  }, [activeRecords, wonRecords, lostRecords]);

  const filtered = React.useMemo(() => {
    let list = stageFilter === 'todos'
      ? activeRecords
      : stageFilter === '__WON__'
        ? wonRecords
        : stageFilter === '__LOST__'
          ? lostRecords
          : activeRecords.filter(r => r.Stage_Name === stageFilter && r.Status === 'OPEN');
    if (sortBy === 'valor') list = [...list].sort((a, b) => (parseFloat(b.Produto_Valor_K) || 0) - (parseFloat(a.Produto_Valor_K) || 0));
    if (sortBy === 'stage') list = [...list].sort((a, b) => (parseInt(FM_STAGE_CODES[a.Stage_Name] || 999) - parseInt(FM_STAGE_CODES[b.Stage_Name] || 999)) || (a.Stage_Name || '').localeCompare(b.Stage_Name || ''));
    if (sortBy === 'cliente') list = [...list].sort((a, b) => (a.Entidade_Nome || '').localeCompare(b.Entidade_Nome || ''));
    if (sortBy === 'data') list = [...list].sort((a, b) => {
      const dA = parseInt(a.Ano || 0) * 100 + parseInt(a.Mes || 0);
      const dB = parseInt(b.Ano || 0) * 100 + parseInt(b.Mes || 0);
      return dB - dA;
    });
    return list;
  }, [activeRecords, stageFilter, sortBy]);

  const totalValue = filtered.reduce((s, r) => s + Math.round((parseFloat(r.Produto_Valor_K) || 0) * 1000), 0);

  const stageCounts = React.useMemo(() => {
    const c = {};
    for (const r of activeRecords) c[r.Stage_Name] = (c[r.Stage_Name] || 0) + 1;
    return c;
  }, [activeRecords]);

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 12, marginBottom: 12, flexWrap: 'wrap' }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 12 }}>
          <h3 className="font-display" style={{ margin: 0, fontSize: 16, fontWeight: 600, letterSpacing: '-0.01em' }}>Pipeline Completo · Gestor</h3>
          <div style={{ fontSize: 11, color: 'var(--dgd-green-700)', fontWeight: 600, fontFamily: 'var(--dgd-font-mono)' }}>dados reais</div>
          <div style={{ fontSize: 11, color: 'var(--dgd-fg-2)' }}>{filtered.length} OPs · {fmtEur(totalValue)}</div>
        </div>
        <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
          <span style={{ fontSize: 11, color: 'var(--dgd-fg-2)' }}>Ordenar:</span>
          {[{id:'valor',l:'Valor'},{id:'stage',l:'Stage'},{id:'cliente',l:'Cliente'},{id:'data',l:'Data'}].map(s => (
            <button key={s.id} onClick={() => setSortBy(s.id)} style={{
              padding: '4px 10px', borderRadius: 6, fontSize: 11, fontFamily: 'inherit', cursor: 'pointer',
              background: sortBy === s.id ? 'var(--dgd-bg-app)' : 'transparent',
              color: sortBy === s.id ? 'var(--dgd-fg-1)' : 'var(--dgd-fg-2)',
              border: sortBy === s.id ? '1px solid var(--dgd-border-1)' : '1px solid transparent',
            }}>{s.l}</button>
          ))}
        </div>
      </div>

      {/* Stage filter chips */}
      <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 12 }}>
        {stages.map(s => {
          const color = s === '__WON__' ? 'var(--dgd-green-700)' : s === '__LOST__' ? 'var(--dgd-red-700)' : s === 'todos' ? 'var(--dgd-primary-500)' : (FM_STAGE_COLORS_BP[s] || 'var(--dgd-primary-500)');
          const count = s === 'todos' ? activeRecords.length : s === '__WON__' ? wonRecords.length : s === '__LOST__' ? lostRecords.length : (stageCounts[s] || 0);
          return (
            <button key={s} onClick={() => setStageFilter(s)} style={{
              display: 'inline-flex', alignItems: 'center', gap: 5,
              padding: '5px 10px', borderRadius: 6, fontSize: 11, fontFamily: 'inherit', cursor: 'pointer',
              background: stageFilter === s ? `color-mix(in oklch, ${color} 14%, transparent)` : 'transparent',
              color: stageFilter === s ? color : 'var(--dgd-fg-2)',
              border: `1px solid ${stageFilter === s ? `color-mix(in oklch, ${color} 30%, var(--dgd-border-1))` : 'var(--dgd-border-1)'}`,
            }}>
              {s === 'todos' ? 'Todos' : s === '__WON__' ? '✓ WON' : s === '__LOST__' ? '✕ LOST' : (FM_STAGE_CODES[s] ? <><span style={{ opacity: 0.6, fontSize: 10, fontFamily: 'var(--dgd-font-mono)' }}>{FM_STAGE_CODES[s]}</span> · {s}</> : s)}
              <span style={{ fontSize: 10, opacity: 0.7, padding: '0 4px', borderRadius: 3, background: stageFilter === s ? `color-mix(in oklch, ${color} 12%, transparent)` : 'var(--dgd-bg-app)' }}>{count}</span>
            </button>
          );
        })}
      </div>

      {/* Tabela */}
      <div style={{ background: 'var(--dgd-bg-surface)', border: '1px solid var(--dgd-border-1)', borderRadius: 10, overflow: 'hidden' }}>
        <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 12.5 }}>
          <thead>
            <tr style={{ background: 'var(--dgd-bg-app)', borderBottom: '1px solid var(--dgd-border-1)' }}>
              {['Cliente', 'Produto', 'Stage', 'Status', 'Valor', 'Ano/Mês'].map((h, i) => (
                <th key={i} style={{ padding: '9px 12px', textAlign: i > 3 ? 'right' : 'left', fontSize: 10.5, fontWeight: 600, color: 'var(--dgd-fg-2)', letterSpacing: '0.06em', textTransform: 'uppercase', fontFamily: 'var(--dgd-font-mono)' }}>{h}</th>
              ))}
            </tr>
          </thead>
          <tbody>
            {filtered.map((r, i) => {
              const val = Math.round((parseFloat(r.Produto_Valor_K) || 0) * 1000);
              const stageColor = FM_STAGE_COLORS_BP[r.Stage_Name] || 'var(--dgd-primary-500)';
              return (
                <tr key={i} style={{ borderTop: '1px solid var(--dgd-border-2)' }}
                    onMouseEnter={e => e.currentTarget.style.background = 'var(--dgd-bg-app)'}
                    onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                  <td style={{ padding: '10px 12px', maxWidth: 260 }}>
                    <div style={{ fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r.Entidade_Nome || '—'}</div>
                  </td>
                  <td style={{ padding: '10px 12px', color: 'var(--dgd-fg-2)', maxWidth: 160 }}>
                    <div style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r.Produto_Name || '—'}</div>
                  </td>
                  <td style={{ padding: '10px 12px' }}>
                    <span style={{
                      display: 'inline-flex', alignItems: 'center',
                      padding: '2px 8px', borderRadius: 4, fontSize: 10,
                      fontFamily: 'var(--dgd-font-mono)', fontWeight: 700,
                      background: `color-mix(in oklch, ${stageColor} 14%, transparent)`,
                      color: stageColor, whiteSpace: 'nowrap',
                    }}>{r.Stage_Name}</span>
                  </td>
                  <td style={{ padding: '10px 12px' }}>
                    {r.Status === 'WON' && <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 7px', borderRadius: 4, fontSize: 10, fontWeight: 700, fontFamily: 'var(--dgd-font-mono)', background: 'color-mix(in oklch, var(--dgd-green-700) 14%, transparent)', color: 'var(--dgd-green-700)' }}>✓ WON</span>}
                    {r.Status === 'LOST' && <span style={{ display: 'inline-flex', alignItems: 'center', gap: 4, padding: '2px 7px', borderRadius: 4, fontSize: 10, fontWeight: 700, fontFamily: 'var(--dgd-font-mono)', background: 'color-mix(in oklch, var(--dgd-red-700) 14%, transparent)', color: 'var(--dgd-red-700)' }}>✕ LOST</span>}
                  </td>
                  <td style={{ padding: '10px 12px', textAlign: 'right', fontFamily: 'var(--dgd-font-mono)', fontWeight: 600 }}>
                    {val > 0 ? fmtEur(val) : '—'}
                  </td>
                  <td style={{ padding: '10px 12px', textAlign: 'right', color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', fontSize: 11 }}>
                    {r.Ano || ''}{r.Mes ? ` · ${r.Mes}` : ''}
                  </td>
                </tr>
              );
            })}
            {filtered.length === 0 && (
              <tr><td colSpan={6} style={{ padding: 24, textAlign: 'center', color: 'var(--dgd-fg-3)', fontSize: 12 }}>Sem OPs para este filtro.</td></tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
};

// ============================================================================
// SCREEN
// ============================================================================
const ScreenComercialBP = ({ vendedorId, initialStage }) => {
  const { data: pipelineData, loading } = usePipelineBP(vendedorId);
  const isLive = !!pipelineData?.byStage;
  return (
    <div className="dgd-design-system scrollbar" style={{ height: '100%', overflow: 'auto', background: 'var(--dgd-bg-app)' }}>
      <div style={{ padding: '22px 28px 60px', maxWidth: 1360, margin: '0 auto', display: 'flex', flexDirection: 'column', gap: 22 }}>

        <BPHero pipelineData={pipelineData} />

        {/* Pipeline Completo — dados reais FM */}
        {(isLive || loading) && (
          <div>
            {loading && <div style={{ fontSize: 12, color: 'var(--dgd-fg-3)', fontFamily: 'var(--dgd-font-mono)', padding: '12px 0' }}>A carregar pipeline do Gestor…</div>}
            {isLive && <BPPipelineCompleto pipelineData={pipelineData} initialStage={initialStage} />}
          </div>
        )}

        {/* Secções mock (BP Primavera pendente) */}
        <div style={{ opacity: 0.5, pointerEvents: 'none' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12 }}>
            <span style={{ padding: '3px 10px', borderRadius: 999, background: 'color-mix(in oklch, var(--dgd-pumpkin-700) 14%, transparent)', color: 'var(--dgd-pumpkin-700)', fontSize: 10.5, fontWeight: 600 }}>PRIMAVERA PENDENTE · task #25</span>
            <span style={{ fontSize: 11, color: 'var(--dgd-fg-3)' }}>Métricas abaixo são mock — ficarão reais após integração Primavera</span>
          </div>
          <BPMatriz />
        </div>

        <BPKpisDerivados />

        <BPAnaliseDigi />

        {/* Secção plano recuperação */}
        <div>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 12, marginBottom: 10 }}>
            <h3 className="font-display" style={{ margin: 0, fontSize: 16, fontWeight: 600, letterSpacing: '-0.01em' }}>Plano de recuperação</h3>
            <div style={{ fontSize: 11, color: 'var(--dgd-fg-2)' }}>3 alavancas concretas + gap residual · total a recuperar <strong style={{ color: 'var(--dgd-red-700)' }}>{fmtEur(GAP_RECUPERAR)}</strong></div>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
            <PlanoBlocoCarteira />
            <PlanoBlocoOPs />
            <PlanoBlocoProspec />
            <PlanoBlocoGap />
          </div>
        </div>

      </div>
    </div>
  );
};

window.ScreenComercialBP = ScreenComercialBP;
