<?php
/**
 * Compras / Dashboard do Comprador — visao completa para tomada de decisao.
 * Shell instantaneo: sem queries no render. Dados via fetch() apos DOM pronto.
 */
$actionUrl = '/compras/dashboard';
?>
<div class="pbi-page-header">
    <div class="pbi-page-icon"><i class="bi bi-cart3"></i></div>
    <div>
        <div class="pbi-page-title">Painel de Compras</div>
        <div class="pbi-page-subtitle" id="cmp-periodo-label">Carregando...</div>
    </div>
    <div class="ms-auto d-flex gap-2 align-items-center">
        <span id="cmp-badge" class="badge bg-secondary">...</span>
        <button id="btnCmpAtualizar" class="btn btn-sm btn-outline-secondary" title="Atualizar">
            <i class="bi bi-arrow-clockwise"></i>
        </button>
    </div>
</div>

<?php include __DIR__ . '/_submenu.php' ?>
<?php include __DIR__ . '/_filtro.php'; ?>

<!-- ── Caixa de explicação ────────────────────────────────────────────────── -->
<div class="pbi-card mb-3" style="background:#f8fafc">
    <div style="padding:.75rem 1.25rem">
        <div class="mb-2"><strong>🛒 O que mostra esta tela:</strong> tudo que você comprou no período — quanto gastou no total, com quais fornecedores, quais produtos, e quanto isso representa em relação ao que vendeu (CMV %).</div>
        <div class="row g-2" style="font-size:.85rem">
            <div class="col-md-6"><strong>Total Comprado</strong> = soma de todas as notas de entrada do período</div>
            <div class="col-md-6"><strong>Ticket Médio por Nota</strong> = valor médio de cada nota (total ÷ qtd notas)</div>
            <div class="col-md-6"><strong>Descontos Obtidos</strong> = quanto você negociou de desconto nas compras</div>
            <div class="col-md-6"><strong>CMV %</strong> = quanto você gastou comprando para cada R$ 100 vendidos. <span style="color:#16a34a">Abaixo de 70% é saudável</span>; acima de 85% é sinal de alerta</div>
        </div>
    </div>
</div>

<!-- ── KPIs ────────────────────────────────────────────────────────────────── -->
<div class="row g-3 mb-4" id="cmp-kpi-row">
    <?php
    $kpidefs = [
        ['cmp-kpi-total',    'bi-bag-fill',       'Total Comprado',      'text-accent'],
        ['cmp-kpi-notas',    'bi-receipt',         'Notas de Entrada',   ''],
        ['cmp-kpi-forn',     'bi-truck',           'Fornecedores Ativos', ''],
        ['cmp-kpi-ticket',   'bi-calculator',      'Ticket Médio por Nota',   ''],
        ['cmp-kpi-desc',     'bi-tag-fill',        'Descontos Obtidos',   'text-success'],
        ['cmp-kpi-cmv',      'bi-percent',         'CMV % (Compras ÷ Vendas)', ''],
        // KPIs extras (roadmap 06/2026) — concentração / devoluções / impostos
        ['cmp-kpi-conc',     'bi-pie-chart-fill',  'Concentração Top 1', ''],
        ['cmp-kpi-devol',    'bi-arrow-return-left','Devoluções',        'text-warning'],
        ['cmp-kpi-imp',      'bi-receipt-cutoff',  'Impostos + Frete',   ''],
    ];
    foreach ($kpidefs as [$id, $ico, $lbl, $cls]): ?>
    <div class="col-6 col-md-4 col-lg-2">
        <div class="pbi-kpi-card" id="<?= $id ?>">
            <div class="pbi-kpi-label"><i class="bi <?= $ico ?> me-1 opacity-50"></i><?= $lbl ?></div>
            <div class="pbi-kpi-valor <?= $cls ?> pbi-skeleton" style="height:1.6rem;border-radius:4px">&nbsp;</div>
            <div class="pbi-kpi-sub" id="<?= $id ?>-sub"></div>
        </div>
    </div>
    <?php endforeach; ?>
</div>

<!-- ── Comparativo YoY (mês anterior + ano anterior) ──────────────────────── -->
<div class="row g-3 mb-4" id="cmp-yoy-row">
    <div class="col-12 col-md-4">
        <div class="pbi-kpi-card" id="cmp-yoy-mes">
            <div class="pbi-kpi-label"><i class="bi bi-arrow-left-right me-1 opacity-50"></i>vs Mês Anterior</div>
            <div class="pbi-kpi-valor pbi-skeleton" style="height:1.6rem;border-radius:4px">&nbsp;</div>
            <div class="pbi-kpi-sub" id="cmp-yoy-mes-sub"></div>
        </div>
    </div>
    <div class="col-12 col-md-4">
        <div class="pbi-kpi-card" id="cmp-yoy-ano">
            <div class="pbi-kpi-label"><i class="bi bi-calendar-event me-1 opacity-50"></i>vs Mesmo Período Ano Anterior</div>
            <div class="pbi-kpi-valor pbi-skeleton" style="height:1.6rem;border-radius:4px">&nbsp;</div>
            <div class="pbi-kpi-sub" id="cmp-yoy-ano-sub"></div>
        </div>
    </div>
    <div class="col-12 col-md-4">
        <div class="pbi-kpi-card" id="cmp-yoy-ticket">
            <div class="pbi-kpi-label"><i class="bi bi-calculator me-1 opacity-50"></i>Ticket Médio vs Ano Anterior</div>
            <div class="pbi-kpi-valor pbi-skeleton" style="height:1.6rem;border-radius:4px">&nbsp;</div>
            <div class="pbi-kpi-sub" id="cmp-yoy-ticket-sub"></div>
        </div>
    </div>
</div>

<div class="pbi-hint mb-3" style="margin-top:0">Ticket Médio por Nota = valor médio de cada nota de entrada. CMV % = quanto você gastou comprando para cada R$ 100 que vendeu (compras ÷ vendas); abaixo de 70% é saudável. <strong>Concentração Top 1</strong> = % do fornecedor #1 sobre o total — acima de 40% indica dependência alta. <strong>vs mês/ano anterior</strong>: gastar MENOS é bom (verde); gastar MAIS é alerta (vermelho).</div>

<!-- ── Evolucao Diaria (full width) ───────────────────────────────────────── -->
<div class="pbi-card mb-4">
    <div class="pbi-card-header">
        <i class="bi bi-graph-up me-2 text-accent"></i>Evolução de Compras no Período
        <span class="ms-auto text-muted small" id="cmp-evol-info"></span>
    </div>
    <div class="pbi-card-body">
        <div class="pbi-hint mb-2" style="margin-top:0">Quanto foi comprado em cada dia do período. Barras = valor comprado; linha = quantidade de notas.</div>
        <div id="cmp-evol-chart" style="height:240px;width:100%"></div>
    </div>
</div>

<!-- ── Fornecedores + Participacao ────────────────────────────────────────── -->
<div class="row g-3 mb-4">
    <div class="col-12 col-lg-7">
        <div class="pbi-card h-100">
            <div class="pbi-card-header">
                <i class="bi bi-bar-chart-horizontal me-2 text-accent"></i>Top Fornecedores por Valor
            </div>
            <div class="pbi-card-body">
                <div class="pbi-hint mb-2" style="margin-top:0">Fornecedores onde você mais gastou no período, do maior para o menor.</div>
                <div id="cmp-forn-chart" style="height:280px;width:100%"></div>
            </div>
        </div>
    </div>
    <div class="col-12 col-lg-5">
        <div class="pbi-card h-100">
            <div class="pbi-card-header">
                <i class="bi bi-pie-chart me-2 text-accent"></i>Participação por Fornecedor
            </div>
            <div class="pbi-card-body">
                <div class="pbi-hint mb-2" style="margin-top:0">Fatia de cada fornecedor no total comprado. % mostra a participação de cada um.</div>
                <div id="cmp-forn-donut" style="height:320px;width:100%"></div>
            </div>
        </div>
    </div>
</div>

<!-- ── Dia da Semana + Top Itens por Valor ────────────────────────────────── -->
<div class="row g-3 mb-4">
    <div class="col-12 col-lg-5">
        <div class="pbi-card h-100">
            <div class="pbi-card-header">
                <i class="bi bi-calendar-week me-2 text-accent"></i>Compras por Dia da Semana
                <small class="text-muted fw-normal ms-1" style="font-size:.72rem">(padrão de compras)</small>
            </div>
            <div class="pbi-card-body">
                <div class="pbi-hint mb-2" style="margin-top:0">Em quais dias da semana você costuma comprar mais. Ajuda a enxergar a rotina de compras.</div>
                <div id="cmp-diasem-chart" style="height:240px;width:100%"></div>
            </div>
        </div>
    </div>
    <div class="col-12 col-lg-7">
        <div class="pbi-card h-100">
            <div class="pbi-card-header">
                <i class="bi bi-box-seam me-2 text-accent"></i>Top Itens por Valor Comprado
            </div>
            <div class="pbi-card-body">
                <div class="pbi-hint mb-2" style="margin-top:0">Produtos em que você mais gastou (preço × quantidade) no período.</div>
                <div id="cmp-itens-val-chart" style="height:240px;width:100%"></div>
            </div>
        </div>
    </div>
</div>

<!-- ── Ranking de Fornecedores ────────────────────────────────────────────── -->
<div class="pbi-card mb-4">
    <div class="pbi-card-header">
        <i class="bi bi-table me-2 text-accent"></i>Ranking de Fornecedores
        <span id="cmp-forn-badge" class="badge bg-secondary ms-2" style="display:none"></span>
        <span class="ms-auto">
            <span class="badge me-1" style="background:#22c55e22;color:#16a34a;border:1px solid #22c55e55">A</span>
            <span class="badge me-1" style="background:#f59e0b22;color:#b45309;border:1px solid #f59e0b55">B</span>
            <span class="badge" style="background:#94a3b822;color:#475569;border:1px solid #94a3b855">C</span>
            <small class="text-muted ms-1" style="font-size:.7rem">Curva ABC</small>
        </span>
    </div>
    <div class="pbi-card-body p-0">
        <div class="pbi-hint mb-2" style="margin-top:0;padding:8px 12px 0">% Part. = quanto o fornecedor representa do total comprado. Curva ABC: A = poucos fornecedores que somam a maior parte dos gastos; C = os de menor peso.</div>
        <div class="table-responsive">
            <table class="pbi-table" id="cmp-forn-tabela">
                <thead>
                    <tr>
                        <th style="width:32px">#</th>
                        <th>Fornecedor</th>
                        <th class="text-end">Notas</th>
                        <th class="text-end">Total Comprado</th>
                        <th class="text-end">% Part.</th>
                        <th class="text-end">Ticket Médio</th>
                        <th class="text-end">Desconto</th>
                        <th class="text-end">Última Compra</th>
                        <th class="text-center">Curva</th>
                        <th style="min-width:90px">Participação</th>
                    </tr>
                </thead>
                <tbody id="cmp-forn-body">
                    <tr><td colspan="10" class="text-center text-muted py-3">Carregando...</td></tr>
                </tbody>
                <tfoot id="cmp-forn-foot"></tfoot>
            </table>
        </div>
    </div>
</div>

<!-- ── Top Itens por Qtd + Tabela de Itens ───────────────────────────────── -->
<div class="row g-3 mb-4">
    <div class="col-12 col-lg-6">
        <div class="pbi-card h-100">
            <div class="pbi-card-header">
                <i class="bi bi-sort-numeric-down me-2 text-accent"></i>Top Itens por Quantidade
            </div>
            <div class="pbi-card-body">
                <div class="pbi-hint mb-2" style="margin-top:0">Produtos que você mais comprou em quantidade (volume de unidades), independente do valor.</div>
                <div id="cmp-itens-qtd-chart" style="height:280px;width:100%"></div>
            </div>
        </div>
    </div>
    <div class="col-12 col-lg-6">
        <div class="pbi-card h-100">
            <div class="pbi-card-header">
                <i class="bi bi-info-circle me-2 text-accent"></i>Destaques do Período
            </div>
            <div class="pbi-card-body" id="cmp-destaques">
                <div class="pbi-skeleton mb-2" style="height:14px;width:60%;border-radius:4px">&nbsp;</div>
                <div class="pbi-skeleton mb-2" style="height:14px;width:80%;border-radius:4px">&nbsp;</div>
                <div class="pbi-skeleton mb-2" style="height:14px;width:50%;border-radius:4px">&nbsp;</div>
            </div>
        </div>
    </div>
</div>

<!-- ── Tabela de Itens Comprados ──────────────────────────────────────────── -->
<div class="pbi-card mb-4">
    <div class="pbi-card-header">
        <i class="bi bi-box me-2 text-accent"></i>Itens Mais Comprados — Curva ABC
        <span id="cmp-itens-badge" class="badge bg-secondary ms-2" style="display:none"></span>
    </div>
    <div class="pbi-card-body p-0">
        <div class="pbi-hint mb-2" style="margin-top:0;padding:8px 12px 0">Preço Médio = quanto custou em média a unidade. % Part. = peso do item no total comprado. Curva ABC: A = itens que somam a maior parte do gasto.</div>
        <div class="table-responsive">
            <table class="pbi-table" id="cmp-itens-tabela">
                <thead>
                    <tr>
                        <th style="width:32px">#</th>
                        <th>Código</th>
                        <th>Descrição do Item</th>
                        <th class="text-end">Qtd Total</th>
                        <th class="text-end">Valor Total</th>
                        <th class="text-end">Preço Médio</th>
                        <th class="text-end">Qtd Notas</th>
                        <th class="text-end">% Part.</th>
                        <th class="text-center">Curva</th>
                    </tr>
                </thead>
                <tbody id="cmp-itens-body">
                    <tr><td colspan="9" class="text-center text-muted py-3">Carregando...</td></tr>
                </tbody>
                <tfoot id="cmp-itens-foot"></tfoot>
            </table>
        </div>
    </div>
</div>

<!-- ── Variacao de Preco ──────────────────────────────────────────────────── -->
<div class="pbi-card mb-4">
    <div class="pbi-card-header">
        <i class="bi bi-arrow-left-right me-2 text-accent"></i>Variação de Preço — Período Atual × Anterior
        <span class="ms-auto text-muted small" id="cmp-var-info"></span>
    </div>
    <div class="pbi-card-body p-0">
        <div class="pbi-hint mb-2" style="margin-top:0;padding:8px 12px 0">Compara o preço que você paga agora com o período anterior. Variação em verde = preço caiu; vermelho = preço subiu.</div>
        <div class="table-responsive">
            <table class="pbi-table" id="cmp-var-tabela">
                <thead>
                    <tr>
                        <th style="width:32px">#</th>
                        <th>Código</th>
                        <th>Item</th>
                        <th class="text-end">Preço Anterior</th>
                        <th class="text-end">Preço Atual</th>
                        <th class="text-end">Variação</th>
                        <th class="text-end">Qtd Comprada</th>
                        <th class="text-end">Valor Total</th>
                        <th>Ação Sugerida</th>
                    </tr>
                </thead>
                <tbody id="cmp-var-body">
                    <tr><td colspan="9" class="text-center text-muted py-3">Carregando...</td></tr>
                </tbody>
            </table>
        </div>
    </div>
</div>

<!-- ── Fornecedores Inativos + Comparativo de Precos ──────────────────────── -->
<div class="row g-3 mb-4">
    <div class="col-12 col-lg-5">
        <div class="pbi-card h-100">
            <div class="pbi-card-header">
                <i class="bi bi-person-x me-2 text-warning"></i>Fornecedores sem Comprar Recentemente
                <span id="cmp-inat-badge" class="badge bg-warning text-dark ms-2" style="display:none"></span>
            </div>
            <div class="pbi-card-body p-0">
                <div class="pbi-hint mb-2" style="margin-top:0;padding:8px 12px 0">Fornecedores que faz tempo não recebem um pedido seu. Dias Parado = dias desde a última compra.</div>
                <div class="table-responsive">
                    <table class="pbi-table">
                        <thead>
                            <tr>
                                <th>Fornecedor</th>
                                <th class="text-end">Última Compra</th>
                                <th class="text-end">Dias Parado</th>
                                <th class="text-end">Total no Período</th>
                            </tr>
                        </thead>
                        <tbody id="cmp-inat-body">
                            <tr><td colspan="4" class="text-center text-muted py-3">Carregando...</td></tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
    <div class="col-12 col-lg-7">
        <div class="pbi-card h-100">
            <div class="pbi-card-header">
                <i class="bi bi-arrow-down-up me-2 text-accent"></i>Mesmo Item — Fornecedores Diferentes
                <small class="text-muted fw-normal ms-1" style="font-size:.72rem">(oportunidade de negociação)</small>
                <span id="cmp-comp-badge" class="badge bg-secondary ms-2" style="display:none"></span>
            </div>
            <div class="pbi-card-body p-0">
                <div class="pbi-hint mb-2" style="margin-top:0;padding:8px 12px 0">Mesmo produto comprado de fornecedores diferentes. Diferença % = entre o preço mais caro e o mais barato — oportunidade de negociar.</div>
                <div class="table-responsive">
                    <table class="pbi-table">
                        <thead>
                            <tr>
                                <th>Código</th>
                                <th>Item / Fornecedor</th>
                                <th class="text-end">Preço Médio</th>
                                <th class="text-end">Qtd</th>
                                <th class="text-end">Dif%</th>
                            </tr>
                        </thead>
                        <tbody id="cmp-comp-body">
                            <tr><td colspan="5" class="text-center text-muted py-3">Carregando...</td></tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- ── JS config ──────────────────────────────────────────────────────────── -->
<script>
window.__CMP = {
    dataIni: <?= json_encode($filtros['dataIni']) ?>,
    dataFim: <?= json_encode($filtros['dataFim']) ?>,
    actionUrl: <?= json_encode($actionUrl) ?>
};
</script>

<style>
@keyframes pbi-pulse { 0%,100%{opacity:1} 50%{opacity:.4} }
.pbi-skeleton { background:var(--pbi-border,#e2e8f0); animation:pbi-pulse 1.4s ease-in-out infinite; pointer-events:none; color:transparent!important; }
.curva-a { background:#dcfce7;color:#15803d;border:1px solid #86efac;border-radius:4px;padding:1px 6px;font-size:.7rem;font-weight:700 }
.curva-b { background:#fef9c3;color:#a16207;border:1px solid #fde047;border-radius:4px;padding:1px 6px;font-size:.7rem;font-weight:700 }
.curva-c { background:#f1f5f9;color:#475569;border:1px solid #cbd5e1;border-radius:4px;padding:1px 6px;font-size:.7rem;font-weight:700 }
</style>

<script src="/assets/js/echarts.min.js"></script>
<script>
(function () {
'use strict';

/* ── Helpers ──────────────────────────────────────────────────────────────── */
function moeda(v) { return 'R$ ' + parseFloat(v||0).toLocaleString('pt-BR',{minimumFractionDigits:2,maximumFractionDigits:2}); }
function fmt0(v)  { return parseFloat(v||0).toLocaleString('pt-BR',{minimumFractionDigits:0,maximumFractionDigits:0}); }
function fmt2(v)  { return parseFloat(v||0).toLocaleString('pt-BR',{minimumFractionDigits:2,maximumFractionDigits:2}); }
function fmtPct(v){ return parseFloat(v||0).toLocaleString('pt-BR',{minimumFractionDigits:1,maximumFractionDigits:1})+'%'; }
function fmtKM(v) {
    v = parseFloat(v||0);
    if (v >= 1000000) return 'R$ '+(v/1000000).toFixed(1)+'M';
    if (v >= 1000)    return 'R$ '+(v/1000).toFixed(1)+'K';
    return 'R$ '+v.toFixed(0);
}
function esc(s) { var d=document.createElement('div'); d.textContent=s==null?'':String(s); return d.innerHTML; }
function getCssVar(n) { return getComputedStyle(document.documentElement).getPropertyValue(n).trim(); }
function fmtData(d) {
    if (!d) return '—';
    var p = String(d).substring(0,10).split('-');
    return (p[2]||'')+'/'+(p[1]||'')+'/'+(p[0]||'');
}
function curvaBadge(curva) {
    if (curva === 'A') return '<span class="curva-a">A</span>';
    if (curva === 'B') return '<span class="curva-b">B</span>';
    return '<span class="curva-c">C</span>';
}
// Calcula curva ABC a partir de array ordenado DESC por valor
// Retorna array de 'A','B','C'
function calcABC(valores) {
    var total = valores.reduce(function(s,v){return s+v;},0);
    if (total <= 0) return valores.map(function(){return 'C';});
    var acum = 0;
    return valores.map(function(v){
        acum += v;
        var pct = acum / total * 100;
        if (pct <= 80) return 'A';
        if (pct <= 95) return 'B';
        return 'C';
    });
}

/* ── Charts refs ──────────────────────────────────────────────────────────── */
var chartEvol     = null;
var chartForn     = null;
var chartFornDon  = null;
var chartDiaSem   = null;
var chartItensVal = null;
var chartItensQtd = null;

/* ── Nomes dias da semana (Firebird WEEKDAY: 0=Dom 1=Seg ... 6=Sab) ─────── */
var DIAS_SEM = ['Dom','Seg','Ter','Qua','Qui','Sex','Sab'];

/* ── KPIs ─────────────────────────────────────────────────────────────────── */
function setKpi(id, val, sub, cls) {
    var el = document.getElementById(id);
    if (!el) return;
    var valEl = el.querySelector('.pbi-kpi-valor');
    var subEl = document.getElementById(id+'-sub');
    if (valEl) { valEl.textContent = val; valEl.className = 'pbi-kpi-valor ' + (cls||''); valEl.removeAttribute('style'); }
    if (subEl) subEl.textContent = sub || '';
}

function renderKpis(kpis, totalVendas, evolucao, fornecedores, devolucoes, impostos) {
    var total    = parseFloat(kpis.TOTAL_COMPRAS  || 0);
    var qtdNotas = parseInt(kpis.QTD_NOTAS        || 0);
    var qtdForn  = parseInt(kpis.QTD_FORNECEDORES || 0);
    var ticket   = qtdNotas > 0 ? total / qtdNotas : 0;
    var desconto = parseFloat(kpis.TOTAL_DESCONTO || 0);
    var cmvPct   = totalVendas > 0 ? (total / totalVendas * 100) : 0;

    setKpi('cmp-kpi-total',  moeda(total),   qtdNotas + ' notas no período', 'text-accent');
    setKpi('cmp-kpi-notas',  fmt0(qtdNotas), 'média ' + fmt2(qtdNotas / Math.max(1,(evolucao||[]).length)) + '/dia');
    setKpi('cmp-kpi-forn',   fmt0(qtdForn),  'fornecedores distintos', '');
    setKpi('cmp-kpi-ticket', moeda(ticket),  'por nota de entrada', '');
    setKpi('cmp-kpi-desc',   moeda(desconto),desconto > 0 ? fmtPct(desconto/total*100)+' de desconto' : 'sem desconto', 'text-success');

    var cmvCls = cmvPct > 85 ? 'text-danger' : cmvPct > 70 ? 'text-warning' : 'text-success';
    var cmvSub = totalVendas > 0
        ? 'vendas: ' + fmtKM(totalVendas)
        : 'sem vendas no período';
    setKpi('cmp-kpi-cmv', cmvPct > 0 ? fmtPct(cmvPct) : '—', cmvSub, cmvCls);

    // ── KPI Concentração Top 1 — quick win 3
    if (fornecedores && fornecedores.length && total > 0) {
        var top1 = parseFloat(fornecedores[0].TOTAL_COMPRAS || 0);
        var pctConc = total > 0 ? top1 / total * 100 : 0;
        var concCls = pctConc > 50 ? 'text-danger' : pctConc > 30 ? 'text-warning' : 'text-success';
        var concSub = (fornecedores[0].FORNECEDOR || '').substring(0,22);
        setKpi('cmp-kpi-conc', fmtPct(pctConc), 'top 1: ' + concSub, concCls);
    } else {
        setKpi('cmp-kpi-conc', '—', 'sem dado', '');
    }

    // ── KPI Devoluções — quick win 5
    if (devolucoes && parseFloat(devolucoes.TOTAL_DEVOLUCAO||0) > 0) {
        var devVal = parseFloat(devolucoes.TOTAL_DEVOLUCAO || 0);
        var devQtd = parseInt(devolucoes.QTD_NOTAS || 0);
        var devPct = total > 0 ? devVal / total * 100 : 0;
        setKpi('cmp-kpi-devol', moeda(devVal), devQtd + ' notas — ' + fmtPct(devPct) + ' das compras', 'text-warning');
    } else {
        setKpi('cmp-kpi-devol', 'R$ 0,00', 'sem devoluções', 'text-success');
    }

    // ── KPI Impostos + Frete — quick win 6
    if (impostos && parseFloat(impostos.TOTAL||0) > 0) {
        var impTot = parseFloat(impostos.TOTAL || 0);
        var impPct = total > 0 ? impTot / total * 100 : 0;
        var impSub = 'ICMS ' + fmtKM(impostos.ICMS||0)
                   + ' · IPI ' + fmtKM(impostos.IPI||0)
                   + ' · ST ' + fmtKM(impostos.ST||0)
                   + ' · Frete ' + fmtKM(impostos.FRETE||0)
                   + ' (' + fmtPct(impPct) + ' do bruto)';
        setKpi('cmp-kpi-imp', moeda(impTot), impSub, '');
    } else {
        setKpi('cmp-kpi-imp', 'R$ 0,00', 'sem dados fiscais', '');
    }

    // Header
    var badge = document.getElementById('cmp-badge');
    var label = document.getElementById('cmp-periodo-label');
    if (badge) badge.textContent = fmt0(qtdNotas) + ' notas';
    if (label) {
        var ini = window.__CMP.dataIni, fim = window.__CMP.dataFim;
        label.textContent = fmtData(ini) + ' a ' + fmtData(fim);
    }
}

/* ── KPIs YoY (mes anterior + ano anterior + ticket ano anterior) ─────────── */
function renderKpisYoY(yoy) {
    if (!yoy || !yoy.atual) {
        setKpi('cmp-yoy-mes',    '—', 'sem comparativo', '');
        setKpi('cmp-yoy-ano',    '—', 'sem comparativo', '');
        setKpi('cmp-yoy-ticket', '—', 'sem comparativo', '');
        return;
    }
    var atualTot = parseFloat((yoy.atual||{}).TOTAL_COMPRAS || 0);
    var mesTot   = parseFloat((yoy.mes_ant||{}).TOTAL_COMPRAS || 0);
    var anoTot   = parseFloat((yoy.ano_ant||{}).TOTAL_COMPRAS || 0);

    var atualN   = parseInt((yoy.atual||{}).QTD_NOTAS || 0);
    var anoN     = parseInt((yoy.ano_ant||{}).QTD_NOTAS || 0);
    var atualTk  = atualN > 0 ? atualTot / atualN : 0;
    var anoTk    = anoN   > 0 ? anoTot   / anoN   : 0;

    // Gastar MAIS em compras é sinal de alerta (custo subindo).
    // Verde = gastou menos (poupou); Vermelho = gastou mais.
    function deltaCard(idBase, atual, anterior, label, fmtFn) {
        if (anterior <= 0) {
            setKpi(idBase, fmtFn(atual), 'sem ' + label, '');
            return;
        }
        var delta = atual - anterior;
        var pct = anterior > 0 ? (delta / anterior * 100) : 0;
        var sinal = delta > 0 ? '+' : '';
        // Para ticket médio: subir é ruim (preço de aquisição subindo).
        var cls = delta > 0 ? 'text-danger' : delta < 0 ? 'text-success' : '';
        var sub = label + ': ' + fmtFn(anterior) + '  ('
                + sinal + fmt2(pct) + '%)';
        setKpi(idBase, fmtFn(atual), sub, cls);
    }

    deltaCard('cmp-yoy-mes',    atualTot, mesTot, 'mês anterior',   function(v){ return fmtKM(v); });
    deltaCard('cmp-yoy-ano',    atualTot, anoTot, 'ano anterior',   function(v){ return fmtKM(v); });
    deltaCard('cmp-yoy-ticket', atualTk,  anoTk,  'ticket ano ant.', function(v){ return moeda(v); });
}

/* ── Evolucao Diaria ──────────────────────────────────────────────────────── */
function renderEvol(evolucao) {
    var el = document.getElementById('cmp-evol-chart');
    if (!el) return;
    if (!chartEvol) chartEvol = echarts.init(el);
    if (!evolucao || !evolucao.length) { chartEvol.clear(); return; }

    var labels  = evolucao.map(function(d){
        var s = String(d.DATA||'').substring(0,10).split('-');
        return (s[2]||'')+'/'+(s[1]||'');
    });
    var totais  = evolucao.map(function(d){ return parseFloat(d.TOTAL||0); });
    var qtds    = evolucao.map(function(d){ return parseInt(d.QTD_NOTAS||0); });
    var many    = labels.length;

    var info = document.getElementById('cmp-evol-info');
    if (info) info.textContent = many + ' dias com compras';

    var cm = getCssVar('--pbi-muted') || '#64748b';
    var cb = getCssVar('--pbi-border') || '#e2e8f0';
    var ca = getCssVar('--pbi-accent') || '#3b82f6';
    var amber = '#f59e0b';

    chartEvol.setOption({
        backgroundColor: 'transparent',
        tooltip: {
            trigger: 'axis', axisPointer: { type: 'cross' }, appendToBody: true,
            formatter: function(p) {
                var i = p[0].dataIndex;
                return '<b>' + labels[i] + '</b><br/>'
                    + 'Comprado: <b>' + moeda(totais[i]) + '</b><br/>'
                    + 'Notas: <b>' + fmt0(qtds[i]) + '</b><br/>'
                    + 'Ticket: <b>' + moeda(totais[i] / Math.max(1, qtds[i])) + '</b>';
            }
        },
        grid: { left: 60, right: 55, top: 20, bottom: many > 30 ? 50 : 30 },
        xAxis: {
            type: 'category', data: labels,
            axisLabel: { fontSize: 10, color: cm, rotate: many > 20 ? 45 : 0, interval: many > 60 ? 6 : many > 30 ? 2 : 0 }
        },
        yAxis: [
            { type: 'value', axisLabel: { fontSize: 10, formatter: function(v){ return fmtKM(v); }, color: cm }, splitLine: { lineStyle: { color: cb } } },
            { type: 'value', axisLabel: { fontSize: 10, formatter: function(v){ return fmt0(v); }, color: amber }, splitLine: { show: false } }
        ],
        series: [
            { name: 'Total Comprado', type: 'bar', yAxisIndex: 0, data: totais, barMaxWidth: 28,
              itemStyle: { color: new echarts.graphic.LinearGradient(0,0,0,1,[{offset:0,color:'#6366f1'},{offset:1,color:'rgba(99,102,241,.3)'}]), borderRadius: [2,2,0,0] } },
            { name: 'Qtd Notas', type: 'line', yAxisIndex: 1, data: qtds, smooth: true,
              lineStyle: { color: amber, width: 2 }, itemStyle: { color: amber }, symbol: many > 60 ? 'none' : 'circle', symbolSize: 4 }
        ]
    }, true);
}

/* ── Top Fornecedores (barras horizontais) ───────────────────────────────── */
function renderFornChart(fornecedores) {
    var el = document.getElementById('cmp-forn-chart');
    if (!el) return;
    if (!chartForn) chartForn = echarts.init(el);
    if (!fornecedores || !fornecedores.length) { chartForn.clear(); return; }

    var top = fornecedores.slice(0, 12).reverse();
    var nomes  = top.map(function(f){ return (f.FORNECEDOR||'').substring(0,24); });
    var totais = top.map(function(f){ return parseFloat(f.TOTAL_COMPRAS||0); });
    var maxV   = Math.max.apply(null, totais);
    var cm = getCssVar('--pbi-muted') || '#64748b';
    var cb = getCssVar('--pbi-border') || '#e2e8f0';
    var cx = getCssVar('--pbi-text')   || '#1e293b';

    var lpx = Math.min(140, Math.max.apply(null, nomes.map(function(n){ return n.length; })) * 6.5);
    chartForn.setOption({
        backgroundColor: 'transparent',
        tooltip: {
            trigger: 'axis', axisPointer: { type: 'shadow' }, appendToBody: true,
            formatter: function(p) {
                var idx = top.length - 1 - p[0].dataIndex;
                var f   = fornecedores[idx] || {};
                var totalGeral = fornecedores.reduce(function(s,v){return s+parseFloat(v.TOTAL_COMPRAS||0);},0);
                var pct  = totalGeral > 0 ? (parseFloat(f.TOTAL_COMPRAS||0)/totalGeral*100).toFixed(1) : 0;
                return '<b>'+esc((f.FORNECEDOR||'').substring(0,30))+'</b><br/>'
                    +'Total: <b>'+moeda(f.TOTAL_COMPRAS||0)+'</b><br/>'
                    +'Participacao: <b>'+pct+'%</b><br/>'
                    +'Notas: <b>'+fmt0(f.QTD_NOTAS||0)+'</b><br/>'
                    +'Ticket Médio: <b>'+moeda(f.TICKET_MEDIO||0)+'</b>';
            }
        },
        grid: { left: lpx + 8, right: 70, top: 6, bottom: 6 },
        xAxis: { type: 'value', axisLabel: { fontSize: 10, formatter: function(v){ return fmtKM(v); }, color: cm }, splitLine: { lineStyle: { color: cb, type: 'dashed' } } },
        yAxis: { type: 'category', data: nomes, axisLabel: { fontSize: 10, color: cx, width: lpx, overflow: 'truncate' } },
        series: [{
            type: 'bar', data: totais, barMaxWidth: 22,
            label: { show: true, position: 'right', formatter: function(p){ return fmtKM(p.value); }, fontSize: 10, color: cx },
            itemStyle: {
                borderRadius: [0,4,4,0],
                color: function(p){ return p.value === maxV ? new echarts.graphic.LinearGradient(0,0,1,0,[{offset:0,color:'#f59e0b'},{offset:1,color:'#fbbf24'}]) : new echarts.graphic.LinearGradient(0,0,1,0,[{offset:0,color:'#4f46e5'},{offset:1,color:'#818cf8'}]); }
            }
        }]
    }, true);
}

/* ── Donut participacao fornecedores ──────────────────────────────────────── */
function renderFornDonut(fornecedores) {
    var el = document.getElementById('cmp-forn-donut');
    if (!el) return;
    if (!chartFornDon) chartFornDon = echarts.init(el);
    if (!fornecedores || !fornecedores.length) { chartFornDon.clear(); return; }

    var total = fornecedores.reduce(function(s,f){ return s+parseFloat(f.TOTAL_COMPRAS||0); },0);
    var CORES  = ['#4f46e5','#818cf8','#22c55e','#f59e0b','#06b6d4','#f97316','#a855f7','#ec4899','#84cc16','#64748b'];

    var top10  = fornecedores.slice(0, 9);
    var resto  = fornecedores.slice(9);
    var dados  = top10.map(function(f,i){
        return { name: (f.FORNECEDOR||'').substring(0,20), value: Math.round(parseFloat(f.TOTAL_COMPRAS||0)/total*1000)/10, itemStyle: { color: CORES[i] } };
    });
    if (resto.length) {
        var somaResto = resto.reduce(function(s,f){return s+parseFloat(f.TOTAL_COMPRAS||0);},0);
        dados.push({ name: 'Outros ('+(resto.length)+')', value: Math.round(somaResto/total*1000)/10, itemStyle: { color: CORES[9] } });
    }

    var ct = getCssVar('--pbi-text') || '#1e293b';
    chartFornDon.setOption({
        backgroundColor: 'transparent',
        tooltip: {
            trigger: 'item', appendToBody: true,
            formatter: function(p){
                var orig = fornecedores[p.dataIndex] || {};
                return '<b>'+esc(p.name)+'</b><br/>Participacao: <b>'+p.value+'%</b><br/>Total: <b>'+moeda(orig.TOTAL_COMPRAS||0)+'</b>';
            }
        },
        title: pbiTotalDonut(total, '50%', '40%'),
        legend: { type: 'scroll', orient: 'horizontal', bottom: 0, left: 'center', textStyle: { fontSize: 10, color: ct }, formatter: function(n){ return n.length > 14 ? n.substring(0,13)+'…' : n; }, itemWidth: 11, itemHeight: 11, pageIconSize: 9 },
        series: [{
            type: 'pie', radius: ['42%','64%'], center: ['50%','40%'],
            label: { show: true, position: 'inside', formatter: function(p){return p.percent>=6?Math.round(p.percent)+'%':'';}, fontSize: 10, fontWeight: 700, color: '#fff' },
            emphasis: { scale: true, scaleSize: 6 },
            data: dados
        }]
    }, true);
}

/* ── Dia da Semana ────────────────────────────────────────────────────────── */
function renderDiaSem(diaSemana) {
    var el = document.getElementById('cmp-diasem-chart');
    if (!el) return;
    if (!chartDiaSem) chartDiaSem = echarts.init(el);
    if (!diaSemana || !diaSemana.length) { chartDiaSem.clear(); return; }

    // Preenche todos os 7 dias (alguns podem nao ter compra)
    var mapa = {};
    diaSemana.forEach(function(d){ mapa[parseInt(d.DIA_SEM)] = d; });
    var nomes  = DIAS_SEM;
    var totais = [0,1,2,3,4,5,6].map(function(i){ return parseFloat((mapa[i]||{}).TOTAL||0); });
    var qtds   = [0,1,2,3,4,5,6].map(function(i){ return parseInt((mapa[i]||{}).QTD_NOTAS||0); });
    var maxT   = Math.max.apply(null, totais);

    var cm = getCssVar('--pbi-muted') || '#64748b';
    var cb = getCssVar('--pbi-border') || '#e2e8f0';

    chartDiaSem.setOption({
        backgroundColor: 'transparent',
        tooltip: {
            trigger: 'axis', axisPointer: { type: 'shadow' }, appendToBody: true,
            formatter: function(p) {
                var i = p[0].dataIndex;
                return '<b>'+nomes[i]+'</b><br/>'
                    + 'Comprado: <b>'+moeda(totais[i])+'</b><br/>'
                    + 'Notas: <b>'+fmt0(qtds[i])+'</b><br/>'
                    + 'Ticket: <b>'+moeda(totais[i]/Math.max(1,qtds[i]))+'</b>';
            }
        },
        grid: { left: 55, right: 10, top: 20, bottom: 24 },
        xAxis: { type: 'category', data: nomes, axisLabel: { fontSize: 11, color: cm } },
        yAxis: { type: 'value', axisLabel: { fontSize: 10, formatter: function(v){ return fmtKM(v); }, color: cm }, splitLine: { lineStyle: { color: cb, type: 'dashed' } } },
        series: [{
            type: 'bar', data: totais, barMaxWidth: 36,
            label: { show: true, position: 'top', formatter: function(p){ return p.value > 0 ? fmtKM(p.value) : ''; }, fontSize: 9, color: cm },
            itemStyle: {
                borderRadius: [3,3,0,0],
                color: function(p){ return p.value === maxT && maxT > 0 ? new echarts.graphic.LinearGradient(0,1,0,0,[{offset:0,color:'#f59e0b'},{offset:1,color:'#fbbf24'}]) : new echarts.graphic.LinearGradient(0,1,0,0,[{offset:0,color:'#4f46e5'},{offset:1,color:'#818cf8'}]); }
            }
        }]
    }, true);
}

/* ── Top Itens por Valor ──────────────────────────────────────────────────── */
function renderItensValor(itens) {
    var el = document.getElementById('cmp-itens-val-chart');
    if (!el) return;
    if (!chartItensVal) chartItensVal = echarts.init(el);
    if (!itens || !itens.length) { chartItensVal.clear(); return; }

    var top  = itens.slice(0, 12).reverse();
    var nomes = top.map(function(i){ return (i.DESCRICAO||i.COD_ITEM||'').substring(0,22); });
    var vals  = top.map(function(i){ return parseFloat(i.VALOR_TOTAL||0); });
    var maxV  = Math.max.apply(null, vals);
    var cm = getCssVar('--pbi-muted') || '#64748b';
    var cb = getCssVar('--pbi-border') || '#e2e8f0';
    var cx = getCssVar('--pbi-text')   || '#1e293b';

    var lpx = Math.min(130, Math.max.apply(null, nomes.map(function(n){ return n.length; })) * 6);
    chartItensVal.setOption({
        backgroundColor: 'transparent',
        tooltip: {
            trigger: 'axis', axisPointer: { type: 'shadow' }, appendToBody: true,
            formatter: function(p) {
                var idx = top.length - 1 - p[0].dataIndex;
                var it = itens.slice(0,12)[idx] || {};
                return '<b>'+esc((it.DESCRICAO||it.COD_ITEM||'').substring(0,32))+'</b><br/>'
                    +'Valor: <b>'+moeda(it.VALOR_TOTAL||0)+'</b><br/>'
                    +'Qtd: <b>'+fmt2(it.QTD_TOTAL||0)+'</b><br/>'
                    +'Preço Médio: <b>'+moeda(it.PRECO_MEDIO||0)+'</b>';
            }
        },
        grid: { left: lpx + 8, right: 65, top: 6, bottom: 6 },
        xAxis: { type: 'value', axisLabel: { fontSize: 10, formatter: function(v){ return fmtKM(v); }, color: cm }, splitLine: { lineStyle: { color: cb, type: 'dashed' } } },
        yAxis: { type: 'category', data: nomes, axisLabel: { fontSize: 10, color: cx, width: lpx, overflow: 'truncate' } },
        series: [{
            type: 'bar', data: vals, barMaxWidth: 20,
            label: { show: true, position: 'right', formatter: function(p){ return fmtKM(p.value); }, fontSize: 10, color: cx },
            itemStyle: {
                borderRadius: [0,4,4,0],
                color: function(p){ return p.value === maxV ? new echarts.graphic.LinearGradient(0,0,1,0,[{offset:0,color:'#059669'},{offset:1,color:'#34d399'}]) : new echarts.graphic.LinearGradient(0,0,1,0,[{offset:0,color:'#0891b2'},{offset:1,color:'#22d3ee'}]); }
            }
        }]
    }, true);
}

/* ── Top Itens por Quantidade ─────────────────────────────────────────────── */
function renderItensQtd(itens) {
    var el = document.getElementById('cmp-itens-qtd-chart');
    if (!el) return;
    if (!chartItensQtd) chartItensQtd = echarts.init(el);
    if (!itens || !itens.length) { chartItensQtd.clear(); return; }

    var top  = itens.slice(0, 12).reverse();
    var nomes = top.map(function(i){ return (i.DESCRICAO||i.COD_ITEM||'').substring(0,22); });
    var qtds  = top.map(function(i){ return parseFloat(i.QTD_TOTAL||0); });
    var maxQ  = Math.max.apply(null, qtds);
    var cm = getCssVar('--pbi-muted') || '#64748b';
    var cb = getCssVar('--pbi-border') || '#e2e8f0';
    var cx = getCssVar('--pbi-text')   || '#1e293b';

    var lpx = Math.min(130, Math.max.apply(null, nomes.map(function(n){ return n.length; })) * 6);
    chartItensQtd.setOption({
        backgroundColor: 'transparent',
        tooltip: {
            trigger: 'axis', axisPointer: { type: 'shadow' }, appendToBody: true,
            formatter: function(p) {
                var idx = top.length - 1 - p[0].dataIndex;
                var it = itens.slice(0,12)[idx] || {};
                return '<b>'+esc((it.DESCRICAO||it.COD_ITEM||'').substring(0,32))+'</b><br/>'
                    +'Quantidade: <b>'+fmt2(it.QTD_TOTAL||0)+'</b><br/>'
                    +'Valor Total: <b>'+moeda(it.VALOR_TOTAL||0)+'</b><br/>'
                    +'Preço Médio: <b>'+moeda(it.PRECO_MEDIO||0)+'</b>';
            }
        },
        grid: { left: lpx + 8, right: 65, top: 6, bottom: 6 },
        xAxis: { type: 'value', axisLabel: { fontSize: 10, formatter: function(v){ return fmt0(v); }, color: cm }, splitLine: { lineStyle: { color: cb, type: 'dashed' } } },
        yAxis: { type: 'category', data: nomes, axisLabel: { fontSize: 10, color: cx, width: lpx, overflow: 'truncate' } },
        series: [{
            type: 'bar', data: qtds, barMaxWidth: 20,
            label: { show: true, position: 'right', formatter: function(p){ return fmt0(p.value); }, fontSize: 10, color: cx },
            itemStyle: {
                borderRadius: [0,4,4,0],
                color: function(p){ return p.value === maxQ ? new echarts.graphic.LinearGradient(0,0,1,0,[{offset:0,color:'#d97706'},{offset:1,color:'#fbbf24'}]) : new echarts.graphic.LinearGradient(0,0,1,0,[{offset:0,color:'#9333ea'},{offset:1,color:'#c084fc'}]); }
            }
        }]
    }, true);
}

/* ── Tabela Fornecedores ──────────────────────────────────────────────────── */
function renderTabelaForn(fornecedores) {
    var tbody = document.getElementById('cmp-forn-body');
    var tfoot = document.getElementById('cmp-forn-foot');
    var badge = document.getElementById('cmp-forn-badge');
    if (!tbody) return;
    if (!fornecedores || !fornecedores.length) {
        tbody.innerHTML = '<tr><td colspan="10" class="text-center text-muted py-3">Sem dados de fornecedores</td></tr>';
        return;
    }

    if (badge) { badge.textContent = fornecedores.length+' fornecedor'+(fornecedores.length>1?'es':''); badge.style.display=''; }

    var total      = fornecedores.reduce(function(s,f){ return s+parseFloat(f.TOTAL_COMPRAS||0); },0);
    var totalQtd   = fornecedores.reduce(function(s,f){ return s+parseInt(f.QTD_NOTAS||0); },0);
    var totalDesc  = fornecedores.reduce(function(s,f){ return s+parseFloat(f.TOTAL_DESCONTO||0); },0);
    var maxForn    = parseFloat(fornecedores[0].TOTAL_COMPRAS||0);

    // Curva ABC
    var valores = fornecedores.map(function(f){ return parseFloat(f.TOTAL_COMPRAS||0); });
    var curvas  = calcABC(valores);

    var html = fornecedores.map(function(f, i){
        var fat  = parseFloat(f.TOTAL_COMPRAS||0);
        var pct  = total > 0 ? fat/total*100 : 0;
        var barW = maxForn > 0 ? Math.round(fat/maxForn*100) : 0;
        var isTop = i === 0;
        var rowBg = isTop ? 'background:rgba(245,158,11,.06)' : '';
        var rank  = isTop ? '&#x1F3C6;' : (i+1);
        return '<tr style="'+rowBg+'">'
            +'<td style="text-align:center;color:var(--pbi-muted);font-weight:700">'+rank+'</td>'
            +'<td style="font-weight:'+(isTop?600:400)+'">'+esc((f.FORNECEDOR||'').substring(0,40))+'</td>'
            +'<td class="text-end">'+fmt0(f.QTD_NOTAS||0)+'</td>'
            +'<td class="text-end" style="font-weight:600">'+moeda(fat)+'</td>'
            +'<td class="text-end">'+fmtPct(pct)+'</td>'
            +'<td class="text-end">'+moeda(f.TICKET_MEDIO||0)+'</td>'
            +'<td class="text-end" style="color:#16a34a">'+moeda(f.TOTAL_DESCONTO||0)+'</td>'
            +'<td class="text-end">'+fmtData(f.ULTIMA_COMPRA)+'</td>'
            +'<td class="text-center">'+curvaBadge(curvas[i])+'</td>'
            +'<td>'
            +  '<div style="background:var(--pbi-border,#e2e8f0);border-radius:4px;height:5px;overflow:hidden">'
            +    '<div style="width:'+barW+'%;height:100%;background:var(--pbi-accent,#4f46e5);border-radius:4px"></div>'
            +  '</div>'
            +  '<div style="font-size:.68rem;color:var(--pbi-muted);text-align:right;margin-top:1px">'+barW+'%</div>'
            +'</td>'
            +'</tr>';
    }).join('');
    tbody.innerHTML = html;

    if (tfoot) {
        tfoot.innerHTML = '<tr style="font-weight:700;border-top:2px solid var(--pbi-border,#e2e8f0)">'
            +'<td></td><td>Total Geral</td>'
            +'<td class="text-end">'+fmt0(totalQtd)+'</td>'
            +'<td class="text-end">'+moeda(total)+'</td>'
            +'<td class="text-end">100%</td>'
            +'<td class="text-end">'+moeda(totalQtd>0?total/totalQtd:0)+'</td>'
            +'<td class="text-end" style="color:#16a34a">'+moeda(totalDesc)+'</td>'
            +'<td colspan="3"></td>'
            +'</tr>';
    }
}

/* ── Tabela Itens ─────────────────────────────────────────────────────────── */
function renderTabelaItens(itens) {
    var tbody = document.getElementById('cmp-itens-body');
    var tfoot = document.getElementById('cmp-itens-foot');
    var badge = document.getElementById('cmp-itens-badge');
    if (!tbody) return;
    if (!itens || !itens.length) {
        tbody.innerHTML = '<tr><td colspan="9" class="text-center text-muted py-3">Sem dados de itens</td></tr>';
        return;
    }

    if (badge) { badge.textContent = itens.length+' itens'; badge.style.display=''; }

    var totalVal = itens.reduce(function(s,i){ return s+parseFloat(i.VALOR_TOTAL||0); },0);
    var totalQtd = itens.reduce(function(s,i){ return s+parseFloat(i.QTD_TOTAL||0); },0);

    var valores = itens.map(function(i){ return parseFloat(i.VALOR_TOTAL||0); });
    var curvas  = calcABC(valores);

    var html = itens.map(function(it, i){
        var val = parseFloat(it.VALOR_TOTAL||0);
        var pct = totalVal > 0 ? val/totalVal*100 : 0;
        var isTop = i === 0;
        var rowBg = isTop ? 'background:rgba(245,158,11,.06)' : '';
        var rank  = isTop ? '&#x1F3C6;' : (i+1);
        return '<tr style="'+rowBg+'">'
            +'<td style="text-align:center;color:var(--pbi-muted);font-weight:700">'+rank+'</td>'
            +'<td style="color:var(--pbi-muted);white-space:nowrap">'+esc(it.COD_ITEM||'')+'</td>'
            +'<td class="fw-semibold" style="font-weight:'+(isTop?600:400)+'">'+esc((it.DESCRICAO||it.COD_ITEM||'').substring(0,50))+'</td>'
            +'<td class="text-end">'+fmt2(it.QTD_TOTAL||0)+'</td>'
            +'<td class="text-end" style="font-weight:600">'+moeda(val)+'</td>'
            +'<td class="text-end">'+moeda(it.PRECO_MEDIO||0)+'</td>'
            +'<td class="text-end">'+fmt0(it.QTD_NOTAS||0)+'</td>'
            +'<td class="text-end">'+fmtPct(pct)+'</td>'
            +'<td class="text-center">'+curvaBadge(curvas[i])+'</td>'
            +'</tr>';
    }).join('');
    tbody.innerHTML = html;

    if (tfoot) {
        tfoot.innerHTML = '<tr style="font-weight:700;border-top:2px solid var(--pbi-border,#e2e8f0)">'
            +'<td></td><td></td><td>Total</td>'
            +'<td class="text-end">'+fmt2(totalQtd)+'</td>'
            +'<td class="text-end">'+moeda(totalVal)+'</td>'
            +'<td colspan="4"></td>'
            +'</tr>';
    }
}

/* ── Destaques do periodo ─────────────────────────────────────────────────── */
function renderDestaques(kpis, fornecedores, itens, evolucao, totalVendas) {
    var el = document.getElementById('cmp-destaques');
    if (!el) return;

    var total = parseFloat(kpis.TOTAL_COMPRAS||0);
    var cmv   = totalVendas > 0 ? total/totalVendas*100 : null;

    // Dia mais ativo
    var diaMaisCompras = null;
    if (evolucao && evolucao.length) {
        var maxEvol = evolucao.slice().sort(function(a,b){ return parseFloat(b.TOTAL||0)-parseFloat(a.TOTAL||0); })[0];
        if (maxEvol) {
            var dp = String(maxEvol.DATA||'').substring(0,10).split('-');
            diaMaisCompras = { data: (dp[2]||'')+'/'+(dp[1]||'')+'/'+(dp[0]||''), total: parseFloat(maxEvol.TOTAL||0) };
        }
    }

    var top1Forn = fornecedores && fornecedores.length ? fornecedores[0] : null;
    var top1Item = itens && itens.length ? itens[0] : null;

    var desconto = parseFloat(kpis.TOTAL_DESCONTO||0);
    var qtdNotas = parseInt(kpis.QTD_NOTAS||0);
    var diasAtivos = (evolucao||[]).length;

    var html = '<div style="display:flex;flex-direction:column;gap:10px">';

    function linha(icone, cor, titulo, val, sub) {
        return '<div style="display:flex;align-items:flex-start;gap:10px;padding:8px 10px;background:'+cor+';border-radius:8px">'
            +'<i class="bi '+icone+'" style="font-size:1.2rem;margin-top:1px"></i>'
            +'<div><div style="font-size:.8rem;font-weight:600">'+titulo+'</div>'
            +'<div style="font-size:.95rem;font-weight:700;color:var(--pbi-accent)">'+val+'</div>'
            +(sub?'<div style="font-size:.72rem;color:var(--pbi-muted)">'+sub+'</div>':'')
            +'</div></div>';
    }

    if (top1Forn) {
        var pctForn = total > 0 ? parseFloat(top1Forn.TOTAL_COMPRAS||0)/total*100 : 0;
        html += linha('bi-truck','rgba(79,70,229,.07)','Principal fornecedor do periodo',esc((top1Forn.FORNECEDOR||'').substring(0,30)),moeda(top1Forn.TOTAL_COMPRAS||0)+' — '+fmtPct(pctForn)+' do total');
    }
    if (top1Item) {
        html += linha('bi-box-seam','rgba(8,145,178,.07)','Item mais comprado (por valor)',esc((top1Item.DESCRICAO||top1Item.COD_ITEM||'').substring(0,30)),moeda(top1Item.VALOR_TOTAL||0)+' · Qtd: '+fmt2(top1Item.QTD_TOTAL||0));
    }
    if (diaMaisCompras) {
        html += linha('bi-calendar-check','rgba(34,197,94,.07)','Dia com maior volume de compras',diaMaisCompras.data,moeda(diaMaisCompras.total)+' comprado neste dia');
    }
    if (cmv !== null) {
        var cmvCor = cmv > 85 ? 'rgba(239,68,68,.07)' : cmv > 70 ? 'rgba(245,158,11,.07)' : 'rgba(34,197,94,.07)';
        var cmvIco = cmv > 85 ? 'bi-exclamation-triangle text-danger' : 'bi-percent text-success';
        html += linha(cmvIco, cmvCor, 'CMV% — Compras sobre Vendas', fmtPct(cmv), 'Referência: abaixo de 70% é saudável');
    }
    if (desconto > 0) {
        html += linha('bi-tag-fill','rgba(245,158,11,.07)','Descontos negociados no período',moeda(desconto), qtdNotas+' notas · '+fmtPct(total>0?desconto/total*100:0)+' do valor bruto');
    }
    if (diasAtivos > 0) {
        html += linha('bi-calendar3','rgba(99,102,241,.07)','Frequência de compras',diasAtivos+' dias com compras', 'média de '+moeda(diasAtivos>0?total/diasAtivos:0)+' por dia');
    }

    html += '</div>';
    el.innerHTML = html;
}

/* ── Variacao de Preco ────────────────────────────────────────────────────── */
function renderVarPreco(itens, dataIni, dataFim) {
    var tbody = document.getElementById('cmp-var-body');
    var info  = document.getElementById('cmp-var-info');
    if (!tbody) return;
    if (!itens || !itens.length) {
        tbody.innerHTML = '<tr><td colspan="9" class="text-center text-muted py-3">Sem dados de variação de preço</td></tr>';
        return;
    }

    // Calcula periodo anterior para exibir no cabecalho
    if (info && dataIni && dataFim) {
        var d1 = new Date(dataIni), d2 = new Date(dataFim);
        var dias = Math.round((d2 - d1) / 86400000) + 1;
        var antFim = new Date(d1); antFim.setDate(antFim.getDate() - 1);
        var antIni = new Date(d1); antIni.setDate(antIni.getDate() - dias);
        function fmtD(d){ return ('0'+d.getDate()).slice(-2)+'/'+(('0'+(d.getMonth()+1)).slice(-2))+'/'+d.getFullYear(); }
        info.textContent = 'Anterior: ' + fmtD(antIni) + ' a ' + fmtD(antFim);
    }

    // Ordena por maior variacao absoluta (alta primeiro, depois queda, sem dado por ultimo)
    var sorted = itens.slice().sort(function(a, b) {
        var va = a.VARIACAO_PCT !== null ? Math.abs(a.VARIACAO_PCT) : -999;
        var vb = b.VARIACAO_PCT !== null ? Math.abs(b.VARIACAO_PCT) : -999;
        return vb - va;
    });

    // Quick win 4: alerta visual quando variação for relevante + sugestão de ação.
    //   > +10%  = ALTA forte    -> "Renegociar fornecedor / cotar concorrente" (vermelho)
    //   +5..10  = subida média  -> "Monitorar próximas compras"               (laranja)
    //   < -10%  = QUEDA forte   -> "Confirmar preço (queda incomum)"          (azul)
    //   -5..-10 = queda média   -> "Manter fornecedor"                        (verde)
    //   senão / sem dado        -> em branco
    function acaoSugerida(pct) {
        if (pct === null || pct === undefined) return { txt: '', bg: '', cor: '' };
        if (pct > 10)   return { txt: 'Renegociar fornecedor / cotar concorrente', bg: 'rgba(220,38,38,.08)',  cor: '#b91c1c' };
        if (pct > 5)    return { txt: 'Monitorar próximas compras',                bg: 'rgba(245,158,11,.06)', cor: '#b45309' };
        if (pct < -10)  return { txt: 'Confirmar preço (queda incomum)',           bg: 'rgba(59,130,246,.06)', cor: '#1d4ed8' };
        if (pct < -5)   return { txt: 'Manter fornecedor',                         bg: 'rgba(34,197,94,.06)',  cor: '#15803d' };
        return { txt: '', bg: '', cor: '' };
    }

    var html = sorted.map(function(it, i) {
        var pct  = it.VARIACAO_PCT;
        var cor  = pct === null ? '' : pct > 0 ? 'color:#dc2626' : pct < 0 ? 'color:#16a34a' : '';
        var ico  = pct === null ? '' : pct > 5 ? '<i class="bi bi-arrow-up-circle-fill text-danger ms-1"></i>' : pct < -5 ? '<i class="bi bi-arrow-down-circle-fill text-success ms-1"></i>' : '';
        var varTxt = pct === null
            ? '<span class="text-muted">sem hist.</span>'
            : '<span style="'+cor+';font-weight:600">' + (pct > 0 ? '+' : '') + fmt2(pct) + '%</span>' + ico;
        var antTxt = it.PRECO_ANT !== null ? moeda(it.PRECO_ANT) : '<span class="text-muted">&#8212;</span>';

        var acao = acaoSugerida(pct);
        var rowStyle = acao.bg ? 'background:'+acao.bg : '';
        var acaoCell = acao.txt
            ? '<td style="font-size:.78rem;color:'+acao.cor+';font-weight:600">'+esc(acao.txt)+'</td>'
            : '<td></td>';

        return '<tr style="'+rowStyle+'">'
            + '<td style="color:var(--pbi-muted);text-align:center">'+(i+1)+'</td>'
            + '<td style="color:var(--pbi-muted);white-space:nowrap">'+esc(it.COD_ITEM||'')+'</td>'
            + '<td class="fw-semibold" style="font-weight:500">'+esc((it.DESCRICAO||it.COD_ITEM||'').substring(0,45))+'</td>'
            + '<td class="text-end">'+antTxt+'</td>'
            + '<td class="text-end" style="font-weight:600">'+moeda(it.PRECO_ATUAL)+'</td>'
            + '<td class="text-end">'+varTxt+'</td>'
            + '<td class="text-end">'+fmt2(it.QTD_ATUAL)+'</td>'
            + '<td class="text-end">'+moeda(it.VALOR_TOTAL)+'</td>'
            + acaoCell
            + '</tr>';
    }).join('');
    tbody.innerHTML = html;
}

/* ── Fornecedores sem comprar recentemente (calculado do dataFim do periodo) ─ */
function renderFornInativos(fornecedores, dataFim) {
    var tbody = document.getElementById('cmp-inat-body');
    var badge = document.getElementById('cmp-inat-badge');
    if (!tbody || !fornecedores || !fornecedores.length) return;

    var limiteData = dataFim ? new Date(dataFim) : new Date();
    var LIMIAR_DIAS = 21; // mais de 21 dias sem comprar dentro do periodo

    var inativos = fornecedores.filter(function(f) {
        if (!f.ULTIMA_COMPRA) return false;
        var ultima = new Date(f.ULTIMA_COMPRA);
        var diff   = Math.round((limiteData - ultima) / 86400000);
        return diff >= LIMIAR_DIAS;
    }).map(function(f) {
        var ultima = new Date(f.ULTIMA_COMPRA);
        var diff   = Math.round((limiteData - ultima) / 86400000);
        return { f: f, dias: diff };
    }).sort(function(a, b) { return b.dias - a.dias; });

    if (!inativos.length) {
        tbody.innerHTML = '<tr><td colspan="4" class="text-center text-muted py-3">Todos os fornecedores compraram recentemente</td></tr>';
        return;
    }

    if (badge) { badge.textContent = inativos.length; badge.style.display = ''; }

    tbody.innerHTML = inativos.slice(0, 15).map(function(item) {
        var cor = item.dias > 60 ? 'color:#dc2626' : item.dias > 30 ? 'color:#d97706' : 'color:#ca8a04';
        return '<tr>'
            + '<td>'+esc((item.f.FORNECEDOR||'').substring(0,32))+'</td>'
            + '<td class="text-end">'+fmtData(item.f.ULTIMA_COMPRA)+'</td>'
            + '<td class="text-end" style="'+cor+';font-weight:700">'+item.dias+'d</td>'
            + '<td class="text-end">'+moeda(item.f.TOTAL_COMPRAS||0)+'</td>'
            + '</tr>';
    }).join('');
}

/* ── Comparativo de precos entre fornecedores ─────────────────────────────── */
function renderComparativoForn(itens) {
    var tbody = document.getElementById('cmp-comp-body');
    var badge = document.getElementById('cmp-comp-badge');
    if (!tbody) return;
    if (!itens || !itens.length) {
        tbody.innerHTML = '<tr><td colspan="5" class="text-center text-muted py-3">Nenhum item comprado de 2 ou mais fornecedores no período</td></tr>';
        return;
    }

    if (badge) { badge.textContent = itens.length + ' itens'; badge.style.display = ''; }

    var html = '';
    itens.forEach(function(item) {
        var forns = item.FORNECEDORES || [];
        var minPreco = Math.min.apply(null, forns.map(function(f){ return f.PRECO_MEDIO; }));
        var maxPreco = Math.max.apply(null, forns.map(function(f){ return f.PRECO_MEDIO; }));
        var difPct   = minPreco > 0 ? (maxPreco - minPreco) / minPreco * 100 : 0;

        // Linha do item
        html += '<tr style="background:var(--pbi-bg2,#f8fafc)">'
            + '<td style="color:var(--pbi-muted);font-weight:600;padding:6px 12px;white-space:nowrap">'+esc(item.COD_ITEM||'')+'</td>'
            + '<td colspan="3" class="fw-semibold" style="font-weight:700;padding:6px 12px">'+esc((item.DESCRICAO||item.COD_ITEM||'').substring(0,50))+'</td>'
            + '<td class="text-end" style="font-weight:700;color:#d97706">Dif: '+fmt2(difPct)+'%</td>'
            + '</tr>';

        // Linhas dos fornecedores ordenadas por preco
        forns.forEach(function(f, fi) {
            var eMelhor  = f.PRECO_MEDIO === minPreco;
            var ePior    = f.PRECO_MEDIO === maxPreco && forns.length > 1;
            var pctVsMin = minPreco > 0 ? (f.PRECO_MEDIO - minPreco) / minPreco * 100 : 0;
            var difTxt   = fi === 0 ? '<span class="badge" style="background:#dcfce7;color:#15803d">melhor preço</span>'
                                    : '+'+fmt2(pctVsMin)+'%';
            html += '<tr>'
                + '<td></td>'
                + '<td style="padding-left:20px;color:var(--pbi-muted)">'+esc((f.FORNECEDOR||'').substring(0,35))+'</td>'
                + '<td class="text-end" style="font-weight:'+(eMelhor?'700':'400')+';color:'+(eMelhor?'#16a34a':ePior?'#dc2626':'inherit')+'">'+moeda(f.PRECO_MEDIO)+'</td>'
                + '<td class="text-end">'+fmt2(f.QTD_TOTAL)+'</td>'
                + '<td class="text-end">'+difTxt+'</td>'
                + '</tr>';
        });
    });
    tbody.innerHTML = html;
}

/* ── Carrega tudo ────────────────────────────────────────────────────────── */
function carregarDados() {
    var ini = window.__CMP.dataIni;
    var fim = window.__CMP.dataFim;
    var qs  = '?data_ini='+encodeURIComponent(ini)+'&data_fim='+encodeURIComponent(fim);

    var badge = document.getElementById('cmp-badge');
    if (badge) badge.className = 'badge bg-secondary';

    fetch('/api/compras/dashboard'+qs, { credentials: 'same-origin' })
        .then(function(r){ if (!r.ok) return r.json().then(function(e){ throw new Error(e.erro||'HTTP '+r.status); }); return r.json(); })
        .then(function(d) {
            var kpis         = d.kpis         || {};
            var evolucao     = d.evolucao      || [];
            var diaSemana    = d.dia_semana    || [];
            var fornecedores = d.fornecedores  || [];
            var itensValor   = d.itens_valor   || [];
            var itensQtd     = d.itens_qtd     || [];
            var totalVendas  = parseFloat(d.total_vendas || 0);
            var variacaoPreco   = d.variacao_preco   || [];
            var comparativoForn = d.comparativo_forn || [];
            var kpisYoY      = d.kpis_yoy     || {};
            var devolucoes   = d.devolucoes    || {};
            var impostos     = d.impostos      || {};

            window.__CMP.dataIni = d.data_ini || ini;
            window.__CMP.dataFim = d.data_fim || fim;

            renderKpis(kpis, totalVendas, evolucao, fornecedores, devolucoes, impostos);
            renderKpisYoY(kpisYoY);
            renderEvol(evolucao);
            renderFornChart(fornecedores);
            renderFornDonut(fornecedores);
            renderDiaSem(diaSemana);
            renderItensValor(itensValor);
            renderItensQtd(itensQtd);
            renderTabelaForn(fornecedores);
            renderTabelaItens(itensValor);
            renderDestaques(kpis, fornecedores, itensValor, evolucao, totalVendas);
            renderVarPreco(variacaoPreco, window.__CMP.dataIni, window.__CMP.dataFim);
            renderFornInativos(fornecedores, window.__CMP.dataFim);
            renderComparativoForn(comparativoForn);

            if (badge) badge.className = 'badge bg-success';
        })
        .catch(function(e) {
            console.error('Dashboard compras:', e);
            if (badge) { badge.className = 'badge bg-danger'; badge.textContent = 'Erro'; }
        });
}

/* ── Init ─────────────────────────────────────────────────────────────────── */
document.addEventListener('DOMContentLoaded', function() {
    carregarDados();
    var btn = document.getElementById('btnCmpAtualizar');
    if (btn) {
        btn.addEventListener('click', function() {
            btn.disabled = true;
            btn.querySelector('i').className = 'bi bi-arrow-clockwise spin';
            carregarDados();
            setTimeout(function(){ btn.disabled=false; btn.querySelector('i').className='bi bi-arrow-clockwise'; }, 1500);
        });
    }
});

/* ── Resize ───────────────────────────────────────────────────────────────── */
window.addEventListener('resize', function() {
    if (chartEvol)     chartEvol.resize();
    if (chartForn)     chartForn.resize();
    if (chartFornDon)  chartFornDon.resize();
    if (chartDiaSem)   chartDiaSem.resize();
    if (chartItensVal) chartItensVal.resize();
    if (chartItensQtd) chartItensQtd.resize();
});

})();
</script>
