/* Comercial · Gestor Classic
 * Monitor de vendas Grupo → Família. Dados de classicGrupos (vp_snapshots).
 */

// ── Helpers ───────────────────────────────────────────────────────────────────
// Tabela: abreviado (1,2M€ / 45k€)
const _gc_fv = n => {
  if (n == null || isNaN(n)) return '—';
  const abs = Math.abs(n);
  if (abs >= 1e6) return (n / 1e6).toFixed(2).replace('.', ',') + 'M€';
  if (abs >= 1e4) return (n / 1e3).toFixed(0) + 'k€';
  if (abs >= 1e3) return (n / 1e3).toFixed(1) + 'k€';
  return Math.round(n) + '€';
};
// Painel: número completo pt-PT (1 911 397)
const _gc_fn = n => {
  if (n == null || isNaN(n)) return '—';
  return Math.round(n).toLocaleString('pt-PT');
};
const _gc_pct = (n, sign = true) => {
  if (n == null) return '—';
  return (sign && n >= 0 ? '+' : '') + n.toFixed(1) + '%';
};
const _gc_pp = n => n == null ? '—' : (n >= 0 ? '+' : '') + n.toFixed(1) + 'pp';
const _gc_vc = n => n == null ? 'inherit' : n >= 0 ? '#8cb700' : '#d93025';
const _gc_col26 = (v26, v25) => v26 > v25 ? { color: '#8cb700', fontWeight: 700 } : v26 < v25 ? { color: '#d93025', fontWeight: 700 } : {};
const _gc_M = ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez'];

// ── CV Badge (tabela) ─────────────────────────────────────────────────────────
const GcCvBadge = ({ cv }) => {
  if (cv == null) return <span style={{ color: 'var(--text-dim)', fontSize: '0.75rem' }}>—</span>;
  const isReg = cv < 40, isSaz = cv < 80;
  const color = isReg ? '#8cb700' : isSaz ? '#f59e0b' : '#d93025';
  const label = isReg ? 'Regular' : isSaz ? 'Sazonal' : 'Irregular';
  return (
    <span style={{
      display: 'inline-flex', alignItems: 'center', gap: 4,
      fontSize: '0.7rem', fontWeight: 600, padding: '2px 7px', borderRadius: 4,
      background: color + '1a', color, border: `1px solid ${color}40`
    }}>● {label}</span>
  );
};

// ── Var badge (painel) ────────────────────────────────────────────────────────
const GcVarBadge = ({ v26, v25 }) => {
  if (v25 === 0 && v26 > 0) return <span style={{ fontSize: '0.7rem', background: '#1a73e820', color: '#1a73e8', borderRadius: 3, padding: '1px 5px', fontWeight: 700 }}>NOVO</span>;
  if (v26 === 0 && v25 > 0) return <span style={{ fontSize: '0.7rem', background: '#d9302520', color: '#d93025', borderRadius: 3, padding: '1px 5px', fontWeight: 700 }}>PERDIDO</span>;
  const pct = v25 !== 0 ? (v26 - v25) / Math.abs(v25) * 100 : 0;
  const col = pct >= 0 ? '#8cb700' : '#d93025';
  return <span style={{ color: col, fontWeight: 700 }}>{pct >= 0 ? '+' : ''}{pct.toFixed(1)}%</span>;
};

// ── KPI card (painel) ─────────────────────────────────────────────────────────
const GcKpiCard = ({ label, value, sub, topColor, valueColor }) => (
  <div style={{
    background: 'var(--bg-hover)', border: '1px solid var(--border)', borderRadius: 10,
    padding: '12px 16px', flex: 1, minWidth: 110, position: 'relative', overflow: 'hidden'
  }}>
    <div style={{
      position: 'absolute', top: 0, left: 0, right: 0, height: 3,
      background: topColor || 'var(--border)'
    }} />
    <div style={{ fontSize: '0.65rem', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--text-dim)', marginBottom: 5 }}>
      {label}
    </div>
    <div style={{ fontSize: '1.2rem', fontWeight: 800, color: valueColor || topColor || 'var(--text)', letterSpacing: '-0.02em' }}>
      {value}
    </div>
    {sub && <div style={{ fontSize: '0.68rem', color: 'var(--text-dim)', marginTop: 3 }}>{sub}</div>}
  </div>
);

// ── Month chart (SVG) ─────────────────────────────────────────────────────────
const GcMonthChart = ({ mensal }) => {
  const hasData = mensal && mensal.some(m => m.y25 > 0 || m.y26 > 0);
  if (!hasData) return <div style={{ color: 'var(--text-dim)', padding: '24px', textAlign: 'center' }}>Sem dados mensais.</div>;
  const W = 580, H = 100, PX = 6, PY = 8;
  const max = Math.max(...mensal.map(m => Math.max(m.y25 || 0, m.y26 || 0)), 1);
  const bw = (W - PX * 2) / 12;
  const bar = 9, gap = 2;
  return (
    <svg viewBox={`0 0 ${W} ${H + 28}`} style={{ width: '100%', maxWidth: W }}>
      {mensal.map((m, i) => {
        const x = PX + i * bw;
        const h25 = Math.max(2, ((m.y25 || 0) / max) * H);
        const h26 = Math.max(2, ((m.y26 || 0) / max) * H);
        return (
          <g key={m.m}>
            <rect x={x + 2} y={PY + H - h25} width={bar} height={h25} fill="#92a6b3" opacity={0.5} rx={2} />
            <rect x={x + 2 + bar + gap} y={PY + H - h26} width={bar} height={h26} fill="#8cb700" opacity={0.8} rx={2} />
            <text x={x + bw / 2} y={PY + H + 16} textAnchor="middle" fill="var(--text-dim)" fontSize={9}>{_gc_M[i]}</text>
          </g>
        );
      })}
      <rect x={W - 88} y={4} width={8} height={7} fill="#92a6b3" opacity={0.5} rx={1} />
      <text x={W - 78} y={11} fill="var(--text-muted)" fontSize={9}>2025</text>
      <rect x={W - 48} y={4} width={8} height={7} fill="#8cb700" opacity={0.8} rx={1} />
      <text x={W - 38} y={11} fill="var(--text-muted)" fontSize={9}>2026</text>
    </svg>
  );
};

// ── Analysis Panel ────────────────────────────────────────────────────────────
const GcAnalysisPanel = ({ fam, grupo, drillData, allDrillData, activeCliente, onClose, panelRef }) => {
  const [tab, setTab] = React.useState('resumo');
  const [alertSort, setAlertSort] = React.useState({ key: 'v25', dir: 'desc' });
  const [artSort,   setArtSort]   = React.useState({ key: 'v26', dir: 'desc' });
  const [cliSort,   setCliSort]   = React.useState({ key: 'v26', dir: 'desc' });

  const clients = drillData || [];
  const cliData = activeCliente ? (clients[0] || null) : null; // single client in Modo Cliente

  // Aggregate artigos from drill
  const artigoMap = {};
  clients.forEach(cli => {
    (cli.items || []).forEach(it => {
      if (!artigoMap[it.a]) artigoMap[it.a] = { cod: it.a, desc: it.d, v26: 0, v25: 0, m26: 0, m25: 0 };
      artigoMap[it.a].v26 += it.v26 || 0;
      artigoMap[it.a].v25 += it.v25 || 0;
      artigoMap[it.a].m26 += (it.v26 || 0) * (it.pm26 || 0) / 100;
      artigoMap[it.a].m25 += (it.v25 || 0) * (it.pm25 || 0) / 100;
    });
  });
  const topArtigos = Object.values(artigoMap)
    .sort((a, b) => b.v26 - a.v26)
    .slice(0, 30)
    .map(a => ({
      ...a,
      vv: a.v25 > 0 ? (a.v26 - a.v25) / a.v25 * 100 : (a.v26 > 0 ? 100 : 0),
      pm26: a.v26 > 0 ? a.m26 / a.v26 * 100 : 0,
      pm25: a.v25 > 0 ? a.m25 / a.v25 * 100 : 0,
    }))
    .map(a => ({ ...a, vm: a.pm26 - a.pm25, mvv: a.m25 > 0 ? (a.m26 - a.m25) / a.m25 * 100 : (a.m26 > 0 ? 100 : 0) }));

  const topClientes = [...clients].sort((a, b) => (b.v26 || 0) - (a.v26 || 0)).slice(0, 30)
    .map(c => ({ ...c, pm26: c.pm26 || 0, pm25: c.pm25 || 0, m26: (c.v26 || 0) * (c.pm26 || 0) / 100, m25: (c.v25 || 0) * (c.pm25 || 0) / 100 }));

  const novos = clients.filter(c => (c.v25 || 0) === 0 && (c.v26 || 0) > 0);
  const perdidos = clients.filter(c => (c.v26 || 0) === 0 && (c.v25 || 0) > 0);

  const alertas = [];
  clients.forEach(cli => {
    (cli.items || []).forEach(it => {
      if ((it.v25 || 0) >= 300 && (it.r25cnt || 0) >= 2 && (it.v26 || 0) < (it.v25 || 0) * 0.5) {
        alertas.push({
          cliCode: cli.e, cliName: cli.n, artCode: it.a, artName: it.d,
          v25: it.v25, v26: it.v26 || 0,
          drop: it.v25 > 0 ? ((it.v26 || 0) - it.v25) / it.v25 * 100 : -100
        });
      }
    });
  });
  alertas.sort((a, b) => a.drop - b.drop);

  const TABS = activeCliente ? [
    { id: 'resumo',   label: 'Resumo' },
    { id: 'artigos',  label: 'Top Artigos' },
    { id: 'alertas',  label: `Alertas ⚠${alertas.length > 0 ? ' (' + alertas.length + ')' : ''}` },
    { id: 'mensal',   label: 'Evolução Mensal' },
    { id: 'previsao', label: 'Previsão' },
  ] : [
    { id: 'resumo',   label: 'Resumo' },
    { id: 'artigos',  label: 'Top Artigos' },
    { id: 'clientes', label: 'Top Clientes' },
    { id: 'novos',    label: 'Novos/Perdidos' },
    { id: 'alertas',  label: `Alertas ⚠${alertas.length > 0 ? ' (' + alertas.length + ')' : ''}` },
    { id: 'mensal',   label: 'Evolução Mensal' },
    { id: 'previsao', label: 'Previsão' },
  ];

  // Resumo values: client-specific in Modo Cliente, family totals otherwise
  const rV26  = cliData ? cliData.v26 : fam.v26;
  const rV25  = cliData ? cliData.v25 : fam.v25;
  const rM26  = cliData ? cliData.v26 * (cliData.pm26 || 0) / 100 : fam.m26;
  const rM25  = cliData ? cliData.v25 * (cliData.pm25 || 0) / 100 : fam.m25;
  const rPm26 = cliData ? (cliData.pm26 || 0) : fam.pm26;
  const rPm25 = cliData ? (cliData.pm25 || 0) : fam.pm25;
  const rVv   = cliData ? (cliData.vp  || 0)  : fam.vv;
  const pesoFam  = cliData && fam.v26 > 0 ? (cliData.v26 / fam.v26 * 100) : null;
  const rankFam  = cliData && allDrillData ? (allDrillData.findIndex(c => c.e === activeCliente.e) + 1) : null;
  const totalFamClis = allDrillData ? allDrillData.length : 0;

  const irr = fam.cv;
  const irrLabel = irr == null ? '—' : irr < 40 ? 'Regular' : irr < 80 ? 'Sazonal' : 'Irregular';
  const irrColor = irr == null ? 'var(--text-dim)' : irr < 40 ? '#8cb700' : irr < 80 ? '#f59e0b' : '#d93025';
  const vvColor = _gc_vc(rVv);

  // Table styles inside panel
  const PTH = {
    padding: '6px 8px', fontSize: '0.68rem', fontWeight: 700, textTransform: 'uppercase',
    letterSpacing: '0.03em', color: 'var(--text-dim)', whiteSpace: 'nowrap',
    borderBottom: '2px solid var(--border)', background: 'var(--surface-muted)'
  };
  const PTD = { padding: '6px 8px', fontSize: '0.78rem', borderBottom: '1px solid var(--border)', color: 'var(--text)', verticalAlign: 'middle' };
  const PTR = { ...PTD, textAlign: 'right', fontVariantNumeric: 'tabular-nums' };

  const currentMonth = new Date().getMonth() + 1;
  const gf = fam.v25 > 0 ? fam.v26 / fam.v25 : 1;

  return (
    <div ref={panelRef} style={{
      borderTop: '2px solid #8cb700',
      background: 'var(--surface-muted)',
      marginTop: 0
    }}>
      {/* Panel header */}
      <div style={{
        padding: '10px 18px', background: 'var(--bg-hover)',
        borderBottom: '1px solid var(--border)',
        display: 'flex', alignItems: 'center', justifyContent: 'space-between',
        flexWrap: 'wrap', gap: 8
      }}>
        {/* Breadcrumb */}
        <div style={{ fontSize: '0.75rem', fontWeight: 600, color: 'var(--text-muted)', display: 'flex', alignItems: 'center', gap: 4, flexWrap: 'wrap' }}>
          <span style={{ color: 'var(--text-dim)' }}>{grupo}</span>
          <span style={{ opacity: 0.4 }}> › </span>
          <span style={{ color: '#8cb700', fontWeight: 800 }}>{fam.fc}</span>
          <span style={{ color: 'var(--text)' }}>{fam.fd !== fam.fc ? ' ' + fam.fd : ''}</span>
          {activeCliente && (<>
            <span style={{ opacity: 0.4 }}> › </span>
            <span style={{ color: '#1a73e8', fontWeight: 800 }}>{activeCliente.n}</span>
            <span style={{ fontSize: '0.68rem', color: 'var(--text-dim)' }}>({activeCliente.e})</span>
          </>)}
        </div>
        {/* Tabs + close */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 5, flexWrap: 'wrap' }}>
          {TABS.map(t => (
            <button key={t.id}
              onClick={() => setTab(t.id)}
              style={{
                padding: '4px 10px', borderRadius: 6, fontSize: '0.72rem', cursor: 'pointer',
                fontWeight: tab === t.id ? 700 : 500,
                background: tab === t.id ? '#8cb700' : 'var(--surface-muted)',
                color: tab === t.id ? '#fff' : 'var(--text-dim)',
                border: `1px solid ${tab === t.id ? '#8cb700' : 'var(--border)'}`,
                whiteSpace: 'nowrap'
              }}>
              {t.label}
            </button>
          ))}
          <button onClick={onClose} style={{
            padding: '4px 10px', borderRadius: 6, fontSize: '0.72rem', cursor: 'pointer',
            background: 'var(--surface-muted)', color: 'var(--text-muted)',
            border: '1px solid var(--border)', fontWeight: 500
          }}>✕ Fechar</button>
        </div>
      </div>

      {/* Content */}
      <div style={{ maxHeight: '65vh', overflowY: 'auto', padding: '16px 18px' }}>

        {/* RESUMO */}
        {tab === 'resumo' && (
          <div>
            {/* 5 KPI cards */}
            <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginBottom: 14 }}>
              <GcKpiCard
                label="V. Líq. 2026"
                value={_gc_fn(rV26) + ' €'}
                sub={_gc_fn(rV25) + ' € em 2025'}
                topColor="#8cb700"
              />
              <GcKpiCard
                label="Variação"
                value={_gc_pct(rVv)}
                sub=""
                topColor={vvColor}
              />
              <GcKpiCard
                label="V. Marg. 2026"
                value={_gc_fn(rM26) + ' €'}
                sub={_gc_fn(rM25) + ' € em 2025'}
                topColor="#00897b"
              />
              <GcKpiCard
                label="% Mg 2026"
                value={_gc_pct(rPm26, false)}
                sub={_gc_pct(rPm25, false) + ' em 2025'}
                topColor={rPm26 >= rPm25 ? '#8cb700' : '#d93025'}
              />
              {activeCliente ? null : (
                <GcKpiCard
                  label="Irregularidade"
                  value={irr != null ? irr.toFixed(1) : '—'}
                  sub={irrLabel}
                  topColor={irrColor}
                />
              )}
            </div>

            {/* Modo Cliente — segunda linha: Peso + Ranking + Comercial(is) */}
            {activeCliente && (
              <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginBottom: 14 }}>
                <GcKpiCard
                  label="Peso na Família"
                  value={pesoFam != null ? pesoFam.toFixed(1) + '%' : '—'}
                  sub={'do total da família em 2026'}
                  topColor="#1a73e8"
                />
                <GcKpiCard
                  label="Ranking na Família"
                  value={rankFam ? '#' + rankFam : '—'}
                  sub={totalFamClis ? 'de ' + totalFamClis + ' clientes activos' : ''}
                  topColor="#7b1fa2"
                />
                {cliData?.vends?.length > 0 && (
                  <div style={{
                    background: 'var(--surface-muted)', border: '1px solid var(--border)',
                    borderRadius: 10, padding: '14px 18px', flex: 1, minWidth: 180
                  }}>
                    <div style={{ fontSize: '0.65rem', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--text-dim)', marginBottom: 10 }}>
                      Comercial(is)
                    </div>
                    <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
                      {cliData.vends.map(v => (
                        <span key={v} style={{
                          background: '#7b1fa2', color: '#fff',
                          borderRadius: 20, padding: '3px 10px', fontSize: '0.75rem', fontWeight: 600
                        }}>{v}</span>
                      ))}
                    </div>
                  </div>
                )}
              </div>
            )}

            {/* Concentração + Alertas */}
            <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', marginBottom: 14 }}>
              {!activeCliente ? (
              <div style={{
                background: 'var(--bg-hover)', border: '1px solid var(--border)',
                borderRadius: 10, padding: '12px 16px', flex: 1, minWidth: 200
              }}>
                <div style={{ fontSize: '0.65rem', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.05em', color: 'var(--text-dim)', marginBottom: 8 }}>
                  Concentração de Clientes (% V. 2026)
                </div>
                <div style={{ display: 'flex', gap: 20 }}>
                  {[['Top 1', fam.conc?.top1], ['Top 3', fam.conc?.top3], ['Top 5', fam.conc?.top5]].map(([label, val]) => (
                    <div key={label}>
                      <div style={{ fontSize: '0.68rem', color: 'var(--text-dim)' }}>{label}</div>
                      <div style={{ fontSize: '1.1rem', fontWeight: 800, color: '#8cb700' }}>
                        {val != null ? val.toFixed(1) + '%' : '—'}
                      </div>
                    </div>
                  ))}
                </div>
              </div>
              ) : null}

              {alertas.length > 0 ? (
                <div
                  onClick={() => setTab('alertas')}
                  style={{
                    background: 'rgba(217,48,37,0.06)', border: '1px solid #d93025',
                    borderRadius: 10, padding: '12px 16px', flex: 1, minWidth: 180, cursor: 'pointer'
                  }}>
                  <div style={{ fontSize: '0.65rem', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.05em', color: '#d93025', marginBottom: 4 }}>
                    ⚠ Alertas Comerciais
                  </div>
                  <div style={{ fontSize: '1.5rem', fontWeight: 800, color: '#d93025' }}>{alertas.length}</div>
                  <div style={{ fontSize: '0.7rem', color: 'var(--text-dim)' }}>clientes com queda &gt;50%</div>
                </div>
              ) : (
                <div style={{
                  background: 'rgba(140,183,0,0.07)', border: '1px solid #8cb700',
                  borderRadius: 10, padding: '12px 16px', flex: 1, minWidth: 180
                }}>
                  <div style={{ fontSize: '0.78rem', fontWeight: 700, color: '#8cb700' }}>✓ Sem alertas comerciais</div>
                </div>
              )}
            </div>

            {/* Top 3 Artigos */}
            {topArtigos.length > 0 && (
              <div style={{ marginBottom: 14 }}>
                <div style={{ fontSize: '0.78rem', fontWeight: 700, color: 'var(--text-muted)', marginBottom: 6 }}>Top 3 Artigos</div>
                <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                  <thead>
                    <tr>
                      {['Cód.', 'Descrição', 'V. 2025', 'V. 2026', 'Var%'].map((h, i) => (
                        <th key={h} style={{ ...PTH, textAlign: i >= 2 ? 'right' : 'left' }}>{h}</th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {topArtigos.slice(0, 3).map(a => (
                      <tr key={a.cod}>
                        <td style={{ ...PTD, fontSize: '0.68rem', color: 'var(--text-dim)', fontWeight: 700, whiteSpace: 'nowrap' }}>{a.cod}</td>
                        <td style={PTD}>{a.desc}</td>
                        <td style={PTR}>{_gc_fn(a.v25)}</td>
                        <td style={{ ...PTR, ..._gc_col26(a.v26, a.v25) }}>{_gc_fn(a.v26)}</td>
                        <td style={PTR}><GcVarBadge v26={a.v26} v25={a.v25} /></td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}

            {/* Top 3 Clientes — oculto em Modo Cliente */}
            {!activeCliente && topClientes.length > 0 && (
              <div>
                <div style={{ fontSize: '0.78rem', fontWeight: 700, color: 'var(--text-muted)', marginBottom: 6 }}>Top 3 Clientes</div>
                <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                  <thead>
                    <tr>
                      {['Cód.', 'Nome', 'V. 2025', 'V. 2026', 'Var%'].map((h, i) => (
                        <th key={h} style={{ ...PTH, textAlign: i >= 2 ? 'right' : 'left' }}>{h}</th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {topClientes.slice(0, 3).map(c => (
                      <tr key={c.e}>
                        <td style={{ ...PTD, fontSize: '0.68rem', color: 'var(--text-dim)', fontWeight: 700, whiteSpace: 'nowrap' }}>{c.e}</td>
                        <td style={PTD}>{c.n}</td>
                        <td style={PTR}>{_gc_fn(c.v25)}</td>
                        <td style={{ ...PTR, ..._gc_col26(c.v26, c.v25) }}>{_gc_fn(c.v26)}</td>
                        <td style={PTR}><GcVarBadge v26={c.v26} v25={c.v25} /></td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        )}

        {/* TOP ARTIGOS */}
        {tab === 'artigos' && (
          <div style={{ overflowX: 'auto' }}>
            {topArtigos.length === 0
              ? <div style={{ color: 'var(--text-dim)', padding: 24, textAlign: 'center' }}>Sem dados de artigos.</div>
              : (() => {
                const ACOLS = [
                  { key: 'cod',  label: 'Artigo',     right: false },
                  { key: 'desc', label: 'Descrição',  right: false },
                  { key: 'v25',  label: 'V.Liq 2025', right: true  },
                  { key: 'v26',  label: 'V.Liq 2026', right: true  },
                  { key: 'vv',   label: 'Cres%',      right: true  },
                  { key: 'm25',  label: 'V.Marg 2025',right: true  },
                  { key: 'm26',  label: 'V.Marg 2026',right: true  },
                  { key: 'mvv',  label: 'Cres% Mg',   right: true  },
                  { key: 'pm25', label: '%Mg 2025',   right: true  },
                  { key: 'pm26', label: '%Mg 2026',   right: true  },
                  { key: 'vm',   label: 'Δpp',        right: true  },
                ];
                const toggle = key => setArtSort(s => ({ key, dir: s.key === key && s.dir === 'desc' ? 'asc' : 'desc' }));
                const sorted = [...topArtigos].sort((a, b) => {
                  const k = artSort.key;
                  const va = (k === 'cod' || k === 'desc') ? (a[k]||'').toLowerCase() : (a[k] || 0);
                  const vb = (k === 'cod' || k === 'desc') ? (b[k]||'').toLowerCase() : (b[k] || 0);
                  return (va < vb ? -1 : va > vb ? 1 : 0) * (artSort.dir === 'asc' ? 1 : -1);
                });
                return (
                  <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                    <thead><tr>
                      {ACOLS.map(col => (
                        <th key={col.key} onClick={() => toggle(col.key)}
                          style={{ ...PTH, textAlign: col.right ? 'right' : 'left', cursor: 'pointer', userSelect: 'none',
                            color: artSort.key === col.key ? '#8cb700' : undefined }}>
                          {col.label}{artSort.key === col.key ? (artSort.dir === 'desc' ? ' ▼' : ' ▲') : ''}
                        </th>
                      ))}
                    </tr></thead>
                    <tbody>
                      {sorted.map(a => (
                        <tr key={a.cod}>
                          <td style={{ ...PTD, fontSize: '0.68rem', color: 'var(--text-dim)', fontWeight: 700 }}>{a.cod}</td>
                          <td style={PTD}>{a.desc}</td>
                          <td style={PTR}>{_gc_fn(a.v25)}</td>
                          <td style={{ ...PTR, ..._gc_col26(a.v26, a.v25) }}>{_gc_fn(a.v26)}</td>
                          <td style={PTR}><GcVarBadge v26={a.v26} v25={a.v25} /></td>
                          <td style={PTR}>{_gc_fn(a.m25)}</td>
                          <td style={{ ...PTR, ..._gc_col26(a.m26, a.m25) }}>{_gc_fn(a.m26)}</td>
                          <td style={PTR}><GcVarBadge v26={a.m26} v25={a.m25} /></td>
                          <td style={PTR}>{a.pm25.toFixed(1)}%</td>
                          <td style={{ ...PTR, ..._gc_col26(a.pm26, a.pm25) }}>{a.pm26.toFixed(1)}%</td>
                          <td style={{ ...PTR, color: _gc_vc(a.vm), fontWeight: 700 }}>{_gc_pp(a.vm)}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                );
              })()}
          </div>
        )}

        {/* TOP CLIENTES */}
        {tab === 'clientes' && (
          <div style={{ overflowX: 'auto' }}>
            {topClientes.length === 0
              ? <div style={{ color: 'var(--text-dim)', padding: 24, textAlign: 'center' }}>Sem dados de clientes.</div>
              : (() => {
                const CCOLS = [
                  { key: 'e',    label: 'Cód.',       right: false },
                  { key: 'n',    label: 'Nome',        right: false },
                  { key: 'v25',  label: 'V.Liq 2025', right: true  },
                  { key: 'v26',  label: 'V.Liq 2026', right: true  },
                  { key: 'vp',   label: 'Cres%',      right: true  },
                  { key: 'm25',  label: 'V.Marg 2025',right: true  },
                  { key: 'm26',  label: 'V.Marg 2026',right: true  },
                  { key: 'pm26', label: 'Mg% 2026',   right: true  },
                ];
                const toggle = key => setCliSort(s => ({ key, dir: s.key === key && s.dir === 'desc' ? 'asc' : 'desc' }));
                const sorted = [...topClientes].sort((a, b) => {
                  const k = cliSort.key;
                  const va = (k === 'e' || k === 'n') ? (a[k]||'').toLowerCase() : (a[k] || 0);
                  const vb = (k === 'e' || k === 'n') ? (b[k]||'').toLowerCase() : (b[k] || 0);
                  return (va < vb ? -1 : va > vb ? 1 : 0) * (cliSort.dir === 'asc' ? 1 : -1);
                });
                return (
                  <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                    <thead><tr>
                      {CCOLS.map(col => (
                        <th key={col.key} onClick={() => toggle(col.key)}
                          style={{ ...PTH, textAlign: col.right ? 'right' : 'left', cursor: 'pointer', userSelect: 'none',
                            color: cliSort.key === col.key ? '#8cb700' : undefined }}>
                          {col.label}{cliSort.key === col.key ? (cliSort.dir === 'desc' ? ' ▼' : ' ▲') : ''}
                        </th>
                      ))}
                    </tr></thead>
                    <tbody>
                      {sorted.map(c => (
                        <tr key={c.e}>
                          <td style={{ ...PTD, fontSize: '0.68rem', color: 'var(--text-dim)', fontWeight: 700 }}>{c.e}</td>
                          <td style={PTD}>{c.n}</td>
                          <td style={PTR}>{_gc_fn(c.v25)}</td>
                          <td style={{ ...PTR, ..._gc_col26(c.v26, c.v25) }}>{_gc_fn(c.v26)}</td>
                          <td style={PTR}><GcVarBadge v26={c.v26} v25={c.v25} /></td>
                          <td style={PTR}>{_gc_fn(c.m25)}</td>
                          <td style={{ ...PTR, ..._gc_col26(c.m26, c.m25) }}>{_gc_fn(c.m26)}</td>
                          <td style={PTR}>{c.pm26.toFixed(1)}%</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                );
              })()}
          </div>
        )}

        {/* NOVOS / PERDIDOS */}
        {tab === 'novos' && (
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 16 }}>
            <div>
              <div style={{ fontSize: '0.72rem', fontWeight: 700, color: '#8cb700', marginBottom: 8, textTransform: 'uppercase', letterSpacing: '0.04em' }}>
                Novos ({novos.length}) — só 2026
              </div>
              {novos.length === 0
                ? <div style={{ color: 'var(--text-dim)', fontSize: '0.8rem' }}>Nenhum cliente novo.</div>
                : novos.map(c => (
                  <div key={c.e} style={{ background: 'var(--bg-hover)', borderRadius: 6, padding: '8px 10px', marginBottom: 5, border: '1px solid #8cb70025' }}>
                    <div style={{ fontWeight: 600, fontSize: '0.8rem' }}>{c.n || c.e}</div>
                    <div style={{ fontSize: '0.7rem', color: 'var(--text-dim)' }}>{c.e} · {_gc_fn(c.v26)} €</div>
                  </div>
                ))}
            </div>
            <div>
              <div style={{ fontSize: '0.72rem', fontWeight: 700, color: '#d93025', marginBottom: 8, textTransform: 'uppercase', letterSpacing: '0.04em' }}>
                Perdidos ({perdidos.length}) — compravam em 2025
              </div>
              {perdidos.length === 0
                ? <div style={{ color: 'var(--text-dim)', fontSize: '0.8rem' }}>Nenhum cliente perdido.</div>
                : perdidos.map(c => (
                  <div key={c.e} style={{ background: 'var(--bg-hover)', borderRadius: 6, padding: '8px 10px', marginBottom: 5, border: '1px solid #d9302525' }}>
                    <div style={{ fontWeight: 600, fontSize: '0.8rem' }}>{c.n || c.e}</div>
                    <div style={{ fontSize: '0.7rem', color: 'var(--text-dim)' }}>{c.e} · {_gc_fn(c.v25)} € em 2025</div>
                  </div>
                ))}
            </div>
          </div>
        )}

        {/* ALERTAS */}
        {tab === 'alertas' && (
          <div>
            {alertas.length === 0
              ? <div style={{ color: 'var(--text-dim)', padding: 24, textAlign: 'center' }}>Sem alertas — nenhum artigo com queda &gt;50% (mín. 300€, ≥2 meses em 2025).</div>
              : (
                <>
                  <div style={{ fontSize: '0.72rem', color: 'var(--text-dim)', marginBottom: 10 }}>
                    {alertas.length} alerta(s) — artigo×cliente regular (≥2 meses, ≥300€ em 2025) com queda &gt;50%
                  </div>
                  {(() => {
                    const ACOLS = [
                      { key: 'cli',  label: 'Cliente', right: false },
                      { key: 'art',  label: 'Artigo',  right: false },
                      { key: 'v25',  label: '2025',    right: true  },
                      { key: 'v26',  label: '2026',    right: true  },
                      { key: 'drop', label: 'Queda',   right: true  },
                    ];
                    const sortFn = (a, b) => {
                      let va, vb;
                      if (alertSort.key === 'cli')  { va = (a.cliName||a.cliCode||'').toLowerCase(); vb = (b.cliName||b.cliCode||'').toLowerCase(); }
                      else if (alertSort.key === 'art') { va = (a.artName||a.artCode||'').toLowerCase(); vb = (b.artName||b.artCode||'').toLowerCase(); }
                      else { va = a[alertSort.key] || 0; vb = b[alertSort.key] || 0; }
                      if (va < vb) return alertSort.dir === 'asc' ? -1 : 1;
                      if (va > vb) return alertSort.dir === 'asc' ? 1 : -1;
                      return 0;
                    };
                    const sorted = [...alertas].sort(sortFn);
                    const toggleSort = key => setAlertSort(s => ({ key, dir: s.key === key && s.dir === 'desc' ? 'asc' : 'desc' }));
                    return (
                      <table style={{ width: '100%', borderCollapse: 'collapse' }}>
                        <thead>
                          <tr>
                            {ACOLS.map(col => (
                              <th key={col.key} onClick={() => toggleSort(col.key)}
                                style={{ ...PTH, textAlign: col.right ? 'right' : 'left', cursor: 'pointer', userSelect: 'none',
                                  color: alertSort.key === col.key ? '#8cb700' : undefined }}>
                                {col.label}{alertSort.key === col.key ? (alertSort.dir === 'desc' ? ' ▼' : ' ▲') : ''}
                              </th>
                            ))}
                          </tr>
                        </thead>
                        <tbody>
                          {sorted.map((al, i) => (
                            <tr key={i}>
                              <td style={PTD}>
                                <div style={{ fontWeight: 600, fontSize: '0.78rem' }}>{al.cliName || al.cliCode}</div>
                                <div style={{ fontSize: '0.68rem', color: 'var(--text-dim)' }}>{al.cliCode}</div>
                              </td>
                              <td style={PTD}>
                                <div style={{ fontSize: '0.78rem' }}>{al.artName || al.artCode}</div>
                                <div style={{ fontSize: '0.68rem', color: 'var(--text-dim)' }}>{al.artCode}</div>
                              </td>
                              <td style={PTR}>{_gc_fn(al.v25)}</td>
                              <td style={{ ...PTR, color: '#d93025', fontWeight: 700 }}>
                                {al.v26 === 0 ? '0' : _gc_fn(al.v26)}
                              </td>
                              <td style={{ ...PTR, color: '#d93025', fontWeight: 800 }}>{_gc_pct(al.drop)}</td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    );
                  })()}
                </>
              )}
          </div>
        )}

        {/* EVOLUÇÃO MENSAL */}
        {tab === 'mensal' && (
          <div>
            <GcMonthChart mensal={fam.mensal} />
            <div style={{ display: 'flex', flexWrap: 'wrap', gap: 5, marginTop: 12 }}>
              {(fam.mensal || []).map(m => (
                <div key={m.m} style={{
                  background: 'var(--bg-hover)', borderRadius: 5, padding: '5px 9px',
                  border: '1px solid var(--border)', textAlign: 'center', minWidth: 66
                }}>
                  <div style={{ fontSize: '0.68rem', color: 'var(--text-dim)' }}>{_gc_M[m.m - 1]}</div>
                  <div style={{ fontSize: '0.7rem', color: 'var(--text-muted)' }}>{_gc_fn(m.y25)}</div>
                  <div style={{ fontSize: '0.76rem', fontWeight: 700, color: m.y26 > 0 ? '#8cb700' : 'var(--text-dim)' }}>
                    {m.y26 > 0 ? _gc_fn(m.y26) : '—'}
                  </div>
                </div>
              ))}
            </div>
          </div>
        )}

        {/* PREVISÃO */}
        {tab === 'previsao' && (() => {
          // ── Modo Cliente: previsão híbrida ─────────────────────────────────
          if (activeCliente && cliData) {
            const cliMen = cliData.men || [];       // {m, y25 YTD, y26}
            const men25full = cliData.men25full || []; // {m, y25 ano completo}
            const gfRaw = cliData.v25 > 0 ? cliData.v26 / cliData.v25 : 1;
            const gfCapped = Math.min(3.0, Math.max(0.3, gfRaw));
            // Ritmo = total v26 ÷ meses elapsed (não meses com dados)
            const avgRhythm = currentMonth > 0 ? cliData.v26 / currentMonth : 0;
            // Sazonalidade da família (full 2025)
            const famBase25 = fam.mensal25full || fam.mensal || [];
            const famVals25 = famBase25.map(m => m.y25 || 0).filter(v => v > 0);
            const famAvg25  = famVals25.length > 0 ? famVals25.reduce((s, v) => s + v, 0) / famVals25.length : 1;
            // Base 2025 ano completo = soma de men25full (todos os 12 meses)
            const base25Total = men25full.reduce((s, m) => s + (m.y25 || 0), 0);
            const actualSet = new Set(cliMen.filter(m => m.y26 > 0).map(m => m.m));
            const futureMonths = Array.from({ length: 12 }, (_, i) => i + 1)
              .filter(m => !actualSet.has(m) && m > currentMonth);
            const rows = futureMonths.map(m => {
              const y25cli = (men25full.find(x => x.m === m)?.y25 || 0);
              const famW   = famAvg25 > 0 ? (famBase25.find(x => x.m === m)?.y25 || 0) / famAvg25 : 1;
              if (y25cli > 0) {
                // Híbrido: mês com histórico 2025 → base × crescimento
                return { m, y25: y25cli, est: y25cli * gfCapped, type: 'base' };
              } else {
                // Sem histórico → ritmo × sazonalidade família
                return { m, y25: 0, est: avgRhythm * (famAvg25 > 0 ? famW : 1), type: 'ritmo' };
              }
            });
            const futureEstTotal = rows.reduce((s, r) => s + r.est, 0);
            const estTotal = cliData.v26 + futureEstTotal;
            const cliDelta = estTotal - base25Total;
            const ytdLabel = `Jan–${_gc_M[currentMonth - 1]}`;
            const hasBase = rows.some(r => r.type === 'base');
            const metodoTxt = hasBase
              ? `Estimativa híbrida — meses com histórico 2025: base × crescimento YTD (${gfCapped.toFixed(2)}x); meses sem histórico: ritmo médio 2026 (${_gc_fn(avgRhythm)} €/mês) × sazonalidade da família.`
              : `Estimativa = ritmo médio 2026 (${_gc_fn(avgRhythm)} €/mês) × sazonalidade da família. Crescimento YTD: ${gfCapped.toFixed(2)}x.`;
            return (
              <div>
                <div style={{
                  background: 'var(--bg-hover)', border: '1px solid var(--border)',
                  borderRadius: 6, padding: '8px 14px', marginBottom: 14,
                  fontSize: '0.73rem', color: 'var(--text-dim)'
                }}>
                  <strong>Método:</strong> {metodoTxt}
                </div>
                {rows.length > 0 ? (
                  <table style={{ width: '100%', borderCollapse: 'collapse', marginBottom: 20 }}>
                    <thead><tr>
                      <th style={{ ...PTH, textAlign: 'left' }}>Mês</th>
                      <th style={{ ...PTH, textAlign: 'right' }}>Base 2025</th>
                      <th style={{ ...PTH, textAlign: 'right', color: '#8cb700' }}>Estimativa 2026</th>
                      <th style={{ ...PTH, textAlign: 'right' }}>Δ vs 2025</th>
                    </tr></thead>
                    <tbody>
                      {rows.map(r => {
                        const rowDelta = r.y25 > 0 ? r.est - r.y25 : r.est;
                        return (
                          <tr key={r.m}>
                            <td style={{ ...PTD, fontWeight: 600 }}>{_gc_M[r.m - 1]}</td>
                            <td style={PTR}>{r.y25 > 0 ? _gc_fn(r.y25) + ' €' : '—'}</td>
                            <td style={{ ...PTR, color: '#8cb700', fontWeight: 700 }}>
                              {_gc_fn(r.est)} €
                              {r.type === 'ritmo' && <span style={{ marginLeft: 5, fontSize: '0.65rem', background: 'rgba(140,183,0,0.15)', color: '#8cb700', borderRadius: 3, padding: '1px 5px' }}>ritmo</span>}
                            </td>
                            <td style={{ ...PTR, color: rowDelta >= 0 ? '#8cb700' : '#d93025', fontWeight: 700 }}>
                              {(rowDelta >= 0 ? '+' : '') + _gc_fn(rowDelta)} €
                            </td>
                          </tr>
                        );
                      })}
                    </tbody>
                  </table>
                ) : (
                  <div style={{ color: 'var(--text-dim)', padding: '12px 0', fontSize: '0.8rem' }}>Sem meses futuros para estimar.</div>
                )}
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 10 }}>
                  <GcKpiCard label="YTD Real 2026" value={_gc_fn(cliData.v26) + ' €'} sub={ytdLabel} topColor="#8cb700" />
                  <GcKpiCard label="Estimativa Ano Completo" value={_gc_fn(estTotal) + ' €'} sub="YTD + previsão restante" topColor="#8cb700" />
                  <GcKpiCard label="Base 2025 Ano Completo" value={base25Total > 0 ? _gc_fn(base25Total) + ' €' : '—'} sub="" topColor="#7f828a" valueColor="#7f828a" />
                  <GcKpiCard label="Δ Estimado vs 2025" value={base25Total > 0 ? (cliDelta >= 0 ? '+' : '') + _gc_fn(cliDelta) + ' €' : '—'} topColor={cliDelta >= 0 ? '#8cb700' : '#d93025'} />
                </div>
              </div>
            );
          }
          // ── Modo Família (normal) ───────────────────────────────────────────
          const gfRaw = fam.v25 > 0 ? fam.v26 / fam.v25 : 1;
          const gfCapped = Math.min(3.0, Math.max(0.3, gfRaw));
          const actualSet = new Set((fam.mensal || []).filter(m => m.y26 > 0).map(m => m.m));
          const base25 = fam.mensal25full || fam.mensal || [];
          const futureRows = base25.filter(m => !actualSet.has(m.m) && m.m > currentMonth);
          const futureEstTotal  = futureRows.reduce((s, m) => s + (m.y25 || 0) * gfCapped, 0);
          const futureBase25Total = futureRows.reduce((s, m) => s + (m.y25 || 0), 0);
          const estTotal    = fam.v26 + futureEstTotal;
          const base25Total = fam.v25 + futureBase25Total;
          const delta = estTotal - base25Total;
          return (
            <div>
              <div style={{
                background: 'var(--bg-hover)', border: '1px solid var(--border)',
                borderRadius: 6, padding: '8px 14px', marginBottom: 14,
                fontSize: '0.73rem', color: 'var(--text-dim)'
              }}>
                Método: Estimativa = base 2025 × fator de crescimento YTD ({gfCapped.toFixed(2)}x). Fator limitado a [0,3× ; 3,0×].
              </div>
              {futureRows.length > 0 ? (
                <table style={{ width: '100%', borderCollapse: 'collapse', marginBottom: 20 }}>
                  <thead><tr>
                    <th style={{ ...PTH, textAlign: 'left' }}>Mês</th>
                    <th style={{ ...PTH, textAlign: 'right' }}>Base 2025</th>
                    <th style={{ ...PTH, textAlign: 'right', color: '#8cb700' }}>Estimativa 2026</th>
                    <th style={{ ...PTH, textAlign: 'right' }}>Δ vs 2025</th>
                  </tr></thead>
                  <tbody>
                    {futureRows.map(m => {
                      const est = (m.y25 || 0) * gfCapped;
                      const d = est - (m.y25 || 0);
                      return (
                        <tr key={m.m}>
                          <td style={{ ...PTD, fontWeight: 600 }}>{_gc_M[m.m - 1]}</td>
                          <td style={PTR}>{_gc_fn(m.y25)} €</td>
                          <td style={{ ...PTR, color: '#8cb700', fontWeight: 700 }}>{_gc_fn(est)} €</td>
                          <td style={{ ...PTR, color: d >= 0 ? '#8cb700' : '#d93025', fontWeight: 700 }}>
                            {d >= 0 ? '+' : ''}{_gc_fn(d)} €
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              ) : (
                <div style={{ color: 'var(--text-dim)', padding: '12px 0', fontSize: '0.8rem' }}>Sem dados de base 2025 para meses futuros.</div>
              )}
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 10 }}>
                <GcKpiCard label="YTD Real 2026" value={_gc_fn(fam.v26) + ' €'} sub="Jan–Jun" topColor="#8cb700" />
                <GcKpiCard label="Estimativa Ano Completo" value={_gc_fn(estTotal) + ' €'} sub="YTD + previsão restante" topColor="#8cb700" />
                <GcKpiCard label="Base 2025 Ano Completo" value={_gc_fn(base25Total) + ' €'} sub="" topColor="#7f828a" valueColor="#7f828a" />
                <GcKpiCard label="Δ Estimado vs 2025" value={(delta >= 0 ? '+' : '') + _gc_fn(delta) + ' €'} topColor={delta >= 0 ? '#8cb700' : '#d93025'} />
              </div>
            </div>
          );
        })()}

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

const _GcInfoTip = ({ text }) => {
  const [show, setShow] = React.useState(false);
  return (
    <span style={{ position: 'relative', display: 'inline-flex', alignItems: 'center', marginLeft: 4, verticalAlign: 'middle' }}>
      <span onMouseEnter={() => setShow(true)} onMouseLeave={() => setShow(false)}
        style={{ cursor: 'default', color: 'rgba(99,102,241,0.65)', fontSize: 11, lineHeight: 1, userSelect: 'none' }}>ⓘ</span>
      {show && (
        <div style={{ position: 'absolute', bottom: 'calc(100% + 6px)', left: '50%', transform: 'translateX(-50%)', background: 'var(--surface-muted)', border: '1px solid var(--border)', borderRadius: 6, padding: '7px 10px', fontSize: 11, color: 'var(--text-muted)', zIndex: 200, boxShadow: '0 3px 10px rgba(0,0,0,0.18)', pointerEvents: 'none', width: 240, lineHeight: 1.5 }}>
          {text}
        </div>
      )}
    </span>
  );
};

// ── Main ──────────────────────────────────────────────────────────────────────
const ScreenGestorClassic = () => {
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [classicGrupos, setClassicGrupos] = React.useState([]);
  const [drill, setDrill] = React.useState({});
  const [fileDate, setFileDate] = React.useState(null);
  const [activeGrupo, setActiveGrupo] = React.useState(null);
  const [activeMercado, setActiveMercado] = React.useState(null);
  const [activeCliente, setActiveCliente] = React.useState(null); // { e, n }
  const [searchQuery, setSearchQuery] = React.useState('');
  const [showSuggestions, setShowSuggestions] = React.useState(false);
  const [expandedGrupos, setExpandedGrupos] = React.useState({});
  // analysisKey = { fc, fd, grupo } | null
  const [analysisKey, setAnalysisKey] = React.useState(null);
  const panelRef = React.useRef(null);

  const MERCADOS = [
    { id: 'Export',   color: '#34a853' },
    { id: 'Nacional', color: '#1a73e8' },
    { id: 'Mimaki',   color: '#e8710a' },
    { id: 'Grupo',    color: '#7b1fa2' },
    { id: 'Partners', color: '#00897b' },
    { id: 'Sensek',   color: '#f9a825' },
    { id: 'Sede',     color: '#5f6368' },
    { id: 'Outros',   color: '#3c4043' },
  ];

  React.useEffect(() => {
    fetch('/api/vp-data')
      .then(r => r.json())
      .then(resp => {
        const d = resp.data || resp;
        const grupos = d.classicGrupos || [];
        setClassicGrupos(grupos);
        setDrill(resp.drill || {});
        setFileDate(resp.file_date || d.file_date || null);
        if (grupos.length > 0) setExpandedGrupos({ [grupos[0].grupo]: true });
        // Actualizar timestamp e origem do último sync (partilhado com VP screen)
        try {
          if (resp.created_at) localStorage.setItem('vp-drill-ts', resp.created_at);
          if (resp.imported_by) localStorage.setItem('vp-imported-by', resp.imported_by);
          if (resp.file_date)   localStorage.setItem('vp-file-date',   resp.file_date);
        } catch(_) {}
        setLoading(false);
      })
      .catch(e => {
        setError('Erro ao carregar dados: ' + e.message);
        setLoading(false);
      });
  }, []);

  // Scroll to panel when it opens
  React.useEffect(() => {
    if (analysisKey && panelRef.current) {
      setTimeout(() => panelRef.current?.scrollIntoView({ behavior: 'smooth', block: 'nearest' }), 50);
    }
  }, [analysisKey]);

  // ── Cliente search ────────────────────────────────────────────────────────
  const allClients = React.useMemo(() => {
    const seen = {};
    for (const clients of Object.values(drill)) {
      for (const c of clients) {
        if (!seen[c.e]) seen[c.e] = { e: c.e, n: c.n };
      }
    }
    return Object.values(seen).sort((a, b) => a.n.localeCompare(b.n));
  }, [drill]);

  const searchSuggestions = React.useMemo(() => {
    if (!searchQuery || searchQuery.length < 2) return [];
    const q = searchQuery.toLowerCase();
    return allClients.filter(c => c.n.toLowerCase().includes(q) || c.e.toLowerCase().startsWith(q)).slice(0, 8);
  }, [searchQuery, allClients]);

  // Per-family data for the active client
  const cliByFam = React.useMemo(() => {
    if (!activeCliente) return {};
    const map = {};
    for (const [fc, clients] of Object.entries(drill)) {
      const found = clients.find(c => c.e === activeCliente.e);
      if (found) map[fc] = found;
    }
    return map;
  }, [activeCliente, drill]);

  if (loading) return (
    <div style={{ height: '100%', overflowY: 'auto', background: 'var(--bg)' }}>
      <div style={{ padding: 60, textAlign: 'center', color: 'var(--text-dim)' }}>
        <div style={{ display: 'inline-block', width: 28, height: 28, border: '3px solid var(--border)', borderTopColor: '#8cb700', borderRadius: '50%', animation: 'spin 0.8s linear infinite', marginBottom: 14 }} />
        <div style={{ fontSize: '0.85rem', letterSpacing: '0.04em' }}>A carregar dados…</div>
        <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>
      </div>
    </div>
  );

  if (error) return (
    <div style={{ height: '100%', overflowY: 'auto', background: 'var(--bg)' }}>
      <div style={{ padding: 40, textAlign: 'center', color: '#d93025' }}>{error}</div>
    </div>
  );

  if (!classicGrupos.length) return (
    <div style={{ height: '100%', overflowY: 'auto', background: 'var(--bg)' }}>
      <div style={{ padding: 40, textAlign: 'center', color: 'var(--text-dim)', lineHeight: 1.6 }}>
        <div style={{ fontSize: '1.1rem', marginBottom: 8 }}>Sem dados disponíveis.</div>
        <div style={{ fontSize: '0.85rem' }}>Aguarda o próximo sync do Primavera (03:00) ou faz uma importação manual.</div>
      </div>
    </div>
  );

  // Helpers para filtro de Mercados
  const _gcMercVal = (obj) => activeMercado ? (obj.mercados?.[activeMercado] || { v26:0, v25:0, m26:0, m25:0 }) : obj;
  const _gcCalcDisp = (v26, v25, m26, m25) => ({
    v26, v25, m26, m25,
    vv:   v25 > 0 ? (v26 - v25) / v25 * 100 : (v26 > 0 ? 100 : 0),
    pm26: v26 > 0 ? m26 / v26 * 100 : 0,
    pm25: v25 > 0 ? m25 / v25 * 100 : 0,
    vm:   (v26 > 0 ? m26 / v26 * 100 : 0) - (v25 > 0 ? m25 / v25 * 100 : 0),
  });
  const gDisp = (g) => {
    if (activeCliente) {
      const sv26 = g.fams.reduce((s, f) => s + (cliByFam[f.fc]?.v26 || 0), 0);
      const sv25 = g.fams.reduce((s, f) => s + (cliByFam[f.fc]?.v25 || 0), 0);
      const sm26 = g.fams.reduce((s, f) => { const cv = cliByFam[f.fc]; return s + (cv ? cv.v26 * (cv.pm26 || 0) / 100 : 0); }, 0);
      const sm25 = g.fams.reduce((s, f) => { const cv = cliByFam[f.fc]; return s + (cv ? cv.v25 * (cv.pm25 || 0) / 100 : 0); }, 0);
      return _gcCalcDisp(sv26, sv25, sm26, sm25);
    }
    const v = _gcMercVal(g); return activeMercado ? _gcCalcDisp(v.v26, v.v25, v.m26, v.m25) : g;
  };
  const fDisp = (f) => {
    if (activeCliente) {
      const cv = cliByFam[f.fc];
      if (!cv) return { v26:0, v25:0, m26:0, m25:0, vv:0, pm26:0, pm25:0, vm:0 };
      const m26 = cv.v26 * (cv.pm26 || 0) / 100;
      const m25 = cv.v25 * (cv.pm25 || 0) / 100;
      return _gcCalcDisp(cv.v26, cv.v25, m26, m25);
    }
    const v = _gcMercVal(f); return activeMercado ? _gcCalcDisp(v.v26, v.v25, v.m26, v.m25) : f;
  };

  const filteredGrupos = (activeGrupo ? classicGrupos.filter(g => g.grupo === activeGrupo) : classicGrupos)
    .map(g => {
      if (!activeCliente) return g;
      const filteredFams = g.fams.filter(f => cliByFam[f.fc]);
      if (filteredFams.length === 0) return null;
      return { ...g, fams: filteredFams };
    })
    .filter(Boolean)
    .filter(g => { const v = gDisp(g); return v.v26 > 0 || v.v25 > 0; });

  const totV26 = filteredGrupos.reduce((s, g) => s + gDisp(g).v26, 0);
  const totV25 = filteredGrupos.reduce((s, g) => s + gDisp(g).v25, 0);
  const totM26 = filteredGrupos.reduce((s, g) => s + gDisp(g).m26, 0);
  const totM25 = filteredGrupos.reduce((s, g) => s + gDisp(g).m25, 0);
  const totVv = totV25 > 0 ? (totV26 - totV25) / totV25 * 100 : 0;
  const totPm26 = totV26 > 0 ? totM26 / totV26 * 100 : 0;
  const totPm25 = totV25 > 0 ? totM25 / totV25 * 100 : 0;

  const toggleGrupo = g => setExpandedGrupos(prev => ({ ...prev, [g]: !prev[g] }));
  const openAnalysis = (fam, grupo) => {
    setAnalysisKey(prev => prev?.fc === fam.fc ? null : { fc: fam.fc, fd: fam.fd, grupo, fam });
  };

  const TH = {
    padding: '9px 10px', fontSize: '0.68rem', color: 'var(--text-dim)', fontWeight: 700,
    textTransform: 'uppercase', letterSpacing: '0.04em', textAlign: 'right',
    borderBottom: '2px solid var(--border)', whiteSpace: 'nowrap', background: 'var(--surface-muted)'
  };
  const THL = { ...TH, textAlign: 'left' };
  const PR = { padding: '8px 10px', textAlign: 'right', fontVariantNumeric: 'tabular-nums' };
  const PL = { ...PR, textAlign: 'left' };

  return (
    <div style={{ height: '100%', overflowY: 'auto', background: 'var(--bg)' }}>
    <div style={{ padding: '16px 20px' }}>

      {/* Header */}
      <div style={{ marginBottom: 20 }}>
        <div style={{ fontSize: 10, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', letterSpacing: '0.08em', marginBottom: 4 }}>
          COMERCIAL · MONITOR DE VENDAS ERP
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexWrap: 'wrap' }}>
          <h2 className="font-display" style={{ margin: 0, fontSize: 26 }}>Monitor de Vendas ERP</h2>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            {(() => {
              const _curM = (() => { const d = new Date(); return d.getMonth() + 1; })();
              const ytdLbl = `YTD 2026 · Jan–${_gc_M[_curM - 1]}`;
              const importTs   = (() => { try { const t = localStorage.getItem('vp-drill-ts'); return t ? new Date(t).toLocaleString('pt-PT', { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' }) : null; } catch { return null; } })();
              const importedBy = (() => { try { return localStorage.getItem('vp-imported-by') || null; } catch { return null; } })();
              const isSync = importedBy && importedBy.startsWith('primavera-sync');
              const importLbl = isSync ? `Sync Primavera · ${importTs || '—'}` : importTs ? `Importação · ${importTs}` : null;
              return (<>
                <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '3px 10px', borderRadius: 999, background: 'rgba(140,183,0,0.1)', color: '#8cb700', fontSize: 10.5, fontWeight: 600, letterSpacing: '0.04em' }}>
                  <span style={{ width: 5, height: 5, borderRadius: '50%', background: '#8cb700' }} />{ytdLbl}
                </div>
                {importLbl && (
                  <div style={{ display: 'inline-flex', alignItems: 'center', gap: 6, padding: '3px 10px', borderRadius: 999, background: 'rgba(202,138,4,0.12)', color: '#ca8a04', fontSize: 10.5, fontWeight: 600, letterSpacing: '0.04em' }}>
                    <span style={{ width: 5, height: 5, borderRadius: '50%', background: '#ca8a04' }} />{importLbl}
                  </div>
                )}
              </>);
            })()}
          </div>
        </div>
      </div>

      {/* KPI Cards */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 12, marginBottom: 16 }}>
        {[
          { label: 'Valor Líquido', tip: 'Faturação bruta por grupo de produto — notas de crédito não estão incluídas neste ecrã. O separador VP mostra o valor líquido (faturação menos créditos).', cur: totV26, prev: totV25, vv: totVv, fmt: _gc_fv, fvv: _gc_pct },
          { label: 'Valor Margem', cur: totM26, prev: totM25, vv: totM25 > 0 ? (totM26 - totM25) / totM25 * 100 : 0, fmt: _gc_fv, fvv: _gc_pct },
          { label: '% Margem', cur: totPm26, prev: totPm25, vv: totPm26 - totPm25, fmt: n => _gc_pct(n, false), fvv: _gc_pp },
        ].map(k => (
          <div key={k.label} style={{ background: 'var(--surface-muted)', borderRadius: 8, padding: '14px 16px', border: '1px solid var(--border)' }}>
            <div style={{ fontSize: '0.68rem', color: 'var(--text-dim)', fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.05em', marginBottom: 8 }}>
              {k.label}{k.tip && <_GcInfoTip text={k.tip} />}
            </div>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 5 }}>
              <span style={{ fontSize: '1.4rem', fontWeight: 800, color: 'var(--text)' }}>{k.fmt(k.cur)}</span>
              <span style={{ fontSize: '0.72rem', color: 'var(--text-dim)' }}>2026</span>
            </div>
            <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
              <span style={{ fontSize: '0.78rem', color: 'var(--text-muted)' }}>{k.fmt(k.prev)} <span style={{ color: 'var(--text-dim)' }}>2025</span></span>
              <span style={{ fontSize: '0.8rem', fontWeight: 700, color: _gc_vc(k.vv) }}>{k.fvv(k.vv)}</span>
            </div>
          </div>
        ))}
      </div>

      {/* Pesquisar Cliente */}
      <div style={{ marginBottom: 12, position: 'relative', maxWidth: 320 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
          <input
            type="text"
            value={activeCliente ? activeCliente.n + ' (' + activeCliente.e + ')' : searchQuery}
            placeholder="Pesquisar Cliente"
            onFocus={() => { if (activeCliente) { setActiveCliente(null); setSearchQuery(''); setAnalysisKey(null); } setShowSuggestions(true); }}
            onChange={e => { setSearchQuery(e.target.value); setActiveCliente(null); setShowSuggestions(true); }}
            onBlur={() => setTimeout(() => setShowSuggestions(false), 150)}
            style={{
              flex: 1, padding: '6px 12px', borderRadius: 20, border: `1.5px solid ${activeCliente ? '#1a73e8' : 'var(--border)'}`,
              background: activeCliente ? 'rgba(26,115,232,0.07)' : 'var(--surface-muted)',
              color: 'var(--text)', fontSize: '0.8rem', outline: 'none',
              fontWeight: activeCliente ? 600 : 400
            }}
          />
          {activeCliente && (
            <button onClick={() => { setActiveCliente(null); setSearchQuery(''); setAnalysisKey(null); }} style={{
              padding: '4px 10px', borderRadius: 20, fontSize: '0.72rem', fontWeight: 700, cursor: 'pointer',
              border: 'none', background: '#d93025', color: '#fff'
            }}>✕ Limpar</button>
          )}
        </div>
        {showSuggestions && searchSuggestions.length > 0 && (
          <div style={{
            position: 'absolute', top: '100%', left: 0, right: 0, zIndex: 100,
            background: 'var(--bg)', border: '1px solid var(--border)', borderRadius: 8,
            boxShadow: '0 4px 16px rgba(0,0,0,0.18)', marginTop: 4, overflow: 'hidden'
          }}>
            {searchSuggestions.map(c => (
              <div key={c.e} onMouseDown={() => {
                setActiveCliente(c); setSearchQuery(''); setShowSuggestions(false); setAnalysisKey(null);
                setExpandedGrupos({});
              }} style={{
                padding: '8px 14px', cursor: 'pointer', fontSize: '0.8rem',
                borderBottom: '1px solid var(--border)',
                display: 'flex', justifyContent: 'space-between', alignItems: 'center'
              }}
              onMouseEnter={e => e.currentTarget.style.background = 'var(--bg-hover)'}
              onMouseLeave={e => e.currentTarget.style.background = 'transparent'}
              >
                <span style={{ fontWeight: 600, color: 'var(--text)' }}>{c.n}</span>
                <span style={{ fontSize: '0.72rem', color: 'var(--text-dim)' }}>{c.e}</span>
              </div>
            ))}
          </div>
        )}
        {activeCliente && (
          <div style={{ fontSize: '0.68rem', color: '#1a73e8', marginTop: 4, paddingLeft: 4, fontWeight: 600 }}>
            Modo Cliente — a mostrar apenas famílias com actividade de {activeCliente.n}
          </div>
        )}
      </div>

      {/* Grupos filter */}
      <div style={{ display: 'flex', gap: 5, flexWrap: 'wrap', marginBottom: 8 }}>
        {[{ grupo: null, label: 'Todos' }, ...classicGrupos.map(g => ({ grupo: g.grupo, label: g.grupo }))].map(item => {
          const active = activeGrupo === item.grupo;
          return (
            <button key={item.label}
              onClick={() => { setActiveGrupo(item.grupo); setAnalysisKey(null); }}
              style={{
                padding: '3px 10px', borderRadius: 20, fontSize: '0.73rem', cursor: 'pointer',
                fontWeight: active ? 700 : 400,
                border: `1px solid ${active ? 'var(--accent-500)' : 'var(--border)'}`,
                background: active ? 'rgba(56,89,208,0.15)' : 'transparent',
                color: active ? '#6b8ef5' : 'var(--text-muted)'
              }}>
              {item.label}
            </button>
          );
        })}
      </div>

      {/* Mercados filter */}
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap', marginBottom: 14 }}>
        <span style={{ fontSize: '0.68rem', fontWeight: 700, color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '0.06em', marginRight: 2 }}>Mercados:</span>
        <button onClick={() => { setActiveMercado(null); setAnalysisKey(null); }} style={{
          padding: '3px 11px', borderRadius: 20, fontSize: '0.73rem', fontWeight: 700, cursor: 'pointer', border: 'none',
          background: activeMercado === null ? '#34a853' : 'var(--surface-muted)',
          color: activeMercado === null ? '#fff' : 'var(--text-muted)'
        }}>Todos</button>
        {MERCADOS.map(m => (
          <button key={m.id} onClick={() => { setActiveMercado(m.id); setAnalysisKey(null); }} style={{
            padding: '3px 11px', borderRadius: 20, fontSize: '0.73rem', fontWeight: 600, cursor: 'pointer', border: 'none',
            background: activeMercado === m.id ? m.color : 'var(--surface-muted)',
            color: activeMercado === m.id ? '#fff' : 'var(--text-muted)',
            outline: activeMercado === m.id ? `2px solid ${m.color}` : 'none', outlineOffset: 1
          }}>{m.id}</button>
        ))}
      </div>

      {/* Table */}
      <div style={{ border: '1px solid var(--border)', borderRadius: 8, overflow: 'hidden' }}>
        <div style={{ overflowX: 'auto' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: '0.82rem' }}>
            <thead>
              <tr>
                <th style={{ ...THL, minWidth: 220 }}>Grupo / Família</th>
                <th style={TH}>V.Líq 2025</th>
                <th style={TH}>V.Líq 2026</th>
                <th style={TH}>Cres%</th>
                <th style={TH}>V.Marg 2026</th>
                <th style={TH}>%Mg 2025</th>
                <th style={TH}>%Mg 2026</th>
                <th style={TH}>Δpp</th>
                <th style={{ ...TH, textAlign: 'center' }}>CV</th>
                <th style={{ ...TH, textAlign: 'center', minWidth: 90 }}>Analisar</th>
              </tr>
            </thead>
            <tbody>
              {/* TOTAIS */}
              <tr style={{ background: 'var(--bg-hover)', borderBottom: '2px solid var(--border-strong)' }}>
                <td style={{ ...PL, fontWeight: 800, fontSize: '0.87rem', color: 'var(--text)' }}>TOTAIS VENDAS</td>
                <td style={{ ...PR, color: 'var(--text-muted)' }}>{_gc_fv(totV25)}</td>
                <td style={{ ...PR, fontWeight: 800 }}>{_gc_fv(totV26)}</td>
                <td style={{ ...PR, fontWeight: 800, color: _gc_vc(totVv) }}>{_gc_pct(totVv)}</td>
                <td style={{ ...PR, fontWeight: 700 }}>{_gc_fv(totM26)}</td>
                <td style={{ ...PR, color: 'var(--text-muted)' }}>{_gc_pct(totPm25, false)}</td>
                <td style={{ ...PR, fontWeight: 700 }}>{_gc_pct(totPm26, false)}</td>
                <td style={{ ...PR, fontWeight: 700, color: _gc_vc(totPm26 - totPm25) }}>{_gc_pp(totPm26 - totPm25)}</td>
                <td /><td />
              </tr>

              {filteredGrupos.map(g => {
                const isExp = !!expandedGrupos[g.grupo];
                return (
                  <React.Fragment key={g.grupo}>
                    {/* Grupo row */}
                    <tr onClick={() => toggleGrupo(g.grupo)} style={{
                      background: 'var(--bg-hover)', cursor: 'pointer',
                      borderTop: '1px solid var(--border-strong)', borderBottom: '1px solid var(--border)'
                    }}>
                      <td style={{ ...PL, fontWeight: 700, color: 'var(--text)' }}>
                        <span style={{ marginRight: 7, fontSize: '0.62rem', color: 'var(--text-dim)' }}>{isExp ? '▼' : '▶'}</span>
                        {g.grupo}
                        <span style={{ marginLeft: 7, fontSize: '0.62rem', color: 'var(--text-dim)', background: 'var(--surface-muted)', padding: '1px 5px', borderRadius: 3 }}>
                          {g.fams.length} fam
                        </span>
                      </td>
                      {(() => { const gd = gDisp(g); return (<>
                      <td style={{ ...PR, color: 'var(--text-muted)' }}>{_gc_fv(gd.v25)}</td>
                      <td style={{ ...PR, fontWeight: 700 }}>{_gc_fv(gd.v26)}</td>
                      <td style={{ ...PR, fontWeight: 700, color: _gc_vc(gd.vv) }}>{_gc_pct(gd.vv)}</td>
                      <td style={{ ...PR, fontWeight: 700 }}>{_gc_fv(gd.m26)}</td>
                      <td style={{ ...PR, color: 'var(--text-muted)' }}>{_gc_pct(gd.pm25, false)}</td>
                      <td style={{ ...PR, fontWeight: 600 }}>{_gc_pct(gd.pm26, false)}</td>
                      <td style={{ ...PR, fontWeight: 600, color: _gc_vc(gd.vm) }}>{_gc_pp(gd.vm)}</td>
                      </>); })()}
                      <td /><td />
                    </tr>

                    {/* Family rows */}
                    {isExp && g.fams.filter(fam => { const fd = fDisp(fam); return fd.v26 > 0 || fd.v25 > 0; }).map(fam => {
                      const isActive = analysisKey?.fc === fam.fc;
                      const fd = fDisp(fam);
                      return (
                        <tr key={fam.fc} style={{
                          background: isActive ? 'rgba(140,183,0,0.05)' : 'var(--bg)',
                          borderBottom: '1px solid var(--border)',
                          borderLeft: `3px solid ${isActive ? '#8cb700' : 'transparent'}`
                        }}>
                          <td style={{ ...PL, paddingLeft: 28, color: 'var(--text-muted)' }}>
                            <span style={{ fontWeight: 500, color: 'var(--text)' }}>{fam.fd}</span>
                            <span style={{ marginLeft: 7, fontSize: '0.68rem', color: 'var(--text-dim)' }}>{fam.fc}</span>
                            {fd.v25 === 0 && fd.v26 > 0 && <span style={{ marginLeft: 7, fontSize: '0.62rem', fontWeight: 700, color: '#8cb700', background: '#8cb70015', padding: '1px 5px', borderRadius: 3 }}>NOVO</span>}
                            {fd.v26 === 0 && fd.v25 > 0 && <span style={{ marginLeft: 7, fontSize: '0.62rem', fontWeight: 700, color: '#d93025', background: '#d9302515', padding: '1px 5px', borderRadius: 3 }}>PERDIDO</span>}
                          </td>
                          <td style={{ ...PR, color: 'var(--text-muted)', fontSize: '0.79rem' }}>{_gc_fv(fd.v25)}</td>
                          <td style={{ ...PR, fontSize: '0.79rem' }}>{_gc_fv(fd.v26)}</td>
                          <td style={{ ...PR, fontWeight: 600, color: _gc_vc(fd.vv), fontSize: '0.79rem' }}>{_gc_pct(fd.vv)}</td>
                          <td style={{ ...PR, fontSize: '0.79rem' }}>{_gc_fv(fd.m26)}</td>
                          <td style={{ ...PR, color: 'var(--text-muted)', fontSize: '0.79rem' }}>{_gc_pct(fd.pm25, false)}</td>
                          <td style={{ ...PR, fontSize: '0.79rem' }}>{_gc_pct(fd.pm26, false)}</td>
                          <td style={{ ...PR, color: _gc_vc(fd.vm), fontWeight: 600, fontSize: '0.79rem' }}>{_gc_pp(fd.vm)}</td>
                          <td style={{ padding: '7px 10px', textAlign: 'center' }}><GcCvBadge cv={fam.cv} /></td>
                          <td style={{ padding: '7px 10px', textAlign: 'center' }}>
                            <button onClick={() => openAnalysis(fam, g.grupo)} style={{
                              padding: '3px 10px', borderRadius: 5, fontSize: '0.71rem', fontWeight: 600, cursor: 'pointer',
                              border: `1px solid ${isActive ? '#8cb700' : 'var(--border)'}`,
                              background: isActive ? '#8cb700' : 'transparent',
                              color: isActive ? '#fff' : 'var(--text-muted)'
                            }}>
                              {isActive ? '↑ Fechar' : '↓ Analisar'}
                            </button>
                          </td>
                        </tr>
                      );
                    })}
                  </React.Fragment>
                );
              })}
            </tbody>
          </table>
        </div>

        {/* Analysis panel — below the table, inside the same container */}
        {analysisKey && (
          <GcAnalysisPanel
            key={analysisKey.fc + (activeCliente?.e || '')}
            fam={analysisKey.fam}
            grupo={analysisKey.grupo}
            drillData={activeCliente ? (drill[analysisKey.fc] || []).filter(c => c.e === activeCliente.e) : (drill[analysisKey.fc] || [])}
            allDrillData={drill[analysisKey.fc] || []}
            activeCliente={activeCliente}
            onClose={() => setAnalysisKey(null)}
            panelRef={panelRef}
          />
        )}
      </div>

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

window.ScreenGestorClassic = ScreenGestorClassic;
