/* =============================================================================
   screen_comercial_rpc.jsx — Produção Comercial (módulo completo)
   =============================================================================
   Sub-tabs:
     1. Mapa RPC         — grelha SPIN/OPTMKT/OPTCOM/OPMANAGERF9/BP/F9/VENDAS/DESVIO
     2. Show me the Money— facturação real mês a mês por gestor
     3. Forecast         — equipamentos e vendedores (pipeline projectado)
     4. Preditividade    — fecho do mês + drilldown OPs
     5. YTD Famílias     — mapa vendas YTD por família/artigo
     6. Media Sales AI   — controlo PrintPlan, Digirent, tintas, alertas
     7. Sugestões AI     — acções de melhoria por comercial

   Dados em tempo real: FM GestorConnect (PTDIG + DIGES) + Primavera Sync (PT).
   Pendente Walter: SPINS layout, ForecastDate em FMRS_API_OPORTUNIDADES, OBJECTIVOS layout.
   ============================================================================= */

// ─── Constantes ───────────────────────────────────────────────────────────────
const RPC_MESES    = ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'];
const RPC_ANO_DEF  = 2026;
const RPC_MES_FECH = 5; // Jun = último mês fechado (0-based)

// ─── Helpers ──────────────────────────────────────────────────────────────────
const rE = (n, compact=true) => {
  if (n == null) return '—';
  const abs = Math.abs(n), s = n < 0 ? '-' : '';
  if (compact && abs >= 1000000) return s + (abs/1000000).toFixed(1).replace('.',',') + 'M';
  if (compact && abs >= 1000)    return s + Math.round(abs/1000) + 'k';
  return s + new Intl.NumberFormat('pt-PT').format(Math.round(abs));
};
const rN = (n) => n == null ? '—' : String(n);
const rPct = (v, t) => t > 0 ? (v/t*100).toFixed(1).replace('.',',')+'%' : '—';
const dStyle = (d, bp) => {
  if (d == null || bp == null) return { color:'var(--dgd-fg-3)' };
  const p = d / bp;
  if (p >= 0)    return { color:'#16a34a', fontWeight:600 };
  if (p > -0.10) return { color:'#d97706', fontWeight:600 };
  return               { color:'#dc2626', fontWeight:600 };
};
const badgeStyle = (sev) => ({
  display:'inline-block', padding:'2px 8px', borderRadius:4, fontSize:10, fontWeight:700, letterSpacing:'0.04em',
  background: sev==='alto'?'#fee2e2': sev==='medio'?'#fef3c7':'#dcfce7',
  color:       sev==='alto'?'#991b1b': sev==='medio'?'#92400e':'#166534',
});

const _zeros12 = [0,0,0,0,0,0,0,0,0,0,0,0];
const _null12  = [null,null,null,null,null,null,null,null,null,null,null,null];
const RPC_EMPTY = { spin:_zeros12, optmkt:_zeros12, optcom:_zeros12, opmanagerf9:_null12, bp:_zeros12, f9:_null12, vendas:_null12 };

// ─── Mock data: comerciais (partilhado entre tabs) ────────────────────────────
const COMERCIAIS_MOCK = [
  // Mimaki PT — EQ7=Andreia C, EQD=Gonçalo P, EQF=Daniel M, EQ4=Humberto L · J=SAT
  { id:'mpt-ac', nome:'Andreia C.',   marca:'Mimaki PT', vendedor:'EQ7'},
  { id:'mpt-gp', nome:'Gonçalo P.',   marca:'Mimaki PT', vendedor:'EQD'},
  { id:'mpt-dm', nome:'Daniel M.',    marca:'Mimaki PT', vendedor:'EQF'},
  { id:'mpt-hl', nome:'Humberto L.',  marca:'Mimaki PT', vendedor:'EQ4'},
  { id:'mpt-sat',nome:'SAT',          marca:'Mimaki PT', vendedor:'J'  },
  // Mimaki ES
  { id:'mes-m01', nome:'David Martinell', marca:'Mimaki ES', vendedor:'M01'},
  { id:'mes-m14', nome:'Raul Cerezo',     marca:'Mimaki ES', vendedor:'M14'},
  { id:'mes-m02', nome:'Sara Ruiz',       marca:'Mimaki ES', vendedor:'M02'},
  { id:'mes-m19', nome:'M19',             marca:'Mimaki ES', vendedor:'M19'},
  // Mimaki PA
  { id:'mes-m04', nome:'Paula Leal',      marca:'Mimaki PA', vendedor:'M04'},
  // Mimaki AD
  { id:'mes-m16', nome:'Eleuterio Silva', marca:'Mimaki AD', vendedor:'M16'},
  // Decal PT — C39=Andreia C, C41=Cláudia M, C42=Ana F, C43=Rita S, C44=Rute S, C47=?
  { id:'dpt-ac', nome:'Andreia C.',   marca:'Decal PT',  vendedor:'C39'},
  { id:'dpt-cm', nome:'Cláudia M.',   marca:'Decal PT',  vendedor:'C41'},
  { id:'dpt-af', nome:'Ana F.',       marca:'Decal PT',  vendedor:'C42'},
  { id:'dpt-rs', nome:'Rita S.',      marca:'Decal PT',  vendedor:'C43'},
  { id:'dpt-ru', nome:'Rute S.',      marca:'Decal PT',  vendedor:'C44'},
  // Sensek
  { id:'st',     nome:'Sensek PT',    marca:'Sensek',    vendedor:'C45'},
  // NetScreen (vendedor a confirmar)
  { id:'mt',     nome:'NetScreen',    marca:'NetScreen', vendedor:'—'  },
];

const MARCAS = ['Mimaki PT','Mimaki ES','Mimaki PA','Mimaki AD','Decal PT','Sensek','NetScreen'];
const ES_MARCAS = ['Mimaki ES','Mimaki PA','Mimaki AD'];


// ─── Hook: FM pipeline por vendedor ───────────────────────────────────────────
// Fonte: /api/rpc/fm-pipeline → GestorDeveloper (PTDIG) ou Gestor_Dimension (DIGES)
// byVendedor[id] = { opmanagerf9, optmkt, optcom, won, wonValor } — arrays 12 meses
const useFMPipeline = (empresa, ano) => {
  const [state, setState] = React.useState({ byVendedor: null, totalOps: 0, loading: false });
  React.useEffect(() => {
    if (!empresa) { setState({ byVendedor: null, totalOps: 0, loading: false }); return; }
    setState(s => ({ ...s, loading: true }));
    fetch(`/api/rpc/fm-pipeline?empresa=${empresa}&ano=${ano}`)
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(data => setState({ byVendedor: data.byVendedor || {}, totalOps: data.totalOps || 0, loading: false }))
      .catch(() => setState({ byVendedor: null, totalOps: 0, loading: false }));
  }, [empresa, ano]);
  return state;
};

// Agrega todos os vendedores de um byVendedor FM num único array de 12 meses
function fmAggregateAll(byVendedor, field) {
  const result = new Array(12).fill(0);
  if (!byVendedor) return result;
  Object.values(byVendedor).forEach(v => {
    if (!v[field]) return;
    v[field].forEach((n, i) => { result[i] += (n || 0); });
  });
  return result;
}

// ─── Context: FM pipeline data (SPIN, OPMANAGERF9, VENDAS para ES) ───────────
const FMCtx = React.createContext({});

// ─── Hook: equipa real da BD ──────────────────────────────────────────────────
const useTeam = (managerId) => {
  const [state, setState] = React.useState({ team: null, loading: true });
  React.useEffect(() => {
    if (!managerId) { setState({ team: null, loading: false }); return; }
    fetch(`/api/rpc/team?managerId=${managerId}`)
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(rows => {
        const team = rows.map(r => ({
          id:       'db-' + r.id,
          nome:     r.nome_apresentar || r.nome_completo,
          funcao:   r.funcao || '',
          vendedor: r.gestor_vendedor_id || '—',
          foto_url: r.foto_url || null,
          db_id:    r.id,
        }));
        setState({ team, loading: false });
      })
      .catch(() => setState({ team: null, loading: false }));
  }, [managerId]);
  return state;
};

// ─── Hook: YTD mensal por vendedor (Primavera real) ───────────────────────────
const YTDCtx = React.createContext({});

const useYTDMensal = (ano) => {
  const [state, setState] = React.useState({ byVendedor: null, loading: true });
  React.useEffect(() => {
    fetch(`/api/rpc/ytd?ano=${ano}`)
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(data => {
        const map = {};
        (data.mensal || []).forEach(row => {
          if (!map[row.vendedor]) map[row.vendedor] = new Array(12).fill(null);
          map[row.vendedor][row.mes - 1] = parseFloat(row.valor) || 0;
        });
        setState({ byVendedor: map, loading: false });
      })
      .catch(() => setState({ byVendedor: null, loading: false }));
  }, [ano]);
  return state;
};

// ─── 1. MAPA RPC ──────────────────────────────────────────────────────────────
const RPCGrid = ({ com, d }) => {
  const { spin,optmkt,optcom,opmanagerf9,bp,f9,vendas } = d;
  const desvio = vendas.map((v,i) => v==null ? null : v-(bp[i]||0));
  const s = (arr,n) => arr.slice(0,n).reduce((a,v)=>a+(v||0),0);
  const mf = RPC_MES_FECH+1;
  const rows = [
    { label:'SPIN',       vals:spin,       tot:s(spin,mf),       fmt:rN  },
    { label:'OPTMKT',     vals:optmkt,     tot:s(optmkt,mf),     fmt:rN  },
    { label:'OPTCOM',     vals:optcom,     tot:s(optcom,mf),     fmt:rN  },
    { label:'OPMANAGERF9',vals:opmanagerf9,tot:s(opmanagerf9,mf),fmt:rE  },
    { label:'BP',         vals:bp,         tot:s(bp,12),         fmt:rE, isBP:true  },
    { label:'F9FACTURAR', vals:f9,         tot:s(f9.filter(Boolean),f9.length),fmt:rE },
    { label:'VENDAS',     vals:vendas,     tot:s(vendas,mf),     fmt:rE, isV:true   },
    { label:'BP DESVIO',  vals:desvio,     tot:s(vendas,mf)-s(bp,mf), fmt:rE, isD:true },
  ];
  const C = { base:{padding:'4px 7px',textAlign:'right',fontSize:11,fontFamily:'var(--dgd-font-mono,monospace)',whiteSpace:'nowrap',borderRight:'1px solid var(--dgd-border-1,#e2e8f0)',borderBottom:'1px solid var(--dgd-border-1,#e2e8f0)'} };
  return (
    <div style={{marginBottom:20}}>
      <div style={{display:'flex',alignItems:'center',gap:8,padding:'6px 0 4px'}}>
        <div style={{width:26,height:26,borderRadius:7,background:'var(--dgd-bg-surface,#f1f5f9)',border:'1px solid var(--dgd-border-1)',display:'grid',placeItems:'center',fontSize:10,fontWeight:700,color:'var(--dgd-fg-2)',flexShrink:0}}>
          {com.nome.split(' ').map(w=>w[0]).slice(0,2).join('')}
        </div>
        <div style={{fontSize:13,fontWeight:600,color:'var(--dgd-fg-1)'}}>{com.nome}</div>
        {com.vendedor!=='—'&&<div style={{fontSize:10,color:'var(--dgd-fg-3)',fontFamily:'var(--dgd-font-mono,monospace)'}}>Primavera: {com.vendedor}</div>}
      </div>
      <div style={{overflowX:'auto',borderRadius:8,border:'1px solid var(--dgd-border-1,#e2e8f0)'}}>
        <table style={{borderCollapse:'collapse',width:'100%',minWidth:840}}>
          <thead>
            <tr>
              <th style={{...C.base,textAlign:'left',minWidth:108,position:'sticky',left:0,zIndex:2,background:'var(--dgd-bg-surface,#f8fafc)',fontSize:10,color:'var(--dgd-fg-3)',fontWeight:600,letterSpacing:'0.04em',paddingTop:5,paddingBottom:5}}>—</th>
              {RPC_MESES.map((m,i)=>(
                <th key={m} style={{...C.base,fontSize:10,color:i>RPC_MES_FECH?'var(--dgd-fg-3)':'var(--dgd-fg-2)',fontWeight:600,letterSpacing:'0.04em',paddingTop:5,paddingBottom:5,background:i===RPC_MES_FECH?'color-mix(in oklch,#3b82f6 6%,var(--dgd-bg-surface,#f8fafc))':'var(--dgd-bg-surface,#f8fafc)'}}>
                  {m}
                </th>
              ))}
              <th style={{...C.base,fontSize:10,fontWeight:700,color:'var(--dgd-fg-1)',background:'var(--dgd-bg-sunken,#f1f5f9)',borderRight:'none',paddingTop:5,paddingBottom:5}}>YTD</th>
            </tr>
          </thead>
          <tbody>
            {rows.map((row,ri)=>{
              const bgRow = row.isD?'color-mix(in oklch,#1e293b 3%,transparent)':row.isBP?'color-mix(in oklch,#3b82f6 4%,transparent)':row.isV?'color-mix(in oklch,#22c55e 3%,transparent)':ri%2===0?'transparent':'color-mix(in oklch,#94a3b8 3%,transparent)';
              return (
                <tr key={row.label} style={{background:bgRow}}>
                  <td style={{...C.base,textAlign:'left',fontWeight:row.isD||row.isBP||row.isV?700:500,fontSize:10.5,letterSpacing:'0.06em',color:row.isD?'var(--dgd-fg-1)':row.isBP?'#3b82f6':'var(--dgd-fg-2)',background:'var(--dgd-bg-card,white)',position:'sticky',left:0,zIndex:1,borderRight:'2px solid var(--dgd-border-1)'}}>
                    {row.label}
                  </td>
                  {row.vals.map((v,i)=>(
                    <td key={i} style={{...C.base,background:i===RPC_MES_FECH&&!row.isD?'color-mix(in oklch,#3b82f6 4%,transparent)':'transparent',...(row.isD?dStyle(v,bp[i]):{color:i>RPC_MES_FECH?'var(--dgd-fg-3)':'var(--dgd-fg-1)'})}}>
                      {row.fmt(v)}
                    </td>
                  ))}
                  <td style={{...C.base,borderRight:'none',fontWeight:700,background:'var(--dgd-bg-sunken,#f1f5f9)',...(row.isD?dStyle(row.tot,s(bp,mf)):{color:'var(--dgd-fg-1)'})}}>
                    {row.fmt(row.tot)}
                  </td>
                </tr>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
};

const TabMapaRPC = ({ coms }) => {
  const ytdMap = React.useContext(YTDCtx);
  const fmMap  = React.useContext(FMCtx);
  const mkD = (v) => {
    const fm = fmMap[v];
    return {
      spin:        _zeros12,                                    // pendente: layout SPINS (Walter)
      optmkt:      fm ? fm.optmkt      : _zeros12,
      optcom:      fm ? fm.optcom      : _zeros12,
      opmanagerf9: fm ? fm.opmanagerf9 : _null12,
      bp:          _zeros12,                                    // pendente: OBJECTIVOS layout (Walter)
      f9:          _null12,                                     // pendente: ForecastDate em FMRS_API_OPORTUNIDADES
      vendas:      ytdMap[v] ? ytdMap[v] : (fm ? fm.wonValor : _null12),
    };
  };
  return (
    <div>
      {coms.map(c=><RPCGrid key={c.id} com={c} d={mkD(c.vendedor)} />)}
      {coms.length>1&&(()=>{
        const tot = { nome:'Totais Equipa', id:'__tot__', vendedor:'—' };
        const agg = k => Array.from({length:12},(_,i)=>coms.every(c=>mkD(c.vendedor)[k][i]==null)?null:coms.reduce((s,c)=>s+(mkD(c.vendedor)[k][i]||0),0));
        return <RPCGrid com={tot} d={{spin:agg('spin'),optmkt:agg('optmkt'),optcom:agg('optcom'),opmanagerf9:agg('opmanagerf9'),bp:agg('bp'),f9:agg('f9'),vendas:agg('vendas')}} />;
      })()}
    </div>
  );
};

// ─── 2. SHOW ME THE MONEY ────────────────────────────────────────────────────
const TabShowMoney = ({ coms }) => {
  const [mesDetalhe, setMesDetalhe] = React.useState(null);
  const ytdMap = React.useContext(YTDCtx);
  const getV = (vendedor) => ytdMap[vendedor] || _null12;

  const thS = { padding:'5px 10px', fontSize:10, fontWeight:600, letterSpacing:'0.06em', color:'var(--dgd-fg-3)', fontFamily:'var(--dgd-font-mono,monospace)', borderBottom:'1px solid var(--dgd-border-1)', background:'var(--dgd-bg-surface)', textAlign:'right' };
  const tdS = (fut,cur) => ({ padding:'5px 10px', fontSize:11.5, fontFamily:'var(--dgd-font-mono,monospace)', textAlign:'right', borderBottom:'1px solid var(--dgd-border-1)', color:fut?'var(--dgd-fg-3)':'var(--dgd-fg-1)', background:cur?'color-mix(in oklch,#3b82f6 5%,transparent)':'transparent', cursor:fut?'default':'pointer' });

  return (
    <div>
      <div style={{fontSize:12,color:'var(--dgd-fg-2)',marginBottom:12}}>
        Facturação real por comercial · mês a mês. {mesDetalhe!=null&&<button onClick={()=>setMesDetalhe(null)} style={{marginLeft:8,fontSize:11,color:'#3b82f6',background:'none',border:'none',cursor:'pointer'}}>← voltar</button>}
      </div>

      {mesDetalhe==null ? (
        <div style={{overflowX:'auto',borderRadius:8,border:'1px solid var(--dgd-border-1)'}}>
          <table style={{borderCollapse:'collapse',width:'100%',minWidth:760}}>
            <thead>
              <tr>
                <th style={{...thS,textAlign:'left',minWidth:130,position:'sticky',left:0,zIndex:2,background:'var(--dgd-bg-surface)'}}>Comercial</th>
                {RPC_MESES.map((m,i)=><th key={m} style={{...thS,color:i>RPC_MES_FECH?'var(--dgd-fg-3)':'var(--dgd-fg-2)',background:i===RPC_MES_FECH?'color-mix(in oklch,#3b82f6 6%,var(--dgd-bg-surface))':'var(--dgd-bg-surface)'}}>{m}</th>)}
                <th style={{...thS,fontWeight:700,color:'var(--dgd-fg-1)',borderRight:'none'}}>YTD</th>
              </tr>
            </thead>
            <tbody>
              {coms.map((c,ri)=>{
                const v = getV(c.vendedor);
                const ytd = v.slice(0,RPC_MES_FECH+1).reduce((a,x)=>a+(x||0),0);
                return (
                  <tr key={c.id} style={{background:ri%2===0?'transparent':'color-mix(in oklch,#94a3b8 3%,transparent)'}}>
                    <td style={{...tdS(false,false),textAlign:'left',fontWeight:600,position:'sticky',left:0,background:'var(--dgd-bg-card,white)',borderRight:'2px solid var(--dgd-border-1)'}}>{c.nome}</td>
                    {v.map((val,i)=>(
                      <td key={i} style={tdS(i>RPC_MES_FECH,i===RPC_MES_FECH)} onClick={()=>i<=RPC_MES_FECH&&setMesDetalhe(i)}>{rE(val)}</td>
                    ))}
                    <td style={{...tdS(false,false),fontWeight:700,background:'var(--dgd-bg-sunken)',borderRight:'none'}}>{rE(ytd)}</td>
                  </tr>
                );
              })}
              <tr style={{background:'var(--dgd-bg-sunken)'}}>
                <td style={{...tdS(false,false),textAlign:'left',fontWeight:700,position:'sticky',left:0,background:'var(--dgd-bg-sunken)',borderRight:'2px solid var(--dgd-border-1)',borderTop:'2px solid var(--dgd-border-1)'}}>EQUIPA</td>
                {Array.from({length:12},(_,i)=>{
                  const tot = coms.reduce((s,c)=>s+(getV(c.vendedor)[i]||0),0);
                  return <td key={i} style={{...tdS(i>RPC_MES_FECH,i===RPC_MES_FECH),fontWeight:700,borderTop:'2px solid var(--dgd-border-1)'}}>{i>RPC_MES_FECH?'—':rE(tot)}</td>;
                })}
                <td style={{...tdS(false,false),fontWeight:700,borderTop:'2px solid var(--dgd-border-1)',borderRight:'none'}}>{rE(coms.reduce((s,c)=>s+getV(c.vendedor).slice(0,RPC_MES_FECH+1).reduce((a,v)=>a+(v||0),0),0))}</td>
              </tr>
            </tbody>
          </table>
        </div>
      ) : (
        <div>
          <div style={{fontSize:13,fontWeight:600,marginBottom:10}}>{RPC_MESES[mesDetalhe]} 2026 — Detalhe por comercial</div>
          {coms.map(c=>{
            const val = getV(c.vendedor)[mesDetalhe];
            const bpV = null; // BP pendente: layout OBJECTIVOS (Walter)
            const dev = val!=null&&bpV!=null?val-bpV:null;
            return (
              <div key={c.id} style={{display:'flex',gap:12,alignItems:'center',padding:'10px 14px',borderRadius:8,marginBottom:6,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)'}}>
                <div style={{width:28,height:28,borderRadius:7,background:'var(--dgd-bg-surface)',border:'1px solid var(--dgd-border-1)',display:'grid',placeItems:'center',fontSize:10,fontWeight:700,color:'var(--dgd-fg-2)'}}>{c.nome.split(' ').map(w=>w[0]).slice(0,2).join('')}</div>
                <div style={{flex:1,fontSize:13,fontWeight:500}}>{c.nome}</div>
                <div style={{textAlign:'right'}}>
                  <div style={{fontSize:16,fontWeight:700,fontFamily:'var(--dgd-font-mono,monospace)'}}>{rE(val)}</div>
                  <div style={{fontSize:10,color:'var(--dgd-fg-3)'}}>BP {rE(bpV)}</div>
                </div>
                <div style={{width:64,textAlign:'right',fontFamily:'var(--dgd-font-mono,monospace)',fontSize:12,...dStyle(dev,bpV)}}>{dev!=null?(dev>=0?'+':'')+rE(dev):'—'}</div>
                <div style={{width:52,textAlign:'right',fontFamily:'var(--dgd-font-mono,monospace)',fontSize:11,color:'var(--dgd-fg-2)'}}>{bpV?rPct(val||0,bpV):''}</div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
};

// ─── 3. FORECAST ─────────────────────────────────────────────────────────────
const FORECAST_OPS = [
  { id:'OP-2026-0441', comercial:'Daniel Silva', cliente:'Gráfica Lusitana',    equip:'Mimaki UCJV300-160',   val:48500,  prob:80, closeEst:'Jul 2026', stage:80 },
  { id:'OP-2026-0389', comercial:'Daniel Silva', cliente:'Print & Go Lda',       equip:'Mimaki JFX200-2513',   val:72000,  prob:65, closeEst:'Jul 2026', stage:65 },
  { id:'OP-2026-0412', comercial:'Carla Ferreira',cliente:'Decor Viseu',         equip:'Mimaki CJV330-160',    val:34800,  prob:90, closeEst:'Jul 2026', stage:90 },
  { id:'OP-2026-0398', comercial:'Carla Ferreira',cliente:'Sintra Digital',      equip:'Mimaki UJV100-160',    val:28400,  prob:50, closeEst:'Ago 2026', stage:65 },
  { id:'OP-2026-0455', comercial:'Javier García', cliente:'Imprenta Málaga S.L.',equip:'Mimaki TS100-1600',    val:41200,  prob:80, closeEst:'Jul 2026', stage:80 },
  { id:'OP-2026-0421', comercial:'Andreia Costa', cliente:'Decal Almada',        equip:'Pack Decal Start',     val:18600,  prob:90, closeEst:'Jul 2026', stage:92 },
  { id:'OP-2026-0438', comercial:'Cláudia Moreira',cliente:'Decorama Lda',       equip:'Pack Decal Pro',       val:24800,  prob:65, closeEst:'Jul 2026', stage:65 },
  { id:'OP-2026-0467', comercial:'Paulo Neves',   cliente:'ClinicaEstetica BeautyX',equip:'Biond Pro 6000',   val:12400,  prob:80, closeEst:'Jul 2026', stage:80 },
  { id:'OP-2026-0444', comercial:'Miguel Teixeira',cliente:'ShoppingParque',     equip:'NetScreen 65" Kit',    val:9800,   prob:65, closeEst:'Ago 2026', stage:65 },
];

const STAGE_LABELS = { 10:'Lead',20:'Demonst. Int.',50:'Evento',65:'Demo',80:'AG Decisão',90:'AG Aprovado',92:'Fecho' };
const stageBadge = (s) => {
  const c = s>=90?'#16a34a':s>=80?'#2563eb':s>=65?'#7c3aed':'#d97706';
  return { display:'inline-block', padding:'2px 7px', borderRadius:4, fontSize:10, fontWeight:600, background:`color-mix(in oklch,${c} 12%,transparent)`, color:c };
};

const TabForecast = ({ coms: comsArr }) => {
  const coms = comsArr.map(c=>c.nome);
  const ops = FORECAST_OPS.filter(o=>coms.includes(o.comercial));
  const totalWgtd = ops.reduce((s,o)=>s+o.val*o.prob/100,0);
  const totalFull = ops.reduce((s,o)=>s+o.val,0);

  return (
    <div>
      <div style={{display:'flex',gap:10,marginBottom:14,flexWrap:'wrap'}}>
        {[
          { l:'OPs em curso', v:ops.length+' ops', c:'var(--dgd-fg-1)' },
          { l:'Valor total pipeline', v:rE(totalFull), c:'var(--dgd-fg-1)' },
          { l:'Valor ponderado (prob.)', v:rE(totalWgtd), c:'#2563eb' },
        ].map(k=>(
          <div key={k.l} style={{padding:'10px 16px',borderRadius:8,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)'}}>
            <div style={{fontSize:9.5,color:'var(--dgd-fg-3)',fontFamily:'var(--dgd-font-mono,monospace)',letterSpacing:'0.08em',marginBottom:2}}>{k.l}</div>
            <div className="font-display" style={{fontSize:20,fontWeight:700,color:k.c,letterSpacing:'-0.02em'}}>{k.v}</div>
          </div>
        ))}
      </div>

      {ops.length===0 ? <div style={{color:'var(--dgd-fg-3)',fontSize:13}}>Sem OPs em pipeline para esta marca.</div> : (
        <div style={{overflowX:'auto',borderRadius:8,border:'1px solid var(--dgd-border-1)'}}>
          <table style={{borderCollapse:'collapse',width:'100%',minWidth:680}}>
            <thead>
              <tr style={{background:'var(--dgd-bg-surface)'}}>
                {['OP','Comercial','Cliente','Equipamento','Valor','Prob.','Stage','Fecho Est.'].map(h=>(
                  <th key={h} style={{padding:'6px 10px',fontSize:10,fontWeight:600,color:'var(--dgd-fg-3)',letterSpacing:'0.06em',fontFamily:'var(--dgd-font-mono,monospace)',borderBottom:'1px solid var(--dgd-border-1)',textAlign:h==='Valor'||h==='Prob.'?'right':'left'}}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {ops.map((op,i)=>(
                <tr key={op.id} style={{background:i%2===0?'transparent':'color-mix(in oklch,#94a3b8 3%,transparent)'}}>
                  <td style={{padding:'7px 10px',fontSize:11,fontFamily:'var(--dgd-font-mono,monospace)',color:'#3b82f6',borderBottom:'1px solid var(--dgd-border-1)'}}>{op.id}</td>
                  <td style={{padding:'7px 10px',fontSize:12,borderBottom:'1px solid var(--dgd-border-1)'}}>{op.comercial}</td>
                  <td style={{padding:'7px 10px',fontSize:12,borderBottom:'1px solid var(--dgd-border-1)',color:'var(--dgd-fg-2)'}}>{op.cliente}</td>
                  <td style={{padding:'7px 10px',fontSize:11.5,borderBottom:'1px solid var(--dgd-border-1)',color:'var(--dgd-fg-2)'}}>{op.equip}</td>
                  <td style={{padding:'7px 10px',fontSize:12,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',fontWeight:600,borderBottom:'1px solid var(--dgd-border-1)'}}>{rE(op.val)}</td>
                  <td style={{padding:'7px 10px',fontSize:12,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',color:op.prob>=80?'#16a34a':op.prob>=60?'#d97706':'#dc2626',fontWeight:600,borderBottom:'1px solid var(--dgd-border-1)'}}>{op.prob}%</td>
                  <td style={{padding:'7px 10px',borderBottom:'1px solid var(--dgd-border-1)'}}><span style={stageBadge(op.stage)}>{STAGE_LABELS[op.stage]||op.stage}</span></td>
                  <td style={{padding:'7px 10px',fontSize:11,color:'var(--dgd-fg-2)',fontFamily:'var(--dgd-font-mono,monospace)',borderBottom:'1px solid var(--dgd-border-1)'}}>{op.closeEst}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
};

// ─── 4. PREDITIVIDADE ─────────────────────────────────────────────────────────
const TabPreditividade = ({ coms: comsArr }) => {
  const [drill, setDrill] = React.useState(null);
  const ytdMap = React.useContext(YTDCtx);
  const getV = (vendedor) => ytdMap[vendedor] || _null12;
  const coms = comsArr.map(c=>c.nome);
  const ops = FORECAST_OPS.filter(o=>coms.includes(o.comercial)&&o.closeEst==='Jul 2026');

  const bpJul  = 0; // BP pendente: layout OBJECTIVOS (Walter)
  const vendJun = comsArr.reduce((s,c)=>s+getV(c.vendedor).slice(0,RPC_MES_FECH+1).reduce((a,v)=>a+(v||0),0),0);
  const projectado = ops.reduce((s,o)=>s+o.val*o.prob/100,0);
  const confScore = bpJul>0 ? Math.min(Math.round(projectado/bpJul*100),105) : 0;

  return (
    <div>
      {/* Header KPIs */}
      <div style={{display:'flex',gap:10,marginBottom:16,flexWrap:'wrap'}}>
        {[
          { l:'BP Jul 2026', v:rE(bpJul), c:'#3b82f6' },
          { l:'Projectado (ponderado)', v:rE(projectado), c:projectado>=bpJul?'#16a34a':'#dc2626' },
          { l:'Desvio projectado', v:(projectado-bpJul>=0?'+':'')+rE(projectado-bpJul), c:projectado>=bpJul?'#16a34a':'#dc2626' },
          { l:'Confiança', v:confScore+'%', c:confScore>=90?'#16a34a':confScore>=70?'#d97706':'#dc2626' },
        ].map(k=>(
          <div key={k.l} style={{padding:'10px 16px',borderRadius:8,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)',minWidth:110}}>
            <div style={{fontSize:9.5,color:'var(--dgd-fg-3)',fontFamily:'var(--dgd-font-mono,monospace)',letterSpacing:'0.08em',marginBottom:2}}>{k.l}</div>
            <div className="font-display" style={{fontSize:20,fontWeight:700,color:k.c,letterSpacing:'-0.02em'}}>{k.v}</div>
          </div>
        ))}
      </div>

      {/* Barra de progresso */}
      <div style={{marginBottom:16,padding:'12px 16px',borderRadius:8,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)'}}>
        <div style={{display:'flex',justifyContent:'space-between',fontSize:11,color:'var(--dgd-fg-2)',marginBottom:6}}>
          <span>Progresso vs BP Julho</span><span>{rE(projectado)} / {rE(bpJul)}</span>
        </div>
        <div style={{height:8,borderRadius:4,background:'var(--dgd-bg-sunken)'}}>
          <div style={{height:'100%',width:Math.min(confScore,100)+'%',borderRadius:4,background:confScore>=90?'#16a34a':confScore>=70?'#d97706':'#dc2626',transition:'width 0.4s'}} />
        </div>
      </div>

      {/* Drilldown OPs */}
      <div style={{fontSize:12,fontWeight:600,marginBottom:8,color:'var(--dgd-fg-2)'}}>OPs a contribuir para Julho</div>
      {ops.length===0?<div style={{color:'var(--dgd-fg-3)',fontSize:13}}>Sem OPs com fecho estimado em Julho.</div>:(
        <div>
          {ops.map(op=>(
            <div key={op.id} onClick={()=>setDrill(drill?.id===op.id?null:op)} style={{padding:'10px 14px',borderRadius:8,marginBottom:6,background:'var(--dgd-bg-card,white)',border:'1px solid '+(drill?.id===op.id?'#3b82f6':'var(--dgd-border-1)'),cursor:'pointer',transition:'border-color 0.15s'}}>
              <div style={{display:'flex',alignItems:'center',gap:10}}>
                <span style={stageBadge(op.stage)}>{STAGE_LABELS[op.stage]}</span>
                <span style={{fontWeight:600,fontSize:12,flex:1}}>{op.cliente}</span>
                <span style={{fontSize:11,color:'var(--dgd-fg-2)'}}>{op.equip}</span>
                <span style={{fontFamily:'var(--dgd-font-mono,monospace)',fontSize:13,fontWeight:700}}>{rE(op.val)}</span>
                <span style={{fontFamily:'var(--dgd-font-mono,monospace)',fontSize:12,color:op.prob>=80?'#16a34a':'#d97706',fontWeight:600}}>{op.prob}%</span>
                <span style={{fontFamily:'var(--dgd-font-mono,monospace)',fontSize:11,color:'#3b82f6'}}>= {rE(op.val*op.prob/100)}</span>
              </div>
              {drill?.id===op.id&&(
                <div style={{marginTop:8,paddingTop:8,borderTop:'1px solid var(--dgd-border-1)',fontSize:11,color:'var(--dgd-fg-2)',display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:6}}>
                  <div><strong>OP</strong> {op.id}</div>
                  <div><strong>Comercial</strong> {op.comercial}</div>
                  <div><strong>Fecho Est.</strong> {op.closeEst}</div>
                </div>
              )}
            </div>
          ))}
        </div>
      )}
    </div>
  );
};

// ─── 5. YTD FAMÍLIAS/ARTIGOS ──────────────────────────────────────────────────
const YTD_FAM = [
  { familia:'Mimaki Impressão', artigos:[
    { nome:'Mimaki UCJV300-160', ytdQty:4, ytdVal:194000, bp:280000 },
    { nome:'Mimaki JFX200-2513', ytdQty:2, ytdVal:144000, bp:200000 },
    { nome:'Mimaki CJV330-160',  ytdQty:6, ytdVal:208800, bp:240000 },
    { nome:'Mimaki UJV100-160',  ytdQty:3, ytdVal:85200,  bp:120000 },
    { nome:'Mimaki TS100-1600',  ytdQty:5, ytdVal:206000, bp:250000 },
  ]},
  { familia:'Mimaki Corte', artigos:[
    { nome:'Mimaki CG-130FX',  ytdQty:8,  ytdVal:56000, bp:72000 },
    { nome:'Mimaki CG-60FX',   ytdQty:12, ytdVal:60000, bp:84000 },
  ]},
  { familia:'Decal Consumíveis', artigos:[
    { nome:'Pack Decal Start',   ytdQty:22, ytdVal:408800, bp:528000 },
    { nome:'Pack Decal Pro',     ytdQty:14, ytdVal:347200, bp:432000 },
    { nome:'Pack Decal Premium', ytdQty:8,  ytdVal:288000, bp:336000 },
  ]},
  { familia:'Biond Soluções', artigos:[
    { nome:'Biond Pro 6000',    ytdQty:6,  ytdVal:74400,  bp:96000 },
    { nome:'Biond Starter Kit', ytdQty:10, ytdVal:69000,  bp:90000 },
  ]},
  { familia:'Sensek', artigos:[
    { nome:'Sensek Starter',  ytdQty:8, ytdVal:63200, bp:88000 },
    { nome:'Sensek Advanced', ytdQty:4, ytdVal:54000, bp:72000 },
  ]},
];

const useYTDData = (ano) => {
  const [state, setState] = React.useState({ data: null, loading: true, error: null, isLive: false });
  React.useEffect(() => {
    fetch(`/api/rpc/ytd?ano=${ano}`)
      .then(r => r.ok ? r.json() : Promise.reject(r.status))
      .then(json => {
        // Agrupar por família para a view
        const byFam = {};
        json.rows.forEach(r => {
          if (!byFam[r.familia]) byFam[r.familia] = { familia: r.familia, artigos: [] };
          byFam[r.familia].artigos.push({ nome: r.artigo, ytdQty: Number(r.qtd), ytdVal: Number(r.valor), bp: 0 });
        });
        const fams = Object.values(byFam)
          .sort((a, b) => b.artigos.reduce((s, x) => s + x.ytdVal, 0) - a.artigos.reduce((s, x) => s + x.ytdVal, 0))
          .slice(0, 20); // top 20 famílias
        setState({ data: fams, mensal: json.mensal, loading: false, error: null, isLive: true });
      })
      .catch(() => setState({ data: null, loading: false, error: null, isLive: false }));
  }, [ano]);
  return state;
};

const TabYTD = ({ ano }) => {
  const live = useYTDData(ano);
  const famData = live.isLive ? live.data : YTD_FAM;
  const [expanded, setExpanded] = React.useState({});
  const [sort, setSort] = React.useState({ col: 'ytdVal', dir: 'desc' });

  const toggleSort = (col) => setSort(s => ({ col, dir: s.col === col && s.dir === 'desc' ? 'asc' : 'desc' }));
  const sortIcon = (col) => sort.col !== col ? ' ↕' : sort.dir === 'desc' ? ' ↓' : ' ↑';

  const sorted = [...famData].sort((a, b) => {
    const fYtdV = f => f.artigos.reduce((s,x)=>s+x.ytdVal,0);
    const fYtdQ = f => f.artigos.reduce((s,x)=>s+x.ytdQty,0);
    const fBp   = f => f.artigos.reduce((s,x)=>s+x.bp,0);
    const fPct  = f => { const bp=fBp(f); return bp>0?fYtdV(f)/bp:0; };
    const fDev  = f => fYtdV(f)-fBp(f);
    const getV  = (f) => ({ ytdVal:fYtdV(f), ytdQty:fYtdQ(f), bp:fBp(f), pct:fPct(f), dev:fDev(f), name:f.familia }[sort.col] ?? fYtdV(f));
    return sort.dir === 'desc' ? getV(b) - getV(a) : getV(a) - getV(b);
  });
  return (
    <div>
      {live.isLive && (
        <div style={{marginBottom:10,padding:'6px 12px',borderRadius:6,background:'color-mix(in oklch,#22c55e 10%,transparent)',border:'1px solid color-mix(in oklch,#22c55e 30%,transparent)',fontSize:11,color:'#166534',display:'inline-flex',alignItems:'center',gap:6}}>
          <span style={{width:6,height:6,borderRadius:'50%',background:'#16a34a',display:'inline-block'}} />
          Dados reais Primavera · tipodoc FA/VD/FR (filtro conservador — afinar com Márcio)
        </div>
      )}
      {live.loading && <div style={{color:'var(--dgd-fg-3)',fontSize:13,padding:'20px 0'}}>A carregar dados Primavera...</div>}
      <div style={{overflowX:'auto',borderRadius:8,border:'1px solid var(--dgd-border-1)'}}>
        <table style={{borderCollapse:'collapse',width:'100%',minWidth:560}}>
          <thead>
            <tr style={{background:'var(--dgd-bg-surface)'}}>
              {[['Família / Artigo','name'],['YTD Qtd','ytdQty'],['YTD Valor','ytdVal'],['BP Anual','bp'],['% BP','pct'],['Desvio','dev']].map(([h,col],i)=>(
                <th key={h} onClick={()=>toggleSort(col)} style={{padding:'6px 10px',fontSize:10,fontWeight:600,color:sort.col===col?'var(--dgd-fg-1)':'var(--dgd-fg-3)',letterSpacing:'0.06em',fontFamily:'var(--dgd-font-mono,monospace)',borderBottom:'1px solid var(--dgd-border-1)',textAlign:i===0?'left':'right',cursor:'pointer',userSelect:'none',whiteSpace:'nowrap'}}>
                  {h}{sortIcon(col)}
                </th>
              ))}
            </tr>
          </thead>
          <tbody>
            {sorted.map(f=>{
              const fYtdV = f.artigos.reduce((s,a)=>s+a.ytdVal,0);
              const fBp   = f.artigos.reduce((s,a)=>s+a.bp,0);
              const fDev  = fYtdV-fBp;
              const isExp = expanded[f.familia];
              return (
                <React.Fragment key={f.familia}>
                  <tr style={{background:'color-mix(in oklch,#3b82f6 5%,transparent)',cursor:'pointer'}} onClick={()=>setExpanded(e=>({...e,[f.familia]:!isExp}))}>
                    <td style={{padding:'8px 10px',fontSize:12,fontWeight:700,color:'var(--dgd-fg-1)',borderBottom:'1px solid var(--dgd-border-1)'}}>
                      <span style={{marginRight:6,fontSize:10}}>{isExp?'▼':'▶'}</span>{f.familia}
                    </td>
                    <td style={{padding:'8px 10px',fontSize:12,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',fontWeight:600,borderBottom:'1px solid var(--dgd-border-1)'}}>{f.artigos.reduce((s,a)=>s+a.ytdQty,0)}</td>
                    <td style={{padding:'8px 10px',fontSize:12,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',fontWeight:600,borderBottom:'1px solid var(--dgd-border-1)'}}>{rE(fYtdV)}</td>
                    <td style={{padding:'8px 10px',fontSize:12,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',color:'var(--dgd-fg-2)',borderBottom:'1px solid var(--dgd-border-1)'}}>{rE(fBp)}</td>
                    <td style={{padding:'8px 10px',fontSize:12,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',borderBottom:'1px solid var(--dgd-border-1)',...dStyle(fYtdV,fBp)}}>{rPct(fYtdV,fBp)}</td>
                    <td style={{padding:'8px 10px',fontSize:12,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',borderBottom:'1px solid var(--dgd-border-1)',...dStyle(fDev,fBp)}}>{(fDev>=0?'+':'')+rE(fDev)}</td>
                  </tr>
                  {isExp&&f.artigos.map((a,ai)=>{
                    const dev = a.ytdVal-a.bp;
                    return (
                      <tr key={a.nome} style={{background:ai%2===0?'transparent':'color-mix(in oklch,#94a3b8 2%,transparent)'}}>
                        <td style={{padding:'6px 10px 6px 26px',fontSize:11.5,color:'var(--dgd-fg-2)',borderBottom:'1px solid var(--dgd-border-1)'}}>{a.nome}</td>
                        <td style={{padding:'6px 10px',fontSize:11.5,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',color:'var(--dgd-fg-1)',borderBottom:'1px solid var(--dgd-border-1)'}}>{a.ytdQty}</td>
                        <td style={{padding:'6px 10px',fontSize:11.5,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',color:'var(--dgd-fg-1)',borderBottom:'1px solid var(--dgd-border-1)'}}>{rE(a.ytdVal)}</td>
                        <td style={{padding:'6px 10px',fontSize:11.5,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',color:'var(--dgd-fg-3)',borderBottom:'1px solid var(--dgd-border-1)'}}>{rE(a.bp)}</td>
                        <td style={{padding:'6px 10px',fontSize:11.5,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',borderBottom:'1px solid var(--dgd-border-1)',...dStyle(a.ytdVal,a.bp)}}>{rPct(a.ytdVal,a.bp)}</td>
                        <td style={{padding:'6px 10px',fontSize:11.5,fontFamily:'var(--dgd-font-mono,monospace)',textAlign:'right',borderBottom:'1px solid var(--dgd-border-1)',...dStyle(dev,a.bp)}}>{(dev>=0?'+':'')+rE(dev)}</td>
                      </tr>
                    );
                  })}
                </React.Fragment>
              );
            })}
          </tbody>
        </table>
      </div>
    </div>
  );
};

// ─── 6. AI MEDIA SALES ───────────────────────────────────────────────────────
const MEDIA_ALERTS = [
  { tipo:'perda_vendas',   sev:'alto',  cliente:'Gráfica Lusitana',    msg:'Vendas Dez-Abr: -38% vs período anterior. Consumo tinta normal, zero media.', action:'Open OP Reunião', comercial:'Daniel Silva' },
  { tipo:'margem_neg',     sev:'alto',  cliente:'Print & Go Lda',       msg:'Margem bruta Jun: -4.2%. Desconto excessivo aplicado por fora do sistema.', action:'Sugestão Estratégia', comercial:'Daniel Silva' },
  { tipo:'so_tintas',      sev:'medio', cliente:'Décor Viseu',           msg:'12 meses só consumíveis, sem renovação de equipamento. Potencial upgrade.', action:'Open OP + NextStep', comercial:'Carla Ferreira' },
  { tipo:'printplan_desv', sev:'medio', cliente:'Decorama Lda',          msg:'PrintPlan: consumo real 8.200 m² vs contrato 12.000 m²/ano (-32%). Email correcção pendente.', action:'Enviar email correcção', comercial:'Cláudia Moreira' },
  { tipo:'printplan_desv', sev:'medio', cliente:'Sintra Digital',         msg:'PrintPlan: consumo 15.400 m² vs contrato 10.000 m²/ano (+54%). Recalcular preço semestral.', action:'Enviar email correcção', comercial:'Carla Ferreira' },
  { tipo:'digirent_desv',  sev:'alto',  cliente:'EspacoArte Lisboa',     msg:'Digirent: 3 mensalidades em atraso. Total em dívida: €2.840. Email regularização urgente.', action:'Enviar email regularização', comercial:'Daniel Silva' },
  { tipo:'digirent_desv',  sev:'medio', cliente:'Publi Braga',            msg:'Digirent: utilização média 18h/dia vs contrato 8h/dia. Renegociar condições.', action:'Enviar email medidas', comercial:'Javier García' },
  { tipo:'so_tintas',      sev:'medio', cliente:'Gráficas Sur S.L.',      msg:'8 meses só tintas. Sem interesse em upgrade mas consumo crescente. Proposta media bundle.', action:'AI Sugestão Comercial', comercial:'Javier García' },
];

const TIPO_LABELS = { perda_vendas:'Perdas de Vendas', margem_neg:'Margem Negativa', so_tintas:'Só Tintas', printplan_desv:'PrintPlan Desvio', digirent_desv:'Digirent Desvio' };
const TIPO_COLORS = { perda_vendas:'#dc2626', margem_neg:'#dc2626', so_tintas:'#d97706', printplan_desv:'#d97706', digirent_desv:'#dc2626' };

const TabMediaSales = () => {
  const [filtroTipo, setFiltroTipo] = React.useState('todos');
  const [acao, setAcao] = React.useState(null);
  const tipos = ['todos',...new Set(MEDIA_ALERTS.map(a=>a.tipo))];
  const alertas = filtroTipo==='todos' ? MEDIA_ALERTS : MEDIA_ALERTS.filter(a=>a.tipo===filtroTipo);

  return (
    <div>
      {/* Resumo */}
      <div style={{display:'flex',gap:8,marginBottom:14,flexWrap:'wrap'}}>
        {[
          { l:'Alto risco', v:MEDIA_ALERTS.filter(a=>a.sev==='alto').length, c:'#dc2626' },
          { l:'Médio risco', v:MEDIA_ALERTS.filter(a=>a.sev==='medio').length, c:'#d97706' },
          { l:'Acções pendentes', v:MEDIA_ALERTS.length, c:'#3b82f6' },
        ].map(k=>(
          <div key={k.l} style={{padding:'8px 14px',borderRadius:8,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)'}}>
            <div style={{fontSize:9.5,color:'var(--dgd-fg-3)',fontFamily:'var(--dgd-font-mono,monospace)',letterSpacing:'0.08em',marginBottom:2}}>{k.l}</div>
            <div className="font-display" style={{fontSize:20,fontWeight:700,color:k.c,letterSpacing:'-0.02em'}}>{k.v}</div>
          </div>
        ))}
      </div>

      {/* Filtros tipo */}
      <div style={{display:'flex',gap:4,marginBottom:12,flexWrap:'wrap'}}>
        {tipos.map(t=>(
          <button key={t} onClick={()=>setFiltroTipo(t)} style={{padding:'4px 10px',borderRadius:6,fontSize:11,fontWeight:filtroTipo===t?700:400,background:filtroTipo===t?'var(--dgd-fg-1)':'var(--dgd-bg-card,white)',color:filtroTipo===t?'white':'var(--dgd-fg-2)',border:'1px solid '+(filtroTipo===t?'var(--dgd-fg-1)':'var(--dgd-border-1)'),cursor:'pointer'}}>
            {t==='todos'?'Todos':TIPO_LABELS[t]}
          </button>
        ))}
      </div>

      {/* Alertas */}
      {alertas.map((a,i)=>(
        <div key={i} style={{padding:'12px 14px',borderRadius:8,marginBottom:8,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)',borderLeft:'3px solid '+(TIPO_COLORS[a.tipo]||'#94a3b8')}}>
          <div style={{display:'flex',alignItems:'flex-start',gap:10,flexWrap:'wrap'}}>
            <div style={{flex:1,minWidth:0}}>
              <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:4,flexWrap:'wrap'}}>
                <span style={badgeStyle(a.sev)}>{a.sev.toUpperCase()}</span>
                <span style={{fontSize:10,padding:'2px 7px',borderRadius:4,background:`color-mix(in oklch,${TIPO_COLORS[a.tipo]} 10%,transparent)`,color:TIPO_COLORS[a.tipo],fontWeight:600,letterSpacing:'0.04em'}}>{TIPO_LABELS[a.tipo]}</span>
                <span style={{fontSize:12,fontWeight:600}}>{a.cliente}</span>
                <span style={{fontSize:11,color:'var(--dgd-fg-3)'}}>· {a.comercial}</span>
              </div>
              <div style={{fontSize:12,color:'var(--dgd-fg-2)',lineHeight:1.5}}>{a.msg}</div>
            </div>
            <div style={{display:'flex',flexDirection:'column',gap:4,alignItems:'flex-end',flexShrink:0}}>
              <button onClick={()=>setAcao(acao===i?null:i)} style={{padding:'5px 12px',borderRadius:6,fontSize:11,fontWeight:600,background:acao===i?'var(--dgd-fg-1)':'color-mix(in oklch,#3b82f6 12%,transparent)',color:acao===i?'white':'#3b82f6',border:'1px solid '+(acao===i?'var(--dgd-fg-1)':'color-mix(in oklch,#3b82f6 30%,transparent)'),cursor:'pointer'}}>
                AI {a.action}
              </button>
            </div>
          </div>
          {acao===i&&(
            <div style={{marginTop:10,paddingTop:10,borderTop:'1px solid var(--dgd-border-1)',background:'color-mix(in oklch,#3b82f6 4%,transparent)',borderRadius:6,padding:'10px 12px',fontSize:12,color:'var(--dgd-fg-2)',fontStyle:'italic'}}>
              Acção AI — <strong style={{color:'var(--dgd-fg-1)'}}>TODO: activar quando AI endpoint disponível.</strong> Esta acção vai {a.tipo==='printplan_desv'||a.tipo==='digirent_desv'?'gerar e enviar email automático ao cliente com desvios e proposta de correcção':'abrir OP no FM em stage 20 e notificar '+(a.comercial)+' com NextStep gerado por AI'}.
            </div>
          )}
        </div>
      ))}
    </div>
  );
};

// ─── 7. SUGESTÕES AI ─────────────────────────────────────────────────────────
const SUGESTOES_AI = [
  { comercial:'Daniel Silva', prioridade:'alta', tipo:'Pipeline', sugestao:'OP-2026-0389 (Print & Go, €72k) está em stage 65 há 34 dias. Probabilidade de stall elevada. Sugerido: propor demo técnica presencial + comparativo ROI vs concorrente.' },
  { comercial:'Daniel Silva', prioridade:'media', tipo:'Retenção', sugestao:'Gráfica Lusitana: -38% vendas YTD. Histórico mostra compra de upgrade a cada 3 anos — o último foi em Abr 2023. Janela ideal para proposta Mimaki UCJV.' },
  { comercial:'Carla Ferreira', prioridade:'alta', tipo:'Upsell', sugestao:'Décor Viseu: 12 meses só consumíveis, MRR estável. Cliente com expansão recente (2 novas lojas). Potencial bundle equipamento + PrintPlan. Abrir OP com contexto AI.' },
  { comercial:'Carla Ferreira', prioridade:'media', tipo:'Risco', sugestao:'Sintra Digital: consumo PrintPlan +54% acima do contrato. Risco de insatisfação no próximo ciclo de facturação. Contactar proactivamente antes da factura.' },
  { comercial:'Javier García', prioridade:'media', tipo:'Cross-sell', sugestao:'Imprenta Málaga: equipamento Mimaki TS100 em fecho. Perfil compatível com pack Sensek para aplicações têxteis. Incluir demonstração no fecho da OP.' },
  { comercial:'Cláudia Moreira', prioridade:'alta', tipo:'Retenção', sugestao:'Decorama Lda: PrintPlan 32% abaixo do contrato. 2 pagamentos em dia mas risco de rescisão no semestre. Agendar visita técnica + proposta ajuste contrato.' },
  { comercial:'Paulo Neves', prioridade:'media', tipo:'Pipeline', sugestao:'Pipeline Biond muito concentrado: 1 OP vale 63% do total. Diversificar — identificar 3-4 clínicas com perfil compatível para abertura de SPIN.' },
];

const TabSugestoes = () => {
  const [filtro, setFiltro] = React.useState('todos');
  const comerciais = ['todos',...new Set(SUGESTOES_AI.map(s=>s.comercial))];
  const lista = filtro==='todos' ? SUGESTOES_AI : SUGESTOES_AI.filter(s=>s.comercial===filtro);

  return (
    <div>
      <div style={{display:'flex',gap:4,marginBottom:12,flexWrap:'wrap'}}>
        {comerciais.map(c=>(
          <button key={c} onClick={()=>setFiltro(c)} style={{padding:'4px 10px',borderRadius:6,fontSize:11,fontWeight:filtro===c?700:400,background:filtro===c?'var(--dgd-fg-1)':'var(--dgd-bg-card,white)',color:filtro===c?'white':'var(--dgd-fg-2)',border:'1px solid '+(filtro===c?'var(--dgd-fg-1)':'var(--dgd-border-1)'),cursor:'pointer'}}>
            {c==='todos'?'Todos':c.split(' ')[0]}
          </button>
        ))}
      </div>
      {lista.map((s,i)=>(
        <div key={i} style={{padding:'12px 14px',borderRadius:8,marginBottom:8,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)',borderLeft:'3px solid '+(s.prioridade==='alta'?'#7c3aed':'#3b82f6')}}>
          <div style={{display:'flex',alignItems:'center',gap:8,marginBottom:6,flexWrap:'wrap'}}>
            <span style={{...badgeStyle(s.prioridade==='alta'?'alto':'medio'),background:s.prioridade==='alta'?'#ede9fe':'#dbeafe',color:s.prioridade==='alta'?'#5b21b6':'#1e40af'}}>{s.prioridade.toUpperCase()}</span>
            <span style={{fontSize:10,padding:'2px 7px',borderRadius:4,background:'color-mix(in oklch,#7c3aed 10%,transparent)',color:'#7c3aed',fontWeight:600,letterSpacing:'0.04em'}}>{s.tipo}</span>
            <span style={{fontSize:12,fontWeight:600,color:'var(--dgd-fg-1)'}}>{s.comercial}</span>
          </div>
          <div style={{fontSize:12.5,color:'var(--dgd-fg-2)',lineHeight:1.6}}>{s.sugestao}</div>
          <div style={{marginTop:8,display:'flex',gap:6}}>
            <button style={{padding:'4px 10px',borderRadius:5,fontSize:11,fontWeight:600,background:'color-mix(in oklch,#7c3aed 10%,transparent)',color:'#7c3aed',border:'1px solid color-mix(in oklch,#7c3aed 25%,transparent)',cursor:'not-allowed',opacity:0.7}}>
              AI Aplicar acção
            </button>
            <button style={{padding:'4px 10px',borderRadius:5,fontSize:11,fontWeight:600,background:'transparent',color:'var(--dgd-fg-3)',border:'1px solid var(--dgd-border-1)',cursor:'not-allowed',opacity:0.7}}>
              Ignorar
            </button>
          </div>
        </div>
      ))}
    </div>
  );
};

// ─── Componente principal ─────────────────────────────────────────────────────
const RPC_TABS_ALL   = [
  { id:'rpc',        label:'Mapa RPC' },
  { id:'money',      label:'Show me the Money' },
  { id:'forecast',   label:'Forecast' },
  { id:'predit',     label:'Preditividade' },
  { id:'ytd',        label:'YTD Famílias' },
  { id:'mediasales', label:'Media Sales AI' },
  { id:'sugestoes',  label:'Sugestões AI' },
];
const RPC_TABS_BOARD = [
  { id:'rpc',        label:'Mapa RPC' },
  { id:'money',      label:'Show me the Money' },
];

// Permissões — resolve com base no userTipo
const rpcPermissions = (userTipo) => {
  const t = (userTipo || '').toLowerCase();
  if (t === 'admin' || t === 'manager')                    return { level: 'manager', tabs: RPC_TABS_ALL };
  if (t === 'c_suite' || t === 'chairman' || t === 'director') return { level: 'board',   tabs: RPC_TABS_BOARD };
  return { level: 'none', tabs: [] };
};

const ScreenComercialRPC = ({ vendedorId, userTipo, userName, user }) => {
  const perm = rpcPermissions(userTipo);

  // Todos os hooks têm de ser chamados incondicionalmente (React rules of hooks)
  const [tab, setTab]   = React.useState(perm.tabs[0]?.id || 'rpc');
  const [ano, setAno]   = React.useState(RPC_ANO_DEF);
  const [marca, setMarca] = React.useState('Mimaki PT');
  const isManager  = !!vendedorId;
  const teamState  = useTeam(isManager ? user?.id : null);
  const ytdState   = useYTDMensal(ano);
  // FM pipeline — carrega PT e ES em paralelo (sempre, independente da marca activa)
  const fmPT = useFMPipeline('PTDIG', ano);
  const fmES = useFMPipeline('DIGES', ano);

  // Sem acesso (após todos os hooks)
  if (perm.level === 'none') {
    return (
      <div style={{height:'100%',display:'flex',alignItems:'center',justifyContent:'center',background:'var(--dgd-bg-app,#f8fafc)'}}>
        <div style={{textAlign:'center',maxWidth:380,padding:'40px 32px',borderRadius:12,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)'}}>
          <div style={{fontSize:32,marginBottom:12}}>🔒</div>
          <div style={{fontSize:16,fontWeight:600,color:'var(--dgd-fg-1)',marginBottom:8}}>Acesso restrito</div>
          <div style={{fontSize:13,color:'var(--dgd-fg-3)',lineHeight:1.6}}>
            O Relatório de Produção Comercial está disponível para gestores e administradores.<br/>
            Contacta o administrador para acesso.
          </div>
        </div>
      </div>
    );
  }

  // activeComs: equipa BD se disponível, senão mock filtrado por marca
  const marcasVisiveis = isManager ? [] : MARCAS;
  const marcasComTab   = ['rpc','money','forecast','predit'].includes(tab);

  const mockComs = COMERCIAIS_MOCK.filter(c => c.marca === marca);
  const activeComs = (isManager && teamState.team) ? teamState.team : mockComs;

  // Merge FM PT + ES num único mapa byVendedor
  const fmByV = { ...(fmPT.byVendedor || {}), ...(fmES.byVendedor || {}) };

  // ytdByV: começa com dados Primavera (PT); sobrepõe com FM wonValor para ES (sem Primavera ES)
  const ytdByV = { ...(ytdState.byVendedor || {}) };
  Object.entries(fmES.byVendedor || {}).forEach(([v, d]) => {
    if (!ytdByV[v]) ytdByV[v] = d.wonValor; // ES: só usa FM wonValor se não tiver Primavera
  });

  const getVendas = (vendedor) => ytdByV[vendedor] || (fmByV[vendedor] ? fmByV[vendedor].wonValor : _null12);
  const coms = activeComs;
  const ytdV = coms.reduce((s,c)=>s+getVendas(c.vendedor).slice(0,RPC_MES_FECH+1).reduce((a,v)=>a+(v||0),0),0);
  const ytdB = 0; // BP pendente: layout OBJECTIVOS (Walter)
  const hasFMData = !!(fmPT.byVendedor || fmES.byVendedor);
  const hasRealData = !!ytdState.byVendedor || hasFMData;

  return (
    <FMCtx.Provider value={fmByV}>
    <YTDCtx.Provider value={ytdByV}>
    <div className="scrollbar" style={{height:'100%',overflowY:'auto',background:'var(--dgd-bg-app,#f8fafc)'}}>
      <div style={{maxWidth:1200,padding:'18px 24px 80px'}}>

        {/* Banner board */}
        {perm.level === 'board' && (
          <div style={{marginBottom:12,padding:'6px 12px',borderRadius:6,background:'color-mix(in oklch,#3b82f6 8%,transparent)',border:'1px solid color-mix(in oklch,#3b82f6 25%,transparent)',fontSize:11,color:'#1e40af',display:'flex',alignItems:'center',gap:6}}>
            <span style={{fontWeight:700}}>Visão executiva</span> · leitura apenas · Mapa RPC e facturação real
          </div>
        )}

        {/* Header */}
        <div style={{display:'flex',alignItems:'flex-start',justifyContent:'space-between',flexWrap:'wrap',gap:10,marginBottom:12}}>
          <div>
            <div style={{fontSize:10,color:'var(--dgd-fg-3)',fontFamily:'var(--dgd-font-mono,monospace)',letterSpacing:'0.1em',marginBottom:2}}>COMERCIAL · PRODUÇÃO COMERCIAL · {RPC_ANO_DEF}</div>
            <h2 className="font-display" style={{margin:0,fontSize:21,fontWeight:600,letterSpacing:'-0.01em',color:'var(--dgd-fg-1)'}}>
              {perm.tabs.find(t=>t.id===tab)?.label}
              {marcasComTab&&<span style={{fontSize:13,fontWeight:400,color:'var(--dgd-fg-3)',marginLeft:8}}>· {marca}</span>}
              {hasRealData
                ? <span style={{fontSize:11,fontWeight:400,color:'#166534',marginLeft:10,fontFamily:'var(--dgd-font-mono,monospace)',background:'color-mix(in oklch,#22c55e 10%,transparent)',padding:'2px 7px',borderRadius:4,border:'1px solid color-mix(in oklch,#22c55e 35%,transparent)'}}>REAL</span>
                : <span style={{fontSize:11,fontWeight:400,color:'#b45309',marginLeft:10,fontFamily:'var(--dgd-font-mono,monospace)',background:'color-mix(in oklch,#f59e0b 10%,transparent)',padding:'2px 7px',borderRadius:4,border:'1px solid color-mix(in oklch,#f59e0b 35%,transparent)'}}>MOCK</span>
              }
            </h2>
          </div>
          <div style={{display:'flex',alignItems:'center',gap:8,flexWrap:'wrap'}}>
            {marcasComTab && (isManager
              ? <span style={{fontSize:11,color:'var(--dgd-fg-2)',padding:'4px 10px',borderRadius:6,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)'}}>{userName || 'A minha equipa'}</span>
              : marcasVisiveis.map(m=>(
                  <button key={m} onClick={()=>setMarca(m)} style={{padding:'4px 10px',borderRadius:6,fontSize:11,fontWeight:marca===m?700:400,background:marca===m?'var(--dgd-fg-1)':'var(--dgd-bg-card,white)',color:marca===m?'white':'var(--dgd-fg-2)',border:'1px solid '+(marca===m?'var(--dgd-fg-1)':'var(--dgd-border-1)'),cursor:'pointer'}}>
                    {m}
                  </button>
                ))
            )}
            <div style={{display:'flex',border:'1px solid var(--dgd-border-1)',borderRadius:7,overflow:'hidden',background:'var(--dgd-bg-card,white)'}}>
              {[2025,2026].map(y=>(
                <button key={y} onClick={()=>setAno(y)} style={{padding:'4px 11px',fontSize:12,fontWeight:y===ano?700:400,background:y===ano?'var(--dgd-fg-1)':'transparent',color:y===ano?'white':'var(--dgd-fg-2)',border:'none',cursor:'pointer'}}>{y}</button>
              ))}
            </div>
          </div>
        </div>

        {/* KPIs rápidos (só quando há marca) */}
        {marcasComTab&&(
          <div style={{display:'flex',gap:8,marginBottom:14,flexWrap:'wrap'}}>
            {[
              { l:'VENDAS YTD', v:rE(ytdV), c:ytdV>=ytdB?'#16a34a':'#dc2626' },
              { l:'BP YTD', v:rE(ytdB), c:'var(--dgd-fg-2)' },
              { l:'DESVIO', v:(ytdV-ytdB>=0?'+':'')+rE(ytdV-ytdB), c:ytdV>=ytdB?'#16a34a':'#dc2626' },
              { l:'% BP', v:rPct(ytdV,ytdB), c:ytdV/ytdB>=1?'#16a34a':ytdV/ytdB>=0.85?'#d97706':'#dc2626' },
            ].map(k=>(
              <div key={k.l} style={{padding:'8px 14px',borderRadius:8,background:'var(--dgd-bg-card,white)',border:'1px solid var(--dgd-border-1)'}}>
                <div style={{fontSize:9.5,color:'var(--dgd-fg-3)',fontFamily:'var(--dgd-font-mono,monospace)',letterSpacing:'0.08em',marginBottom:2}}>{k.l}</div>
                <div className="font-display" style={{fontSize:18,fontWeight:700,color:k.c,letterSpacing:'-0.02em'}}>{k.v}</div>
              </div>
            ))}
          </div>
        )}

        {/* Sub-tabs */}
        <div style={{display:'flex',gap:2,marginBottom:16,borderBottom:'1px solid var(--dgd-border-1)',flexWrap:'wrap'}}>
          {perm.tabs.map(t=>(
            <button key={t.id} onClick={()=>setTab(t.id)} style={{padding:'7px 14px',fontSize:12,fontWeight:tab===t.id?700:400,color:tab===t.id?'var(--dgd-fg-1)':'var(--dgd-fg-3)',background:'none',border:'none',borderBottom:tab===t.id?'2px solid var(--dgd-fg-1)':'2px solid transparent',cursor:'pointer',marginBottom:-1,whiteSpace:'nowrap'}}>
              {t.label}
            </button>
          ))}
        </div>

        {/* Conteúdo */}
        {teamState.loading && isManager && <div style={{padding:'20px 0',color:'var(--dgd-fg-3)',fontSize:12}}>A carregar equipa...</div>}
        {tab==='rpc'        && <TabMapaRPC coms={activeComs} />}
        {tab==='money'      && <TabShowMoney coms={activeComs} />}
        {tab==='forecast'   && <TabForecast coms={activeComs} />}
        {tab==='predit'     && <TabPreditividade coms={activeComs} />}
        {tab==='ytd'        && <TabYTD ano={ano} />}
        {tab==='mediasales' && <TabMediaSales />}
        {tab==='sugestoes'  && <TabSugestoes />}

        {/* Nota dados */}
        {hasRealData
          ? <div style={{marginTop:24,padding:'10px 14px',borderRadius:7,background:'color-mix(in oklch,#22c55e 7%,transparent)',border:'1px solid color-mix(in oklch,#22c55e 25%,transparent)',fontSize:11,color:'#166534'}}>
              <strong>Dados em tempo real</strong> —
              {ytdState.byVendedor ? ' VENDAS PT: Primavera (32 tipos Active=1).' : ''}
              {fmPT.byVendedor ? ` FM PT: ${fmPT.totalOps||0} OPs ${ano} (OPMANAGERF9/OPTMKT/OPTCOM).` : ''}
              {fmES.byVendedor ? ` FM ES: ${fmES.totalOps||0} OPs ${ano} (OPMANAGERF9/OPTMKT/OPTCOM/VENDAS ES).` : ''}
              {' '}SPIN/BP/F9 pendente layouts Walter (SPINS, OBJECTIVOS, ForecastDate).
            </div>
          : <div style={{marginTop:24,padding:'10px 14px',borderRadius:7,background:'color-mix(in oklch,#f59e0b 7%,transparent)',border:'1px solid color-mix(in oklch,#f59e0b 25%,transparent)',fontSize:11,color:'#92400e'}}>
              <strong>A carregar dados...</strong> — FM GestorConnect + Primavera sync.
            </div>
        }
      </div>
    </div>
    </YTDCtx.Provider>
    </FMCtx.Provider>
  );
};

window.ScreenComercialRPC = ScreenComercialRPC;
