<?php
// Depto de Engenharia e Automação - Master Automação - Autor: Derlivon Silva
// (parte do Premium Express BI - Fire Sistemas)
//
// View interna de diagnostico: /diag/cadastro
// Raio-X de qualidade do cadastro de produtos da loja ATIVA.

/**
 * @var string $titulo
 * @var string $subtitulo
 * @var string $erro
 * @var array  $cfg_loja          [id,nome,host,port,database,cod_empresa,tipo]
 * @var bool   $status_conexao
 * @var string $msg_conexao
 * @var ?int   $ms_conexao
 * @var ?int   $ms_query
 * @var int    $cod_empresa
 * @var int    $total
 * @var float  $pct_preco
 * @var float  $pct_custo
 * @var float  $pct_marca
 * @var float  $pct_minimo
 * @var float  $pct_grupo
 * @var float  $pct_ncm
 * @var string $nota
 * @var array  $catalogo_kpis
 * @var array  $saude_kpis
 * @var array  $estoque_kpis
 * @var array  $minimos_kpis
 * @var int    $ruptura_count
 * @var array  $alertas_extras
 * @var array  $sem_movimento_suspeitos
 * @var array  $listas              listas[tipo] = rows
 * @var string $filtro
 * @var array  $filtros_validos
 * @var int    $limite               limite aplicado na consulta (30|100|500|2000)
 * @var array  $limites_validos      whitelist de limites permitidos
 * @var string $busca                texto de busca corrente (DESCRICAO ou COD_ITEM)
 * @var array  $detalhe
 * @var int    $detalhe_total        total real do filtro+busca (sem FIRST)
 * @var array  $diagnosticos
 * @var array  $top_sem_custo
 */

$e   = fn($v) => htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8');
$brl = fn($v) => 'R$ ' . number_format((float)$v, 2, ',', '.');
$num = fn($v) => number_format((float)$v, 0, ',', '.');
$pct = fn($v) => number_format((float)$v, 1, ',', '.') . '%';

// Cor escalar (verde > 90, amarelo 70-90, vermelho < 70)
$cor = function (float $p): array {
    if ($p >= 90) return ['#16a34a', '#dcfce7'];
    if ($p >= 70) return ['#d97706', '#fef3c7'];
    return ['#dc2626', '#fee2e2'];
};

// Mascara o database path mantendo o nome do arquivo
$mascararDb = function (string $db): string {
    if ($db === '') return '—';
    $base = basename(str_replace(['\\','/'], '/', $db));
    if (strlen($db) <= 40) return $db;
    return '…' . substr(dirname(str_replace(['\\','/'], '/', $db)), -18) . '/' . $base;
};

$rotuloTipoProblema = [
    'sem_custo'  => 'Sem custo cadastrado',
    'sem_preco'  => 'Sem preco de venda',
    'prejuizo'   => 'Vendendo em prejuizo',
    'sem_ncm'    => 'Sem NCM',
    'sem_foto'   => 'Sem foto',
    'sem_barras' => 'Sem codigo de barras',
];

$iconeTipoProblema = [
    'sem_custo'  => 'bi-cash-coin',
    'sem_preco'  => 'bi-tag',
    'prejuizo'   => 'bi-graph-down-arrow',
    'sem_ncm'    => 'bi-file-earmark-x',
    'sem_foto'   => 'bi-image-alt',
    'sem_barras' => 'bi-upc-scan',
];
?>

<div class="pbi-page-header" id="pdf-capa">
    <div class="pbi-page-icon" style="background:#fef3c7;color:#92400e">
        <i class="bi bi-clipboard-check"></i>
    </div>
    <div>
        <div class="pbi-page-title"><?= $e($titulo) ?></div>
        <div class="pbi-page-subtitle"><?= $e($subtitulo) ?></div>
    </div>
    <div class="ms-auto d-flex gap-2 align-items-center">
        <span class="badge bg-warning text-dark" title="Tela interna de diagnostico">
            <i class="bi bi-tools me-1"></i>Diagnostico interno
        </span>
    </div>
</div>

<!-- ════ Bloco TOPO — Configuracao da loja ════ -->
<div class="pbi-card mb-3">
    <div class="pbi-card-header">
        <i class="bi bi-hdd-network me-2 text-accent"></i>Configuracao da loja ativa
    </div>
    <div class="pbi-card-body">
        <div class="row g-3" style="font-size:.88rem">
            <div class="col-md-4">
                <div class="text-muted small" style="font-size:.7rem;text-transform:uppercase;letter-spacing:.05em">Loja</div>
                <div style="font-weight:700;color:#0f172a;font-size:1rem">
                    <?= $e($cfg_loja['nome'] ?? '—') ?>
                    <?php if (!empty($cfg_loja['id'])): ?>
                        <span class="text-muted" style="font-weight:400;font-size:.8rem">(<?= $e($cfg_loja['id']) ?>)</span>
                    <?php else: ?>
                        <span class="text-muted" style="font-weight:400;font-size:.8rem">(single-loja)</span>
                    <?php endif; ?>
                </div>
            </div>
            <div class="col-md-4">
                <div class="text-muted small" style="font-size:.7rem;text-transform:uppercase;letter-spacing:.05em">COD_EMPRESA</div>
                <div style="font-family:ui-monospace,monospace;font-weight:700;color:#0f172a;font-size:1rem">
                    <?= (int)($cfg_loja['cod_empresa'] ?? 0) ?>
                </div>
            </div>
            <div class="col-md-4">
                <div class="text-muted small" style="font-size:.7rem;text-transform:uppercase;letter-spacing:.05em">Tipo</div>
                <div>
                    <?php $tipo = strtolower((string)($cfg_loja['tipo'] ?? '')); ?>
                    <span class="badge" style="background:<?= $tipo === 'local' ? '#dcfce7' : '#dbeafe' ?>;color:<?= $tipo === 'local' ? '#166534' : '#1e3a8a' ?>">
                        <i class="bi <?= $tipo === 'local' ? 'bi-house-door' : 'bi-globe2' ?> me-1"></i>
                        <?= $e(strtoupper($tipo ?: '—')) ?>
                    </span>
                </div>
            </div>
            <div class="col-md-4">
                <div class="text-muted small" style="font-size:.7rem;text-transform:uppercase;letter-spacing:.05em">Host : Porta</div>
                <div style="font-family:ui-monospace,monospace;color:#0f172a">
                    <?= $e($cfg_loja['host'] ?? '—') ?>:<?= (int)($cfg_loja['port'] ?? 0) ?>
                </div>
            </div>
            <div class="col-md-8">
                <div class="text-muted small" style="font-size:.7rem;text-transform:uppercase;letter-spacing:.05em">Database</div>
                <div style="font-family:ui-monospace,monospace;color:#0f172a;font-size:.8rem" title="<?= $e($cfg_loja['database'] ?? '') ?>">
                    <?= $e($mascararDb($cfg_loja['database'] ?? '')) ?>
                </div>
            </div>
            <div class="col-md-6">
                <div class="text-muted small" style="font-size:.7rem;text-transform:uppercase;letter-spacing:.05em">Status conexao</div>
                <?php if ($status_conexao): ?>
                    <div style="color:#16a34a;font-weight:700">
                        <i class="bi bi-check-circle-fill me-1"></i>
                        OK
                        <?php if ($ms_conexao !== null): ?>
                            <span class="text-muted" style="font-weight:400;font-size:.85rem"> (conexao em <?= (int)$ms_conexao ?> ms)</span>
                        <?php endif; ?>
                    </div>
                <?php else: ?>
                    <div style="color:#dc2626;font-weight:700">
                        <i class="bi bi-x-circle-fill me-1"></i>
                        Falha: <?= $e($msg_conexao ?: 'sem detalhe') ?>
                    </div>
                <?php endif; ?>
            </div>
            <div class="col-md-6">
                <div class="text-muted small" style="font-size:.7rem;text-transform:uppercase;letter-spacing:.05em">Tempo SELECT 1</div>
                <div style="color:#0f172a;font-weight:600">
                    <?php if ($ms_query !== null): ?>
                        <?= (int)$ms_query ?> ms
                    <?php else: ?>
                        —
                    <?php endif; ?>
                </div>
            </div>
        </div>
    </div>
</div>

<?php if (!empty($erro)): ?>
    <div class="alert alert-danger" style="border-radius:10px">
        <i class="bi bi-exclamation-triangle-fill me-1"></i>
        <strong>Erro ao consultar o banco:</strong> <?= $e($erro) ?>
        <div class="small mt-1" style="opacity:.85">Os blocos abaixo podem aparecer vazios ou parciais — corrija a conexao e recarregue.</div>
    </div>
<?php endif; ?>

<!-- ════ 6 KPIs principais ════ -->
<div class="row g-3 mb-3" id="pdf-kpis">
    <div class="col-6 col-md-4 col-lg-2">
        <div class="pbi-kpi-card">
            <div class="pbi-kpi-label"><i class="bi bi-box-seam me-1"></i>Produtos cadastrados</div>
            <div class="pbi-kpi-valor" style="color:#0f172a"><?= $e($num($total)) ?></div>
            <div class="text-muted small" style="font-size:.7rem">com estoque > 0 na loja</div>
        </div>
    </div>
    <?php
        $kpis6 = [
            ['Com preco',  $pct_preco,  'bi-tag-fill',     'venda > 0'],
            ['Com custo',  $pct_custo,  'bi-cash-coin',    'custo final > 0'],
            ['Com marca',  $pct_marca,  'bi-bookmark-fill','COD_MARCA != null'],
            ['Com minimo', $pct_minimo, 'bi-arrow-down-circle','ESTOQ_MINIMO > 0'],
        ];
        foreach ($kpis6 as $k):
            [$lbl,$p,$ico,$sub] = $k;
            [$corText, $corBg] = $cor($p);
    ?>
        <div class="col-6 col-md-4 col-lg-2">
            <div class="pbi-kpi-card" style="background:<?= $corBg ?>">
                <div class="pbi-kpi-label"><i class="bi <?= $ico ?> me-1"></i><?= $e($lbl) ?></div>
                <div class="pbi-kpi-valor" style="color:<?= $corText ?>"><?= $e($pct($p)) ?></div>
                <div class="text-muted small" style="font-size:.7rem"><?= $e($sub) ?></div>
            </div>
        </div>
    <?php endforeach; ?>
    <?php
        // Nota geral A/B/C/D
        $coresNota = ['A'=>['#16a34a','#dcfce7'], 'B'=>['#0ea5e9','#dbeafe'], 'C'=>['#d97706','#fef3c7'], 'D'=>['#dc2626','#fee2e2']];
        [$ncText, $ncBg] = $coresNota[$nota] ?? ['#0f172a','#f1f5f9'];
    ?>
    <div class="col-6 col-md-4 col-lg-2">
        <div class="pbi-kpi-card" style="background:<?= $ncBg ?>">
            <div class="pbi-kpi-label"><i class="bi bi-award me-1"></i>Nota do cadastro</div>
            <div class="pbi-kpi-valor" style="color:<?= $ncText ?>;font-size:2.2rem"><?= $e($nota) ?></div>
            <div class="text-muted small" style="font-size:.7rem">media preco+custo+marca+minimo</div>
        </div>
    </div>
</div>

<!-- ════ Bloco contextual: catalogo + estoque resumo ════ -->
<div class="row g-3 mb-3">
    <div class="col-md-3 col-6">
        <div class="pbi-kpi-card" style="background:#f1f5f9">
            <div class="pbi-kpi-label"><i class="bi bi-collection me-1"></i>Categorias (TIPO_PRODUTO)</div>
            <div class="pbi-kpi-valor" style="color:#0f172a"><?= $e($num($catalogo_kpis['TOTAL_CATEGORIAS'] ?? 0)) ?></div>
        </div>
    </div>
    <div class="col-md-3 col-6">
        <div class="pbi-kpi-card" style="background:#f1f5f9">
            <div class="pbi-kpi-label"><i class="bi bi-bookmark-star me-1"></i>Marcas distintas</div>
            <div class="pbi-kpi-valor" style="color:#0f172a"><?= $e($num($catalogo_kpis['TOTAL_MARCAS'] ?? 0)) ?></div>
        </div>
    </div>
    <div class="col-md-3 col-6">
        <div class="pbi-kpi-card" style="background:#f1f5f9">
            <div class="pbi-kpi-label"><i class="bi bi-bank me-1"></i>Valor de estoque (custo)</div>
            <div class="pbi-kpi-valor" style="color:#0f172a;font-size:1.05rem"><?= $e($brl($estoque_kpis['VALOR_CUSTO'] ?? 0)) ?></div>
        </div>
    </div>
    <div class="col-md-3 col-6">
        <div class="pbi-kpi-card" style="background:#fff7ed">
            <div class="pbi-kpi-label"><i class="bi bi-exclamation-octagon me-1"></i>Abaixo do minimo</div>
            <div class="pbi-kpi-valor" style="color:#9a3412"><?= $e($num($minimos_kpis['TOTAL_ABAIXO'] ?? 0)) ?></div>
            <div class="text-muted small" style="font-size:.7rem">deficit: <?= $e($num($minimos_kpis['DEFICIT_TOTAL'] ?? 0)) ?> un.</div>
        </div>
    </div>
</div>

<!-- ════ Alertas (cards vermelhos/amarelos) ════ -->
<div class="pbi-card mb-3" id="pdf-alertas">
    <div class="pbi-card-header">
        <i class="bi bi-shield-exclamation me-2 text-accent"></i>Alertas — pontos quentes do cadastro
    </div>
    <div class="pbi-card-body">
        <?php
        $alertas = [
            [
                'titulo' => 'Vendendo em prejuizo',
                'desc'   => 'PRECO_VENDA < CUSTO_FINAL (com estoque)',
                'qtd'    => (int)($saude_kpis['PREJUIZO'] ?? 0),
                'cor'    => '#dc2626', 'bg' => '#fee2e2', 'ico' => 'bi-graph-down-arrow',
                'href'   => '?f=prejuizo#detalhe',
            ],
            [
                'titulo' => 'Custo SUSPEITO',
                'desc'   => 'custo > R$ 100k OU > 50x o preco',
                'qtd'    => (int)($alertas_extras['custo_suspeito'] ?? 0),
                'cor'    => '#dc2626', 'bg' => '#fee2e2', 'ico' => 'bi-exclamation-triangle-fill',
                'href'   => '?f=suspeito#detalhe',
            ],
            [
                'titulo' => 'Preco ZERO c/ estoque',
                'desc'   => 'PRECO_VENDA <= 0 mas tem estoque',
                'qtd'    => (int)($saude_kpis['SEM_PRECO'] ?? 0),
                'cor'    => '#dc2626', 'bg' => '#fee2e2', 'ico' => 'bi-tag',
                'href'   => '?f=sem_preco#detalhe',
            ],
            [
                'titulo' => 'Sem custo TOTAL',
                'desc'   => 'CUSTO_FINAL, CUSTO_COMPRA e CUSTO_MEDIO zerados',
                'qtd'    => (int)($alertas_extras['custo_zero_total'] ?? 0),
                'cor'    => '#d97706', 'bg' => '#fef3c7', 'ico' => 'bi-cash-coin',
                'href'   => '?f=sem_custo#detalhe',
            ],
            [
                'titulo' => 'Estoque NEGATIVO',
                'desc'   => 'ITENS_ESTOQUE.QTD < 0',
                'qtd'    => (int)($alertas_extras['estoque_negativo'] ?? 0),
                'cor'    => '#dc2626', 'bg' => '#fee2e2', 'ico' => 'bi-arrow-down-square',
                'href'   => '',
            ],
            [
                'titulo' => 'Cadastro velho',
                'desc'   => 'DT_ATUALIZACAO > 90 dias',
                'qtd'    => (int)($alertas_extras['cadastro_velho'] ?? 0),
                'cor'    => '#d97706', 'bg' => '#fef3c7', 'ico' => 'bi-calendar-x',
                'href'   => '',
            ],
            [
                'titulo' => 'Sem grupo/estrutura',
                'desc'   => 'i.COD_ESTRUTURA IS NULL',
                'qtd'    => (int)($alertas_extras['sem_grupo'] ?? 0),
                'cor'    => '#d97706', 'bg' => '#fef3c7', 'ico' => 'bi-diagram-3',
                'href'   => '',
            ],
            [
                'titulo' => 'Rupturas no momento',
                'desc'   => 'abaixo do minimo (qualquer)',
                'qtd'    => (int)$ruptura_count,
                'cor'    => '#d97706', 'bg' => '#fef3c7', 'ico' => 'bi-cart-x',
                'href'   => '',
            ],
        ];
        ?>
        <div class="row g-3">
        <?php foreach ($alertas as $a): ?>
            <div class="col-md-3 col-sm-6">
                <?php $tag = $a['href'] ? 'a' : 'div'; $hrefAttr = $a['href'] ? "href=\"{$e($a['href'])}\"" : ''; ?>
                <<?= $tag ?> <?= $hrefAttr ?> style="display:block;text-decoration:none;color:inherit;background:<?= $a['bg'] ?>;border:1px solid <?= $a['cor'] ?>30;border-radius:10px;padding:.9rem 1rem;height:100%">
                    <div style="font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;color:<?= $a['cor'] ?>;font-weight:700">
                        <i class="bi <?= $a['ico'] ?> me-1"></i><?= $e($a['titulo']) ?>
                    </div>
                    <div style="font-size:1.6rem;font-weight:800;color:<?= $a['cor'] ?>;margin:.2rem 0">
                        <?= $e($num($a['qtd'])) ?>
                    </div>
                    <div class="text-muted small" style="font-size:.72rem;line-height:1.3">
                        <?= $e($a['desc']) ?>
                    </div>
                </<?= $tag ?>>
            </div>
        <?php endforeach; ?>
        </div>
    </div>
</div>

<!-- ════ Cards colapsaveis das 6 categorias de problema ════ -->
<div class="pbi-card mb-3" id="pdf-listas">
    <div class="pbi-card-header">
        <i class="bi bi-list-check me-2 text-accent"></i>Listas — primeiros 50 itens de cada problema
    </div>
    <div class="pbi-card-body">
        <div class="row g-3">
        <?php foreach (['sem_custo','sem_preco','prejuizo','sem_ncm','sem_foto','sem_barras'] as $tipo):
            $rows = $listas[$tipo] ?? [];
            $qtdTipo = count($rows);
        ?>
            <div class="col-md-6">
                <details style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:8px;padding:.6rem .9rem">
                    <summary style="cursor:pointer;font-weight:700;color:#0f172a;font-size:.9rem">
                        <i class="bi <?= $iconeTipoProblema[$tipo] ?? 'bi-dot' ?> me-1"></i>
                        <?= $e($rotuloTipoProblema[$tipo] ?? $tipo) ?>
                        <span class="badge ms-2" style="background:<?= $qtdTipo>0 ? '#dc2626':'#16a34a' ?>;color:#fff">
                            <?= (int)$qtdTipo ?>
                        </span>
                    </summary>
                    <?php if ($qtdTipo === 0): ?>
                        <div class="text-muted small mt-2"><i class="bi bi-check-circle me-1"></i>Nenhum problema dessa categoria.</div>
                    <?php else: ?>
                        <div class="mt-2" style="max-height:280px;overflow-y:auto;background:#fff;border-radius:6px">
                            <table class="table table-sm mb-0" style="font-size:.78rem">
                                <thead style="background:#f1f5f9;color:#475569;font-size:.68rem;text-transform:uppercase;letter-spacing:.04em;position:sticky;top:0">
                                    <tr>
                                        <th style="padding:.4rem .6rem">Cod</th>
                                        <th>Descricao</th>
                                        <th class="text-end">Qtd</th>
                                        <th class="text-end">Preco</th>
                                        <th class="text-end">Custo</th>
                                    </tr>
                                </thead>
                                <tbody>
                                <?php foreach ($rows as $r): ?>
                                    <tr>
                                        <td style="padding:.35rem .6rem;font-family:ui-monospace,monospace;color:#0f172a"><?= $e($r['COD_ITEM'] ?? '') ?></td>
                                        <td><?= $e($r['DESCRICAO'] ?? '') ?></td>
                                        <td class="text-end" style="font-family:ui-monospace,monospace"><?= $e($num($r['QTD'] ?? 0)) ?></td>
                                        <td class="text-end" style="font-family:ui-monospace,monospace"><?= $e($brl($r['PRECO_VENDA'] ?? 0)) ?></td>
                                        <td class="text-end" style="font-family:ui-monospace,monospace"><?= $e($brl($r['CUSTO_FINAL'] ?? 0)) ?></td>
                                    </tr>
                                <?php endforeach; ?>
                                </tbody>
                            </table>
                        </div>
                    <?php endif; ?>
                </details>
            </div>
        <?php endforeach; ?>
        </div>
    </div>
</div>

<!-- ════ Tabela detalhada (top N) com filtros, busca, limite e exportacao ════ -->
<?php
// Helpers de querystring pra preservar estado entre as pills/forms/botoes
$qsBase = static function (array $extra = []) use ($filtro, $limite, $busca): string {
    $params = [];
    if ($filtro !== '') $params['f']      = $filtro;
    if ($limite !== 30) $params['limite'] = $limite;
    if ($busca  !== '') $params['busca']  = $busca;
    foreach ($extra as $k => $v) {
        if ($v === null || $v === '' || $v === false) {
            unset($params[$k]);
        } else {
            $params[$k] = $v;
        }
    }
    return $params ? ('?' . http_build_query($params)) : '?';
};
$totalDetalhe = (int)($detalhe_total ?? count($detalhe));
$mostrando    = count($detalhe);
?>
<div class="pbi-card mb-3" id="detalhe"><span id="pdf-tabela" style="display:block"></span>
    <div class="pbi-card-header d-flex align-items-center flex-wrap gap-2">
        <div>
            <i class="bi bi-table me-2 text-accent"></i>Tabela detalhada
            <span class="text-muted" style="font-weight:400;font-size:.78rem;margin-left:.4rem">
                <?= $limite === 999999 ? '(Todos)' : '(top ' . (int)$limite . ')' ?>
            </span>
        </div>
        <div class="ms-auto d-flex flex-wrap gap-1" role="tablist" aria-label="Filtros">
            <?php
            $rotulos = [
                'todos'     => 'Todos com problema',
                'prejuizo'  => 'Prejuizo',
                'sem_preco' => 'Sem preco',
                'sem_custo' => 'Sem custo',
                'suspeito'  => 'Custo suspeito',
                'sem_marca' => 'Sem marca',
            ];
            foreach ($filtros_validos as $f):
                $ativo = ($filtro === $f);
                // Trocar filtro reseta limite/busca? Nao — preserva limite e busca.
                $href  = $qsBase(['f' => $f]) . '#detalhe';
            ?>
                <a href="<?= $e($href) ?>"
                   class="btn btn-sm"
                   style="border-radius:6px;font-size:.78rem;padding:.3rem .7rem;font-weight:600;text-decoration:none;
                          background:<?= $ativo ? '#0ea5e9' : '#f1f5f9' ?>;
                          color:<?= $ativo ? '#fff' : '#475569' ?>;
                          border:1px solid <?= $ativo ? '#0ea5e9' : '#cbd5e1' ?>">
                    <?= $e($rotulos[$f] ?? $f) ?>
                </a>
            <?php endforeach; ?>
        </div>
    </div>

    <!-- Barra de controles: pills de limite + busca + exportar CSV -->
    <div style="padding:.7rem 1rem;border-bottom:1px solid #e2e8f0;background:#f8fafc">
        <div class="d-flex flex-wrap align-items-center gap-2" style="row-gap:.6rem">
            <!-- Pills de limite -->
            <div class="d-flex align-items-center gap-1" role="group" aria-label="Limite">
                <span class="text-muted" style="font-size:.72rem;text-transform:uppercase;letter-spacing:.05em;font-weight:700;margin-right:.3rem">
                    <i class="bi bi-stack me-1"></i>Mostrar
                </span>
                <?php foreach ($limites_validos as $l):
                    $ativoL  = ($limite === $l);
                    $href    = $qsBase(['limite' => ($l === 30 ? null : $l)]) . '#detalhe';
                    $ehTodos = ($l === 999999);
                    $rotuloL = $ehTodos ? 'Todos' : (string)(int)$l;
                    $titleL  = $ehTodos ? 'Mostrar todos os itens (sem limite)' : ('Mostrar ate ' . (int)$l . ' itens');
                ?>
                    <a href="<?= $e($href) ?>"
                       class="btn btn-sm"
                       title="<?= $e($titleL) ?>"
                       style="border-radius:6px;font-size:.75rem;padding:.25rem .65rem;font-weight:700;text-decoration:none;
                              background:<?= $ativoL ? '#0f172a' : '#fff' ?>;
                              color:<?= $ativoL ? '#fff' : '#475569' ?>;
                              border:1px solid <?= $ativoL ? '#0f172a' : '#cbd5e1' ?>">
                        <?= $e($rotuloL) ?>
                    </a>
                <?php endforeach; ?>
            </div>

            <!-- Form de busca (preserva f e limite via hidden) -->
            <form method="get" action="" class="d-flex gap-1 align-items-center" style="margin-left:auto" role="search">
                <input type="hidden" name="f"      value="<?= $e($filtro) ?>">
                <input type="hidden" name="limite" value="<?= (int)$limite ?>">
                <div class="input-group input-group-sm" style="width:280px">
                    <span class="input-group-text" style="background:#fff;border-color:#cbd5e1">
                        <i class="bi bi-search" style="color:#64748b"></i>
                    </span>
                    <input type="text" name="busca"
                           class="form-control"
                           value="<?= $e($busca) ?>"
                           maxlength="80"
                           placeholder="Buscar por descricao ou COD_ITEM"
                           style="border-color:#cbd5e1;font-size:.85rem">
                    <?php if ($busca !== ''): ?>
                        <a href="<?= $e($qsBase(['busca' => null]) . '#detalhe') ?>"
                           class="btn btn-outline-secondary"
                           title="Limpar busca"
                           style="border-color:#cbd5e1">
                            <i class="bi bi-x-lg"></i>
                        </a>
                    <?php endif; ?>
                    <button class="btn" type="submit" style="background:#0ea5e9;color:#fff;border-color:#0ea5e9">
                        Buscar
                    </button>
                </div>
            </form>

            <!-- Exportar CSV (preserva tudo + csv=1) -->
            <a href="<?= $e($qsBase(['csv' => 1])) ?>"
               class="btn btn-sm"
               title="Exportar a tabela atual (limite e busca aplicados) em CSV — abre direto no Excel"
               style="background:#16a34a;color:#fff;border-radius:6px;font-size:.78rem;padding:.35rem .8rem;font-weight:700;text-decoration:none">
                <i class="bi bi-file-earmark-spreadsheet me-1"></i>Exportar CSV
            </a>

            <!-- Exportar PDF — gera relatorio executivo do Raio-X (capa + KPIs + alertas + listas + tabela + recomendacao) -->
            <button type="button"
                    onclick="gerarPDFCadastro()"
                    title="Gerar relatorio PDF completo do diagnostico (capa, KPIs, alertas, listas, tabela e recomendacao)"
                    style="background:#dc2626;color:#fff;border:0;border-radius:6px;font-size:.78rem;padding:.35rem .8rem;font-weight:700;cursor:pointer">
                <i class="bi bi-file-pdf me-1"></i>Exportar PDF
            </button>
        </div>

        <!-- "Mostrando X de Y" + aviso quando esta cortando -->
        <?php $ehTodos = ($limite === 999999); ?>
        <div class="d-flex flex-wrap align-items-center gap-2 mt-2" style="font-size:.78rem;color:#64748b">
            <div>
                <i class="bi bi-info-circle me-1"></i>
                <?php if ($ehTodos): ?>
                    Mostrando <strong style="color:#0f172a"><?= $e($num($mostrando)) ?></strong> itens
                <?php else: ?>
                    Mostrando <strong style="color:#0f172a"><?= $e($num($mostrando)) ?></strong>
                    de <strong style="color:#0f172a"><?= $e($num($totalDetalhe)) ?></strong> itens
                <?php endif; ?>
                <?php if ($busca !== ''): ?>
                    <span class="ms-1">
                        — busca: <code style="background:#e0f2fe;color:#0c4a6e;padding:.05rem .35rem;border-radius:4px"><?= $e($busca) ?></code>
                    </span>
                <?php endif; ?>
            </div>
            <?php if (!$ehTodos && $totalDetalhe > $mostrando): ?>
                <?php $faltam = $totalDetalhe - $mostrando; ?>
                <div style="color:#9a3412;background:#fff7ed;border:1px solid #fed7aa;border-radius:6px;padding:.25rem .6rem">
                    <i class="bi bi-exclamation-triangle-fill me-1"></i>
                    Estao faltando <strong><?= $e($num($faltam)) ?></strong>
                    <?= $faltam === 1 ? 'item' : 'itens' ?>. Aumente o limite ou
                    <a href="<?= $e($qsBase(['csv' => 1])) ?>" style="color:#9a3412;text-decoration:underline;font-weight:700">exporte pra CSV</a>.
                </div>
            <?php endif; ?>
        </div>
    </div>

    <div class="pbi-card-body" style="padding:0">
        <?php if (empty($detalhe)): ?>
            <div style="padding:2rem;text-align:center;color:#64748b">
                <i class="bi bi-check-circle" style="font-size:2rem;display:block;margin-bottom:.5rem;color:#16a34a"></i>
                Nenhum item com esse problema. Cadastro impecavel nessa categoria.
            </div>
        <?php else: ?>
            <div class="table-responsive">
                <table class="table table-hover mb-0" style="font-size:.85rem">
                    <thead style="background:#f1f5f9;color:#475569;font-size:.72rem;text-transform:uppercase;letter-spacing:.04em">
                        <tr>
                            <th style="padding:.6rem .75rem">Cod</th>
                            <th>Descricao</th>
                            <th>Marca</th>
                            <th class="text-end">Estoque</th>
                            <th class="text-end">Preco venda</th>
                            <th class="text-end">Custo final</th>
                            <th class="text-end">Markup %</th>
                            <th>Status</th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php foreach ($detalhe as $r):
                        $st = $r['STATUS'] ?? [];
                        $temPrej = in_array('prejuizo', $st, true);
                        $temSus  = in_array('suspeito', $st, true);
                        $bg = ($temPrej || $temSus) ? '#fef2f2' : (count($st) ? '#fffbeb' : '#fff');
                        $markup = $r['MARKUP'];
                    ?>
                        <tr style="background:<?= $bg ?>">
                            <td style="padding:.55rem .75rem;font-family:ui-monospace,monospace;font-weight:700;color:#0f172a">
                                <?= $e($r['COD_ITEM'] ?? '') ?>
                            </td>
                            <td style="color:#1e293b;font-weight:500"><?= $e($r['DESCRICAO'] ?? '') ?></td>
                            <td style="color:<?= ($r['MARCA'] ?? '') === '' ? '#dc2626' : '#475569' ?>;font-size:.8rem">
                                <?= $e(($r['MARCA'] ?? '') !== '' ? $r['MARCA'] : '— (sem marca)') ?>
                            </td>
                            <td class="text-end" style="font-family:ui-monospace,monospace">
                                <?= $e($num($r['QTD'] ?? 0)) ?>
                            </td>
                            <td class="text-end" style="font-family:ui-monospace,monospace;color:<?= ((float)($r['PRECO_VENDA'] ?? 0) <= 0) ? '#dc2626' : '#0f172a' ?>;font-weight:600">
                                <?= $e($brl($r['PRECO_VENDA'] ?? 0)) ?>
                            </td>
                            <td class="text-end" style="font-family:ui-monospace,monospace;color:<?= ((float)($r['CUSTO_FINAL'] ?? 0) <= 0) ? '#dc2626' : (($r['STATUS'][0] ?? '') === 'suspeito' ? '#dc2626' : '#0f172a') ?>;font-weight:600">
                                <?= $e($brl($r['CUSTO_FINAL'] ?? 0)) ?>
                            </td>
                            <td class="text-end" style="font-family:ui-monospace,monospace;color:<?= $markup === null ? '#94a3b8' : ($markup < 0 ? '#dc2626' : ($markup < 10 ? '#d97706' : '#16a34a')) ?>;font-weight:600">
                                <?= $markup === null ? '—' : number_format((float)$markup, 1, ',', '.') . '%' ?>
                            </td>
                            <td>
                                <?php if (empty($st)): ?>
                                    <span class="badge" style="background:#dcfce7;color:#166534">OK</span>
                                <?php else: foreach ($st as $codeStatus):
                                    $cores = [
                                        'sem_preco' => ['#fee2e2','#991b1b'],
                                        'sem_custo' => ['#fef3c7','#92400e'],
                                        'prejuizo'  => ['#fee2e2','#991b1b'],
                                        'suspeito'  => ['#fee2e2','#991b1b'],
                                        'sem_marca' => ['#fef3c7','#92400e'],
                                    ];
                                    [$bgS, $corS] = $cores[$codeStatus] ?? ['#f1f5f9','#475569'];
                                ?>
                                    <span class="badge me-1" style="background:<?= $bgS ?>;color:<?= $corS ?>;font-size:.65rem">
                                        <?= $e($codeStatus) ?>
                                    </span>
                                <?php endforeach; endif; ?>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
        <?php endif; ?>
    </div>
</div>

<!-- ════ Bloco final — Recomendacao ════ -->
<?php
$resumo = empty($diagnosticos)
    ? 'Cadastro nota ' . $nota . '. Sem problemas relevantes detectados nessa loja.'
    : 'Cadastro nota ' . $nota . '. ' . implode(', ', $diagnosticos) . '.';
?>
<div id="pdf-recomendacao" style="background:#fffbeb;border:1px solid #f59e0b;border-radius:10px;padding:1.2rem 1.4rem;color:#78350f;line-height:1.55;margin-bottom:1rem">
    <div style="font-weight:800;font-size:1.05rem;margin-bottom:.4rem">
        <i class="bi bi-lightbulb-fill me-1"></i>
        Recomendacao
    </div>
    <div style="font-size:.92rem;margin-bottom:.6rem">
        <?= $e($resumo) ?>
    </div>
    <?php if (!empty($top_sem_custo)): ?>
        <div style="font-size:.82rem;margin-top:.6rem">
            <strong>Foco em (top 5 itens com mais estoque e sem custo):</strong>
            <ol style="margin:.3rem 0 0 1.2rem;padding:0">
                <?php foreach ($top_sem_custo as $t): ?>
                    <li style="margin:.2rem 0">
                        <code style="background:#fef3c7;padding:.05rem .35rem;border-radius:4px;color:#78350f"><?= $e($t['COD_ITEM'] ?? '') ?></code>
                        <?= $e($t['DESCRICAO'] ?? '') ?>
                        <span class="text-muted" style="font-size:.78rem">
                            — <?= $e($num($t['QTD'] ?? 0)) ?> un. ·
                            preco <?= $e($brl($t['PRECO_VENDA'] ?? 0)) ?>
                        </span>
                    </li>
                <?php endforeach; ?>
            </ol>
        </div>
    <?php endif; ?>
    <div style="font-size:.78rem;margin-top:.8rem;color:#92400e">
        <i class="bi bi-info-circle me-1"></i>
        Inativos provaveis = itens sem registro em <code>ITENS_ESTOQUE</code> pra esta empresa OU com
        <code>QTD &lt;= 0</code> ha muito tempo OU <code>DT_ATUALIZACAO</code> muito antiga.
        O ERP Fire <strong>nao tem soft-delete</strong> em <code>ITENS</code>, entao isso e sempre inferencia.
    </div>
</div>

<?php // ════════════════════════════════════════════════════════════════════════
      // Meta JSON pra alimentar a capa do PDF (lido pelo gerarPDFCadastro)
      // ════════════════════════════════════════════════════════════════════════ ?>
<script type="application/json" id="raiox-cadastro-meta">
<?= json_encode([
    'loja'         => (string)($cfg_loja['nome'] ?? '—'),
    'loja_id'      => (string)($cfg_loja['id'] ?? ''),
    'cod_empresa'  => (int)($cfg_loja['cod_empresa'] ?? 0),
    'tipo'         => strtolower((string)($cfg_loja['tipo'] ?? '')),
    'host'         => (string)($cfg_loja['host'] ?? ''),
    'porta'        => (int)($cfg_loja['port'] ?? 0),
    'status_ok'    => (bool)$status_conexao,
    'status_msg'   => (string)($status_conexao ? 'OK' : ($msg_conexao ?: 'Falha')),
    'nota'         => (string)$nota,
    'kpis'         => [
        'total'      => (int)$total,
        'pct_preco'  => (float)$pct_preco,
        'pct_custo'  => (float)$pct_custo,
        'pct_marca'  => (float)$pct_marca,
        'pct_minimo' => (float)$pct_minimo,
        'pct_ncm'    => (float)$pct_ncm,
    ],
    'limite'       => (int)$limite,
    'filtro'       => (string)$filtro,
    'busca'        => (string)$busca,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>
</script>

<?php // ════════════════════════════════════════════════════════════════════════
      // Depto de Engenharia e Automação - Master Automação - Autor: Derlivon Silva
      // FIX 25/06/2026: o dump fiscal NAO vem mais embutido na pagina.
      // Causava HTTP 500 (timeout 120s) em loja grande/VPN porque o
      // controller chamava cadastroFiscal(999999) em TODA carga da tela.
      // Agora window.gerarPDFFiscal() bate em /diag/cadastro/fiscal-json
      // sob demanda (so quando o usuario clica no FAB).
      // ════════════════════════════════════════════════════════════════════════ ?>

<?php /* Carrega libs jsPDF + html2canvas (idempotente) — já podem ter sido injetadas por _acoes.php em outras telas */ ?>
<?php if(empty($GLOBALS['__pbi_export_loaded'])): $GLOBALS['__pbi_export_loaded']=true; ?>
<script src="/vendor/export/jspdf.umd.min.js"></script>
<script src="/vendor/export/html2canvas.min.js"></script>
<?php endif; ?>
<?php /* autoTable e usado pelo Relatorio Limpo (PDF tabular pra contador/estoque). Idempotente. */ ?>
<?php if(empty($GLOBALS['__pbi_autotable_loaded'])): $GLOBALS['__pbi_autotable_loaded']=true; ?>
<script src="/vendor/export/jspdf.plugin.autotable.min.js"></script>
<?php endif; ?>

<script>
/* Depto de Engenharia e Automacao - Master Automacao - Autor: Derlivon Silva
 *
 * gerarPDFCadastro() — exporta o Raio-X do Cadastro pra PDF executivo.
 *
 * Estrategia (Opcao A): html2canvas captura cada secao da tela como imagem
 * (escala 1.5x) e jsPDF monta o documento A4 portrait com header + footer
 * programaticos. Cada secao vira 1 ou mais paginas conforme o tamanho.
 *
 * Capa: cabecalho Premium Express BI - Fire Sistemas, titulo "Raio-X do
 * Cadastro", subtitulo com nome da loja + cod_empresa, data/hora, status da
 * conexao colorido, nota A/B/C/D e mini-resumo dos 6 KPIs.
 *
 * Performance: pode levar 5-30s dependendo do limite da tabela. Mostra
 * overlay com spinner enquanto trabalha. Se uma secao falhar no html2canvas,
 * o erro e capturado e a geracao segue pras outras secoes.
 */
(function () {
    'use strict';

    function slug(s) {
        return String(s || 'loja')
            .normalize('NFD').replace(/[̀-ͯ]/g, '')
            .toLowerCase()
            .replace(/[^a-z0-9]+/g, '-')
            .replace(/^-+|-+$/g, '')
            .substring(0, 40) || 'loja';
    }

    function pad2(n) { return n < 10 ? '0' + n : '' + n; }

    function carimboArquivo() {
        var d = new Date();
        return d.getFullYear() + pad2(d.getMonth() + 1) + pad2(d.getDate()) +
               '-' + pad2(d.getHours()) + pad2(d.getMinutes());
    }

    function carimboTexto() {
        var d = new Date();
        return pad2(d.getDate()) + '/' + pad2(d.getMonth() + 1) + '/' + d.getFullYear() +
               ' ' + pad2(d.getHours()) + ':' + pad2(d.getMinutes());
    }

    function lerMeta() {
        var tag = document.getElementById('raiox-cadastro-meta');
        if (!tag) return {};
        try { return JSON.parse(tag.textContent || tag.innerText || '{}'); }
        catch (e) { console.warn('meta JSON invalido', e); return {}; }
    }

    function getJsPDF() {
        if (window.jspdf && window.jspdf.jsPDF) return window.jspdf.jsPDF;
        if (window.jsPDF) return window.jsPDF;
        return null;
    }

    // Overlay de "Gerando PDF..."
    function mostrarSpinner(msg) {
        var ov = document.getElementById('pdf-overlay-cadastro');
        if (!ov) {
            ov = document.createElement('div');
            ov.id = 'pdf-overlay-cadastro';
            ov.style.cssText = 'position:fixed;inset:0;background:rgba(15,23,42,.7);z-index:99999;' +
                'display:flex;align-items:center;justify-content:center;flex-direction:column;color:#fff;' +
                'font-family:system-ui,-apple-system,sans-serif';
            ov.innerHTML =
                '<div style="background:#1e293b;border-radius:14px;padding:1.8rem 2.4rem;' +
                'box-shadow:0 20px 60px rgba(0,0,0,.5);text-align:center;min-width:320px">' +
                '<div style="width:48px;height:48px;border:5px solid #334155;border-top-color:#0ea5e9;' +
                'border-radius:50%;animation:pbi-spin 1s linear infinite;margin:0 auto 1rem"></div>' +
                '<div id="pdf-overlay-msg" style="font-size:1.05rem;font-weight:600">Gerando PDF...</div>' +
                '<div style="font-size:.8rem;color:#94a3b8;margin-top:.4rem">' +
                'Isso pode levar alguns segundos com listas grandes.</div></div>' +
                '<style>@keyframes pbi-spin{to{transform:rotate(360deg)}}</style>';
            document.body.appendChild(ov);
        }
        var m = document.getElementById('pdf-overlay-msg');
        if (m && msg) m.textContent = msg;
        ov.style.display = 'flex';
    }
    function esconderSpinner() {
        var ov = document.getElementById('pdf-overlay-cadastro');
        if (ov) ov.style.display = 'none';
    }

    // Captura uma secao (DOM element) como dataURL PNG via html2canvas
    function capturarSecao(el) {
        if (!el) return Promise.resolve(null);
        if (!window.html2canvas) return Promise.resolve(null);
        return window.html2canvas(el, {
            scale: 1.5,
            useCORS: true,
            backgroundColor: '#ffffff',
            logging: false,
            windowWidth: document.documentElement.scrollWidth
        }).then(function (canvas) {
            try { return { dataUrl: canvas.toDataURL('image/png'), w: canvas.width, h: canvas.height }; }
            catch (e) { console.warn('toDataURL falhou', e); return null; }
        }).catch(function (err) {
            console.warn('html2canvas falhou na secao', err);
            return null;
        });
    }

    // Cores ASCII-safe (texto PDF nao quebra acentos com helvetica embutido)
    var PDF = {
        // A4 portrait: 210 x 297 mm
        W: 210, H: 297,
        margem: 12,
        headerH: 16,
        footerH: 10
    };

    function desenharHeader(doc, meta, pagina, totalPaginas) {
        // faixa azul escura no topo
        doc.setFillColor(15, 23, 42);
        doc.rect(0, 0, PDF.W, PDF.headerH, 'F');
        doc.setTextColor(255, 255, 255);
        doc.setFont('helvetica', 'bold');
        doc.setFontSize(10);
        doc.text('Premium Express BI - Fire Sistemas', PDF.margem, 7);
        doc.setFont('helvetica', 'normal');
        doc.setFontSize(8);
        var loja = (meta.loja || '').replace(/[^\x20-\x7E]/g, '?');
        doc.text('Raio-X do Cadastro - ' + loja, PDF.margem, 12);
        // Numero pagina no canto direito
        doc.setFontSize(8);
        var pgTxt = 'Pagina ' + pagina + (totalPaginas ? ' de ' + totalPaginas : '');
        doc.text(pgTxt, PDF.W - PDF.margem, 12, { align: 'right' });
    }

    function desenharFooter(doc, stamp) {
        var y = PDF.H - PDF.footerH + 4;
        doc.setDrawColor(203, 213, 225);
        doc.line(PDF.margem, y - 2, PDF.W - PDF.margem, y - 2);
        doc.setTextColor(100, 116, 139);
        doc.setFont('helvetica', 'normal');
        doc.setFontSize(7);
        doc.text('Gerado pelo Fire Sistemas em ' + stamp, PDF.margem, y + 2);
        doc.text('Fire Sistemas', PDF.W - PDF.margem, y + 2, { align: 'right' });
    }

    // Desenha a CAPA do PDF (pagina 1) sem usar html2canvas — texto vetorial limpo
    function desenharCapa(doc, meta, stamp) {
        // Header ja desenhado pelo finalizarPagina
        var y = PDF.headerH + 14;

        // Titulo grande
        doc.setTextColor(15, 23, 42);
        doc.setFont('helvetica', 'bold');
        doc.setFontSize(26);
        doc.text('Raio-X do Cadastro', PDF.W / 2, y, { align: 'center' });
        y += 8;
        doc.setFont('helvetica', 'normal');
        doc.setFontSize(11);
        doc.setTextColor(100, 116, 139);
        doc.text('Diagnostico de qualidade dos produtos cadastrados', PDF.W / 2, y, { align: 'center' });
        y += 16;

        // Card "loja"
        doc.setFillColor(241, 245, 249);
        doc.roundedRect(PDF.margem, y, PDF.W - 2 * PDF.margem, 36, 3, 3, 'F');
        doc.setTextColor(71, 85, 105);
        doc.setFont('helvetica', 'bold');
        doc.setFontSize(9);
        doc.text('LOJA', PDF.margem + 6, y + 7);
        doc.setFontSize(14);
        doc.setTextColor(15, 23, 42);
        var loja = (meta.loja || '-').replace(/[^\x20-\x7E]/g, '?');
        doc.text(loja, PDF.margem + 6, y + 15);
        doc.setFont('helvetica', 'normal');
        doc.setFontSize(9);
        doc.setTextColor(71, 85, 105);
        doc.text('COD_EMPRESA: ' + (meta.cod_empresa || 0) +
                 '   |   Tipo: ' + (meta.tipo || '-').toUpperCase() +
                 '   |   ' + (meta.host || '-') + ':' + (meta.porta || 0),
                 PDF.margem + 6, y + 22);
        doc.text('Gerado em: ' + stamp, PDF.margem + 6, y + 29);
        y += 44;

        // Status da conexao
        if (meta.status_ok) {
            doc.setFillColor(220, 252, 231);
            doc.setTextColor(22, 101, 52);
        } else {
            doc.setFillColor(254, 226, 226);
            doc.setTextColor(153, 27, 27);
        }
        doc.roundedRect(PDF.margem, y, PDF.W - 2 * PDF.margem, 12, 2, 2, 'F');
        doc.setFont('helvetica', 'bold');
        doc.setFontSize(10);
        doc.text('Conexao: ' + (meta.status_ok ? 'OK' : 'FALHA') +
                 '   -   ' + (meta.status_msg || ''),
                 PDF.margem + 5, y + 8);
        y += 18;

        // Nota grande + cor
        var notas = {
            'A': [22, 163, 74,  220, 252, 231],
            'B': [14, 165, 233, 219, 234, 254],
            'C': [217, 119, 6,  254, 243, 199],
            'D': [220, 38, 38,  254, 226, 226]
        };
        var cn = notas[meta.nota] || [15, 23, 42, 241, 245, 249];
        doc.setFillColor(cn[3], cn[4], cn[5]);
        doc.roundedRect(PDF.margem, y, 60, 36, 3, 3, 'F');
        doc.setTextColor(cn[0], cn[1], cn[2]);
        doc.setFont('helvetica', 'bold');
        doc.setFontSize(9);
        doc.text('NOTA DO CADASTRO', PDF.margem + 5, y + 8);
        doc.setFontSize(36);
        doc.text(meta.nota || '?', PDF.margem + 30, y + 28, { align: 'center' });

        // 6 KPIs em coluna ao lado
        var k = meta.kpis || {};
        var kx = PDF.margem + 66, ky = y + 4;
        doc.setTextColor(71, 85, 105);
        doc.setFont('helvetica', 'bold');
        doc.setFontSize(9);
        doc.text('RESUMO DOS 6 KPIs', kx, ky);
        ky += 5;
        doc.setFont('helvetica', 'normal');
        doc.setFontSize(9);
        var kpis = [
            ['Produtos com estoque',  (k.total || 0).toLocaleString('pt-BR')],
            ['Com preco de venda',    (k.pct_preco || 0).toFixed(1) + '%'],
            ['Com custo cadastrado',  (k.pct_custo || 0).toFixed(1) + '%'],
            ['Com marca',             (k.pct_marca || 0).toFixed(1) + '%'],
            ['Com estoque minimo',    (k.pct_minimo || 0).toFixed(1) + '%'],
            ['Com NCM',               (k.pct_ncm || 0).toFixed(1) + '%']
        ];
        for (var i = 0; i < kpis.length; i++) {
            doc.setTextColor(71, 85, 105);
            doc.text(kpis[i][0] + ':', kx, ky);
            doc.setTextColor(15, 23, 42);
            doc.setFont('helvetica', 'bold');
            doc.text(kpis[i][1], kx + 60, ky, { align: 'right' });
            doc.setFont('helvetica', 'normal');
            ky += 5;
        }
        y += 42;

        // Filtros aplicados
        doc.setTextColor(100, 116, 139);
        doc.setFont('helvetica', 'normal');
        doc.setFontSize(8);
        var filtroTxt = 'Filtro: ' + (meta.filtro || 'todos') +
                        '   |   Limite da tabela: ' + (meta.limite || 30) +
                        (meta.busca ? '   |   Busca: "' + (meta.busca || '').replace(/[^\x20-\x7E]/g, '?') + '"' : '');
        doc.text(filtroTxt, PDF.margem, y + 8);
    }

    // Adiciona uma imagem (PNG dataURL com width/height nativos) ao PDF,
    // quebrando em multiplas paginas se nao couber em 1.
    function adicionarImagemPaginada(doc, img, paginaInfo) {
        if (!img || !img.dataUrl) return;
        var areaW = PDF.W - 2 * PDF.margem;
        var areaH = PDF.H - PDF.headerH - PDF.footerH - 6;
        var ratio = areaW / (img.w * 0.264583);  // px -> mm (96dpi)
        var imgWmm = areaW;
        var imgHmm = (img.h * 0.264583) * ratio;
        // Se cabe em 1 pagina, manda direto
        if (imgHmm <= areaH) {
            doc.addImage(img.dataUrl, 'PNG', PDF.margem, PDF.headerH + 4, imgWmm, imgHmm, undefined, 'FAST');
            return;
        }
        // Senao, quebra em fatias verticais usando canvas
        var canvas = document.createElement('canvas');
        var ctx = canvas.getContext('2d');
        var img2 = new Image();
        img2.src = img.dataUrl;
        // Sincrono porque dataUrl ja esta carregado
        var fatiaPx = Math.floor(img.w * (areaH / areaW));  // altura px que cabe em 1 pagina
        var y = 0, primeira = true;
        // Spin loop usando creates: melhor desenhar sincrono via promise
        return new Promise(function (resolve) {
            img2.onload = function () {
                while (y < img.h) {
                    var alturaFatia = Math.min(fatiaPx, img.h - y);
                    canvas.width = img.w;
                    canvas.height = alturaFatia;
                    ctx.fillStyle = '#fff';
                    ctx.fillRect(0, 0, canvas.width, canvas.height);
                    ctx.drawImage(img2, 0, -y);
                    var fatiaUrl = canvas.toDataURL('image/png');
                    if (!primeira) {
                        doc.addPage();
                        paginaInfo.atual++;
                    }
                    primeira = false;
                    var alturaMm = (alturaFatia * 0.264583) * ratio;
                    doc.addImage(fatiaUrl, 'PNG', PDF.margem, PDF.headerH + 4, imgWmm, alturaMm, undefined, 'FAST');
                    y += alturaFatia;
                }
                resolve();
            };
            // Fallback caso onload nao dispare (dataUrl ja decodificado)
            if (img2.complete) img2.onload();
        });
    }

    window.gerarPDFCadastro = function () {
        var jsPDFCtor = getJsPDF();
        if (!jsPDFCtor || !window.html2canvas) {
            alert('Bibliotecas jsPDF/html2canvas nao carregaram. Recarregue a pagina e tente de novo.');
            return;
        }
        var meta = lerMeta();
        var stamp = carimboTexto();
        mostrarSpinner('Preparando o PDF...');

        // Lista de secoes na ordem
        var secoes = [
            { id: 'pdf-kpis',         titulo: 'KPIs principais' },
            { id: 'pdf-alertas',      titulo: 'Alertas' },
            { id: 'pdf-listas',       titulo: 'Listas de problemas' },
            { id: 'detalhe',          titulo: 'Tabela detalhada' },
            { id: 'pdf-recomendacao', titulo: 'Recomendacao' }
        ];

        var doc = new jsPDFCtor({ orientation: 'portrait', unit: 'mm', format: 'a4' });
        var paginaInfo = { atual: 1 };

        // ---- Pagina 1: CAPA ----
        desenharCapa(doc, meta, stamp);

        // Captura todas as secoes em sequencia
        var capturas = [];
        var i = 0;
        function proxima() {
            if (i >= secoes.length) return Promise.resolve();
            var sec = secoes[i++];
            mostrarSpinner('Capturando: ' + sec.titulo + '...');
            var el = document.getElementById(sec.id);
            return capturarSecao(el).then(function (img) {
                capturas.push({ sec: sec, img: img });
                return proxima();
            });
        }

        proxima().then(function () {
            mostrarSpinner('Montando o PDF...');
            // Pra cada captura, adiciona nova pagina e cola
            return capturas.reduce(function (chain, c) {
                return chain.then(function () {
                    if (!c.img) return;  // secao falhou — pula
                    doc.addPage();
                    paginaInfo.atual++;
                    return adicionarImagemPaginada(doc, c.img, paginaInfo);
                });
            }, Promise.resolve());
        }).then(function () {
            // Finaliza: desenha header + footer em TODAS as paginas
            mostrarSpinner('Finalizando...');
            var total = doc.internal.getNumberOfPages();
            for (var p = 1; p <= total; p++) {
                doc.setPage(p);
                desenharHeader(doc, meta, p, total);
                desenharFooter(doc, stamp);
            }
            var nome = 'diag-cadastro-' + slug(meta.loja) + '-' + carimboArquivo() + '.pdf';
            doc.save(nome);
            esconderSpinner();
        }).catch(function (err) {
            esconderSpinner();
            console.error('Erro ao gerar PDF', err);
            alert('Erro ao gerar PDF: ' + (err && err.message ? err.message : err) +
                  '\n\nVeja o console (F12) pra detalhes.');
        });
    };

    // ════════════════════════════════════════════════════════════════════════
    // Depto de Engenharia e Automacao - Master Automacao - Autor: Derlivon Silva
    //
    // gerarPDFLimpo() — relatorio formal pra entregar a CONTADOR / ESTOQUE.
    //
    // Diferente do gerarPDFCadastro (PDF rico com html2canvas e cores), esse e
    // sobrio: capa simples em texto + tabela densa em autoTable, sem cards
    // coloridos. Escala de cinza, fonte 8pt, paisagem A4, zebra striping.
    //
    // Le os dados DIRETO da tabela renderizada (#detalhe table tbody tr) — nao
    // bate no banco. Status vira texto curto sem badge ("PREJUIZO", "OK", etc).
    // ════════════════════════════════════════════════════════════════════════
    function classificarStatus(badges, precoVenda, custoFinal, markup) {
        // badges = array de strings dos data-status (sem_preco, sem_custo, prejuizo, suspeito, sem_marca)
        // Volta string curta em CAIXA ALTA pra coluna Status do relatorio limpo
        if (badges.indexOf('prejuizo') !== -1)  return 'PREJUIZO';
        if (badges.indexOf('suspeito') !== -1)  return 'CUSTO SUSPEITO';
        if (badges.indexOf('sem_preco') !== -1) return 'SEM PRECO';
        if (badges.indexOf('sem_custo') !== -1) return 'SEM CUSTO';
        if (markup !== null && !isNaN(markup) && markup < 10) return 'MARGEM BAIXA';
        if (badges.indexOf('sem_marca') !== -1) return 'SEM MARCA';
        return 'OK';
    }

    function extrairLinhasTabela() {
        // Pega <tbody> do bloco #detalhe da pagina
        var bloco = document.getElementById('detalhe');
        if (!bloco) return [];
        var tbody = bloco.querySelector('table tbody');
        if (!tbody) return [];
        var trs = tbody.querySelectorAll('tr');
        var linhas = [];
        for (var i = 0; i < trs.length; i++) {
            var tds = trs[i].querySelectorAll('td');
            if (tds.length < 8) continue;
            // Ordem das colunas (vide thead):
            // 0=Cod 1=Descricao 2=Marca 3=Estoque 4=Preco 5=Custo 6=Markup 7=Status
            var statusBadges = [];
            var spans = tds[7].querySelectorAll('span.badge');
            for (var s = 0; s < spans.length; s++) {
                var t = (spans[s].textContent || '').trim().toLowerCase();
                if (t) statusBadges.push(t);
            }
            // Parser numerico tolerante (texto formatado pt-BR: "R$ 1.234,56" / "12,5%")
            function parseNum(txt) {
                if (!txt) return 0;
                var s = String(txt).replace(/[R$\s.%]/g, '').replace(',', '.');
                var n = parseFloat(s);
                return isNaN(n) ? 0 : n;
            }
            function parseInt2(txt) {
                if (!txt) return 0;
                var s = String(txt).replace(/[^\d-]/g, '');
                var n = parseInt(s, 10);
                return isNaN(n) ? 0 : n;
            }
            var markupTxt = (tds[6].textContent || '').trim();
            var markup    = (markupTxt === '—' || markupTxt === '-' || markupTxt === '') ? null : parseNum(markupTxt);
            var marca     = (tds[2].textContent || '').trim();
            if (marca.indexOf('(sem marca)') !== -1 || marca === '—' || marca === '-') marca = '';

            var precoVenda = parseNum(tds[4].textContent);
            var custoFinal = parseNum(tds[5].textContent);

            linhas.push({
                cod:        (tds[0].textContent || '').trim(),
                descricao:  (tds[1].textContent || '').trim(),
                marca:      marca,
                estoque:    parseInt2(tds[3].textContent),
                precoVenda: precoVenda,
                custoFinal: custoFinal,
                markup:     markup,
                status:     classificarStatus(statusBadges, precoVenda, custoFinal, markup)
            });
        }
        return linhas;
    }

    function fmtBRL(v) {
        var n = Number(v) || 0;
        return 'R$ ' + n.toFixed(2).replace('.', ',').replace(/\B(?=(\d{3})+(?!\d))/g, '.');
    }
    function fmtInt(v) {
        var n = Math.round(Number(v) || 0);
        return n.toLocaleString('pt-BR');
    }
    function fmtPctOuTraco(v) {
        if (v === null || v === undefined || isNaN(v)) return '-';
        return Number(v).toFixed(1).replace('.', ',') + '%';
    }

    window.gerarPDFLimpo = function () {
        try {
            var jsPDFCtor = getJsPDF();
            if (!jsPDFCtor) {
                alert('Biblioteca jsPDF nao carregou. Recarregue a pagina (Ctrl+F5) e tente de novo.');
                return;
            }
            // Cria instancia primeiro pra checar autoTable (alguns builds anexam no prototype apos o construtor)
            var docTest = new jsPDFCtor();
            if (typeof docTest.autoTable !== 'function') {
                alert('Plugin autoTable nao carregou. Recarregue a pagina (Ctrl+F5) e tente de novo.');
                return;
            }
            var meta  = lerMeta();
            var stamp = carimboTexto();
            mostrarSpinner('Lendo dados da tabela...');

            var linhas = extrairLinhasTabela();
            if (!linhas.length) {
                esconderSpinner();
                alert('Nenhuma linha encontrada na tabela detalhada. Ajuste o filtro ou o limite e tente de novo.');
                return;
            }

            // Resumo numerico em cima dos dados extraidos (nao do meta)
            var total      = linhas.length;
            var semCusto   = 0, semPreco = 0, prejuizo = 0, comMarca = 0;
            for (var i = 0; i < linhas.length; i++) {
                var r = linhas[i];
                if (!r.custoFinal || r.custoFinal <= 0) semCusto++;
                if (!r.precoVenda || r.precoVenda <= 0) semPreco++;
                if (r.precoVenda > 0 && r.custoFinal > 0 && r.precoVenda < r.custoFinal) prejuizo++;
                if (r.marca && r.marca !== '') comMarca++;
            }
            function pctOf(x) { return total ? (x * 100 / total).toFixed(1).replace('.', ',') + '%' : '0,0%'; }

            mostrarSpinner('Montando o relatorio limpo...');

            // PAISAGEM A4 (297 x 210 mm)
            var doc = new jsPDFCtor({ orientation: 'landscape', unit: 'mm', format: 'a4' });
            var W = 297, H = 210, margem = 12;

            // ─── PAGINA 1: CAPA SIMPLES ────────────────────────────────────
            var y = margem + 4;
            doc.setFont('helvetica', 'normal');
            doc.setFontSize(9);
            doc.setTextColor(0, 0, 0);
            doc.text('Premium Express BI - Fire Sistemas', margem, y);
            y += 10;

            doc.setFont('helvetica', 'bold');
            doc.setFontSize(18);
            doc.text('RELATORIO DE CADASTRO DE PRODUTOS', margem, y);
            y += 10;

            doc.setFont('helvetica', 'normal');
            doc.setFontSize(11);
            var lojaTxt = (meta.loja || '-').replace(/[^\x20-\x7E]/g, '?');
            doc.text('Loja: ' + lojaTxt + '   (cod_empresa ' + (meta.cod_empresa || 0) + ')', margem, y);
            y += 6;
            doc.setFontSize(10);
            doc.text('Data de geracao: ' + stamp, margem, y);
            y += 6;

            var filtroTxt = 'Filtro aplicado: ' + (meta.filtro || 'todos') +
                            '   |   Limite: ' + (meta.limite === 999999 ? 'todos' : (meta.limite || 30));
            if (meta.busca) {
                filtroTxt += '   |   Busca: "' + String(meta.busca).replace(/[^\x20-\x7E]/g, '?') + '"';
            }
            doc.text(filtroTxt, margem, y);
            y += 10;

            doc.setFont('helvetica', 'bold');
            doc.setFontSize(11);
            doc.text('RESUMO', margem, y);
            y += 6;
            doc.setFont('helvetica', 'normal');
            doc.setFontSize(10);
            var linhasResumo = [
                'Total de produtos analisados: ' + fmtInt(total),
                'Sem custo cadastrado: ' + fmtInt(semCusto) + ' (' + pctOf(semCusto) + ')',
                'Sem preco de venda: ' + fmtInt(semPreco) + ' (' + pctOf(semPreco) + ')',
                'Em prejuizo (preco < custo): ' + fmtInt(prejuizo) + ' (' + pctOf(prejuizo) + ')',
                'Com marca preenchida: ' + fmtInt(comMarca) + ' (' + pctOf(comMarca) + ')'
            ];
            for (var lr = 0; lr < linhasResumo.length; lr++) {
                doc.text(linhasResumo[lr], margem, y);
                y += 6;
            }
            y += 4;

            doc.setFont('helvetica', 'normal');
            doc.setFontSize(8);
            doc.setTextColor(80, 80, 80);
            doc.text('Documento gerado pelo Premium Express BI - Fire Sistemas. Os dados refletem o cadastro da loja no momento da geracao.', margem, y);
            doc.setTextColor(0, 0, 0);

            // ─── PAGINAS 2+ : TABELA DENSA via autoTable ─────────────────────
            var head = [[
                'COD', 'Descricao', 'Marca', 'Estoque',
                'Preco Venda', 'Custo Final', 'Markup %', 'Status'
            ]];
            var body = linhas.map(function (r) {
                return [
                    r.cod,
                    r.descricao,
                    r.marca || '-',
                    fmtInt(r.estoque),
                    fmtBRL(r.precoVenda),
                    fmtBRL(r.custoFinal),
                    fmtPctOuTraco(r.markup),
                    r.status
                ];
            });

            doc.addPage();
            doc.autoTable({
                head: head,
                body: body,
                startY: margem + 4,
                margin: { left: margem, right: margem, top: margem + 4, bottom: 14 },
                styles: {
                    font: 'helvetica',
                    fontSize: 8,
                    cellPadding: 1.6,
                    textColor: [0, 0, 0],
                    lineColor: [200, 200, 200],
                    lineWidth: 0.1,
                    overflow: 'linebreak',
                    valign: 'middle'
                },
                headStyles: {
                    fillColor: [226, 232, 240],   // #e2e8f0 cinza claro
                    textColor: [0, 0, 0],
                    fontStyle: 'bold',
                    halign: 'left',
                    lineColor: [180, 180, 180],
                    lineWidth: 0.2
                },
                alternateRowStyles: {
                    fillColor: [248, 250, 252]    // #f8fafc — zebra
                },
                columnStyles: {
                    0: { cellWidth: 22,  fontStyle: 'bold' },         // COD
                    1: { cellWidth: 78 },                              // Descricao
                    2: { cellWidth: 32 },                              // Marca
                    3: { cellWidth: 18, halign: 'right' },             // Estoque
                    4: { cellWidth: 26, halign: 'right' },             // Preco Venda
                    5: { cellWidth: 26, halign: 'right' },             // Custo Final
                    6: { cellWidth: 20, halign: 'right' },             // Markup
                    7: { cellWidth: 30 }                               // Status
                },
                theme: 'plain',
                tableLineColor: [200, 200, 200],
                tableLineWidth: 0.1,
                showHead: 'everyPage'
            });

            // ─── FOOTER em TODAS as paginas (capa + tabelas) ─────────────────
            var totalPg = doc.internal.getNumberOfPages();
            for (var p = 1; p <= totalPg; p++) {
                doc.setPage(p);
                doc.setDrawColor(180, 180, 180);
                doc.setLineWidth(0.1);
                doc.line(margem, H - 10, W - margem, H - 10);
                doc.setFont('helvetica', 'normal');
                doc.setFontSize(8);
                doc.setTextColor(80, 80, 80);
                doc.text('Pagina ' + p + ' de ' + totalPg, margem, H - 5);
                doc.text('Gerado pelo Fire Sistemas em ' + stamp, W - margem, H - 5, { align: 'right' });
            }

            var nome = 'relatorio-cadastro-' + slug(meta.loja) + '-' + carimboArquivo() + '.pdf';
            doc.save(nome);
            esconderSpinner();
        } catch (err) {
            esconderSpinner();
            console.error('Erro ao gerar PDF Limpo', err);
            alert('Erro ao gerar PDF Limpo: ' + (err && err.message ? err.message : err) +
                  '\n\nVeja o console (F12) pra detalhes.');
        }
    };

    // ════════════════════════════════════════════════════════════════════════
    // Injeta opcao "Relatorio Executivo (PDF rico)" no FAB do pbi-export.js
    // (helper global carregado pelo layout main.php — sem hook publico,
    // entao adicionamos via DOM manipulation, idempotente)
    // ════════════════════════════════════════════════════════════════════════
    (function injetarOpcaoExecutivo() {
        function tentar() {
            var menu = document.getElementById('pbi-fab-menu');
            if (!menu) return false;
            if (menu.querySelector('#opt-pdf-executivo')) return true; // ja injetado

            // Pega o estilo dos itens existentes pra ficar igual visualmente
            var ref = menu.querySelector('a, button');
            var classeRef = ref ? ref.className : '';

            // Cria a opcao nova como ultima do menu
            var a = document.createElement('a');
            a.id = 'opt-pdf-executivo';
            a.href = '#';
            a.className = classeRef;
            a.innerHTML = '<i class="bi bi-file-earmark-pdf-fill" style="color:#dc2626;margin-right:.5rem"></i>Relatorio Executivo (PDF rico)';
            a.style.cssText = 'display:flex;align-items:center;padding:.5rem .9rem;text-decoration:none;color:#1e293b;border-radius:6px';
            a.onclick = function (ev) {
                ev.preventDefault();
                if (typeof window.toggleFabMenu === 'function') window.toggleFabMenu(); // fecha menu
                if (typeof window.gerarPDFCadastro === 'function') {
                    window.gerarPDFCadastro();
                } else {
                    alert('Funcao do PDF executivo nao carregou. Recarregue a pagina (Ctrl+F5).');
                }
                return false;
            };

            // Hover sutil
            a.addEventListener('mouseenter', function () { a.style.background = '#f1f5f9'; });
            a.addEventListener('mouseleave', function () { a.style.background = ''; });

            menu.appendChild(a);
            return true;
        }

        // O FAB pode demorar ate o JS carregar — tenta varias vezes
        var tentativas = 0;
        var iv = setInterval(function () {
            tentativas++;
            if (tentar() || tentativas >= 20) clearInterval(iv);
        }, 250);

        // Tambem tenta logo no DOMContentLoaded e depois 600ms
        document.addEventListener('DOMContentLoaded', function () { setTimeout(tentar, 600); });
    })();

    // ════════════════════════════════════════════════════════════════════════
    // Depto de Engenharia e Automacao - Master Automacao - Autor: Derlivon Silva
    //
    // Injeta opcao "Relatorio Limpo (Contador)" no FAB do pbi-export.js.
    // Mesma logica de retry/idempotencia do Executivo. Icone bi-file-text cinza.
    // ════════════════════════════════════════════════════════════════════════
    (function injetarOpcaoLimpo() {
        function tentar() {
            var menu = document.getElementById('pbi-fab-menu');
            if (!menu) return false;
            if (menu.querySelector('#opt-pdf-limpo')) return true; // ja injetado

            // Pega o estilo dos itens existentes pra ficar igual visualmente
            var ref = menu.querySelector('a, button');
            var classeRef = ref ? ref.className : '';

            // Cria a opcao nova como ultima do menu (apos a Executivo)
            var a = document.createElement('a');
            a.id = 'opt-pdf-limpo';
            a.href = '#';
            a.className = classeRef;
            a.innerHTML = '<i class="bi bi-file-text" style="color:#475569;margin-right:.5rem"></i>Relatorio Limpo (Contador)';
            a.style.cssText = 'display:flex;align-items:center;padding:.5rem .9rem;text-decoration:none;color:#1e293b;border-radius:6px';
            a.onclick = function (ev) {
                ev.preventDefault();
                if (typeof window.toggleFabMenu === 'function') window.toggleFabMenu(); // fecha menu
                if (typeof window.gerarPDFLimpo === 'function') {
                    window.gerarPDFLimpo();
                } else {
                    alert('Funcao do PDF limpo nao carregou. Recarregue a pagina (Ctrl+F5).');
                }
                return false;
            };

            // Hover sutil
            a.addEventListener('mouseenter', function () { a.style.background = '#f1f5f9'; });
            a.addEventListener('mouseleave', function () { a.style.background = ''; });

            menu.appendChild(a);
            return true;
        }

        var tentativas = 0;
        var iv = setInterval(function () {
            tentativas++;
            if (tentar() || tentativas >= 20) clearInterval(iv);
        }, 250);

        document.addEventListener('DOMContentLoaded', function () { setTimeout(tentar, 600); });
    })();

    // ════════════════════════════════════════════════════════════════════════
    // Depto de Engenharia e Automacao - Master Automacao - Autor: Derlivon Silva
    //
    // gerarPDFFiscal() — PDF "Cadastro Fiscal por Produto".
    //
    // Diferente do Executivo (rico, html2canvas) e do Limpo (le da tabela
    // visivel), o Fiscal le da tag <script id="fiscal-data"> injetada pelo PHP
    // com o dump COMPLETO do cadastro fiscal (NCM, CEST, CST, ICMS, PIS,
    // COFINS, IPI, CFOP, etc) — NAO depende do filtro/limite da tela.
    //
    // Layout: capa simples (texto) + tabela densa autoTable em paisagem A4.
    // Colunas: COD | Descricao | NCM | CEST | Orig | CST | Aliq ICMS |
    //          Aliq PIS | Aliq COFINS | Status
    // ════════════════════════════════════════════════════════════════════════
    // FIX 25/06/2026: removida lerDadosFiscais() (lia <script id="fiscal-data">
    // embutido pelo PHP). Agora os dados vem por fetch sob demanda. Veja
    // window.gerarPDFFiscal abaixo.

    // Valida NCM (8 digitos numericos).
    function ncmValido(ncm) {
        if (ncm === null || ncm === undefined) return false;
        var s = String(ncm).trim();
        return s.length === 8 && /^\d{8}$/.test(s);
    }

    // Classifica o status fiscal (mesmo criterio do repo, recalculado em JS
    // pra ficar a prova de dump antigo sem STATUS_FISCAL).
    function statusFiscalLinha(r) {
        if (r.STATUS_FISCAL) return String(r.STATUS_FISCAL);
        var ncm = String(r.NCM || '').trim();
        if (ncm === '') return 'SEM NCM';
        if (!ncmValido(ncm)) return 'NCM INVALIDO';
        var cst = String(r.CST_PRINCIPAL || r.CST_PJ_DENTRO || r.CST_PF_DENTRO || '').trim();
        if (cst === '') return 'SEM CST';
        return 'OK';
    }

    // Formata aliquota: numero -> "12,5%". Zero/null -> "—".
    function fmtAliq(v) {
        var n = Number(v);
        if (!isFinite(n) || n <= 0) return '—';
        return n.toFixed(2).replace('.', ',').replace(/,?0+$/, '') + '%';
    }

    // Texto curto pra origem da mercadoria (codigo SEFAZ).
    function fmtOrigem(v) {
        if (v === null || v === undefined || v === '') return '—';
        var s = String(v).trim();
        return s === '' ? '—' : s;
    }

    function ouTraco(v) {
        if (v === null || v === undefined) return '—';
        var s = String(v).trim();
        return s === '' ? '—' : s;
    }

    // ════════════════════════════════════════════════════════════════════════
    // FIX 25/06/2026: gerarPDFFiscal agora busca os dados sob demanda via
    // fetch /diag/cadastro/fiscal-json. Antes lia <script id="fiscal-data">
    // embutido pelo PHP — e o controller carregava o dump em TODA carga da
    // tela, estourando timeout (HTTP 500) em loja com VPN/grande catalogo.
    //
    // Spinner mostra "Buscando dados fiscais..." -> "Montando o PDF...".
    // Try/catch graceful em todos os pontos (rede, parse, montagem).
    // ════════════════════════════════════════════════════════════════════════
    function _atualizarSpinner(msg) {
        var m = document.getElementById('pdf-overlay-msg');
        if (m && msg) m.textContent = msg;
    }

    window.gerarPDFFiscal = function () {
        var jsPDFCtor = getJsPDF();
        if (!jsPDFCtor) {
            alert('Biblioteca jsPDF nao carregou. Recarregue a pagina (Ctrl+F5) e tente de novo.');
            return;
        }
        try {
            var docTest = new jsPDFCtor();
            if (typeof docTest.autoTable !== 'function') {
                alert('Plugin autoTable nao carregou. Recarregue a pagina (Ctrl+F5) e tente de novo.');
                return;
            }
        } catch (e) {
            alert('Erro ao inicializar jsPDF: ' + (e && e.message ? e.message : e));
            return;
        }

        mostrarSpinner('Buscando dados fiscais...');

        fetch('/diag/cadastro/fiscal-json', { credentials: 'same-origin' })
            .then(function (r) {
                if (!r.ok) throw new Error('HTTP ' + r.status + ' ' + r.statusText);
                return r.json();
            })
            .then(function (payload) {
                if (!payload || !payload.ok) {
                    esconderSpinner();
                    alert('Erro buscando dados fiscais: ' + ((payload && payload.erro) || 'desconhecido'));
                    return;
                }
                _atualizarSpinner('Montando o PDF...');
                // setTimeout dá ao browser uma chance de repintar o spinner
                // antes do trabalho pesado (autoTable com 1500+ linhas trava UI)
                setTimeout(function () {
                    try {
                        _montarPDFFiscal(payload);
                        esconderSpinner();
                    } catch (err) {
                        esconderSpinner();
                        console.error('Erro montando PDF Fiscal', err);
                        alert('Erro montando PDF: ' + (err && err.message ? err.message : err) +
                              '\n\nVeja o console (F12) pra detalhes.');
                    }
                }, 100);
            })
            .catch(function (err) {
                esconderSpinner();
                console.error('Erro de rede no fiscal-json', err);
                alert('Erro de rede ao buscar dados fiscais: ' + (err && err.message ? err.message : err));
            });
    };

    /**
     * Monta o PDF "Cadastro Fiscal por Produto" a partir do payload do endpoint
     * /diag/cadastro/fiscal-json. Payload esperado:
     *   { ok: true, loja, cod_empresa, itens: [...], total, data }
     *
     * Estrutura mantida do original (pre 25/06/2026): capa simples + autoTable
     * paisagem A4. So muda a origem dos dados (fetch em vez de tag JSON
     * embutida) e a fonte do nome da loja/cod_empresa (payload em vez de meta).
     */
    function _montarPDFFiscal(payload) {
        var jsPDFCtor = getJsPDF();
        var meta  = lerMeta();
        var stamp = carimboTexto();

        var linhas = (payload && Array.isArray(payload.itens)) ? payload.itens : [];
        // Prefere nome/cod_empresa vindos do payload (fonte da verdade no
        // momento da consulta) — cai pro meta da view se nao tiver.
        var lojaNome    = (payload && payload.loja)        || meta.loja        || '-';
        var codEmpresa  = (payload && payload.cod_empresa) || meta.cod_empresa || 0;

        if (!linhas.length) {
            alert('Nenhum produto encontrado no cadastro fiscal.\n\n' +
                  'Pode ser que o cliente nao tenha produtos cadastrados na empresa ativa.');
            return;
        }

        // ── Resumo de problemas fiscais ─────────────────────────────────────
        var total       = linhas.length;
        var semNcm      = 0;
        var ncmInvalido = 0;
        var semCest     = 0;
        var semCst      = 0;
        for (var i = 0; i < linhas.length; i++) {
            var r   = linhas[i];
            var ncm = String(r.NCM || '').trim();
            if (ncm === '') {
                semNcm++;
            } else if (!ncmValido(ncm)) {
                ncmInvalido++;
            }
            // "Sem CEST mas marcado como ST" -> CSOSN/CST de saida com ST
            // (CSTs com ST: 10/30/70/90 ICMS, ou CSOSN 201/202/203/500)
            var cst = String(r.CST_PRINCIPAL || r.CST_PJ_DENTRO || r.CST_PF_DENTRO || '').trim();
            var cestStr = String(r.CEST || '').trim();
            if (cestStr === '' && cst !== '') {
                var cstUp = cst.toUpperCase();
                if (cstUp === '10' || cstUp === '30' || cstUp === '70' || cstUp === '90' ||
                    cstUp === '201' || cstUp === '202' || cstUp === '203' || cstUp === '500') {
                    semCest++;
                }
            }
            if (cst === '') semCst++;
        }
        function pctOf(x) { return total ? (x * 100 / total).toFixed(1).replace('.', ',') + '%' : '0,0%'; }

        // PAISAGEM A4 (297 x 210 mm)
        var doc = new jsPDFCtor({ orientation: 'landscape', unit: 'mm', format: 'a4' });
        var W = 297, H = 210, margem = 12;

        // ─── PAGINA 1: CAPA SIMPLES ─────────────────────────────────────────
        var y = margem + 4;
        doc.setFont('helvetica', 'normal');
        doc.setFontSize(9);
        doc.setTextColor(0, 0, 0);
        doc.text('Premium Express BI - Fire Sistemas', margem, y);
        y += 10;

        doc.setFont('helvetica', 'bold');
        doc.setFontSize(18);
        doc.text('CADASTRO FISCAL DOS PRODUTOS', margem, y);
        y += 10;

        doc.setFont('helvetica', 'normal');
        doc.setFontSize(11);
        var lojaTxt = String(lojaNome).replace(/[^\x20-\x7E]/g, '?');
        doc.text('Loja: ' + lojaTxt + '   (cod_empresa ' + (codEmpresa || 0) + ')', margem, y);
        y += 6;
        doc.setFontSize(10);
        doc.text('Data de geracao: ' + stamp, margem, y);
        y += 6;
        doc.text('Total de produtos analisados: ' + fmtInt(total), margem, y);
        y += 10;

        doc.setFont('helvetica', 'bold');
        doc.setFontSize(11);
        doc.text('RESUMO DE PROBLEMAS FISCAIS', margem, y);
        y += 6;
        doc.setFont('helvetica', 'normal');
        doc.setFontSize(10);
        var linhasResumo = [
            'Sem NCM cadastrado: ' + fmtInt(semNcm) + ' (' + pctOf(semNcm) + ')',
            'NCM com formato invalido (diferente de 8 digitos): ' + fmtInt(ncmInvalido),
            'Sem CEST mas marcado como ST: ' + fmtInt(semCest),
            'Sem CST/CSOSN: ' + fmtInt(semCst)
        ];
        for (var lr = 0; lr < linhasResumo.length; lr++) {
            doc.text(linhasResumo[lr], margem, y);
            y += 6;
        }
        y += 4;

        doc.setFont('helvetica', 'normal');
        doc.setFontSize(8);
        doc.setTextColor(80, 80, 80);
        doc.text('Cadastro fiscal extraido direto do ERP Fire Sistemas. Aliquotas e codigos sao por produto (centralizados em ITENS), nao por empresa. Os dados refletem o cadastro da loja no momento da geracao.', margem, y, { maxWidth: W - 2 * margem });
        doc.setTextColor(0, 0, 0);

        // ─── PAGINAS 2+ : TABELA DENSA via autoTable ────────────────────────
        var head = [[
            'COD', 'Descricao', 'NCM', 'CEST', 'Orig', 'CST',
            'Aliq ICMS', 'Aliq PIS', 'Aliq COFINS', 'Status'
        ]];
        var body = linhas.map(function (r) {
            return [
                String(r.COD_ITEM || ''),
                String(r.DESCRICAO || ''),
                ouTraco(r.NCM),
                ouTraco(r.CEST),
                fmtOrigem(r.ORIGEM_MERCADORIA),
                ouTraco(r.CST_PRINCIPAL || r.CST_PJ_DENTRO || r.CST_PF_DENTRO || ''),
                fmtAliq(r.ALIQ_ICMS),
                fmtAliq(r.ALIQ_PIS),
                fmtAliq(r.ALIQ_COFINS),
                statusFiscalLinha(r)
            ];
        });

        doc.addPage();
        doc.autoTable({
            head: head,
            body: body,
            startY: margem + 4,
            margin: { left: margem, right: margem, top: margem + 4, bottom: 14 },
            styles: {
                font: 'helvetica',
                fontSize: 8,
                cellPadding: 1.6,
                textColor: [0, 0, 0],
                lineColor: [200, 200, 200],
                lineWidth: 0.1,
                overflow: 'linebreak',
                valign: 'middle'
            },
            headStyles: {
                fillColor: [226, 232, 240],   // #e2e8f0 cinza claro
                textColor: [0, 0, 0],
                fontStyle: 'bold',
                halign: 'left',
                lineColor: [180, 180, 180],
                lineWidth: 0.2
            },
            alternateRowStyles: {
                fillColor: [248, 250, 252]    // #f8fafc — zebra
            },
            columnStyles: {
                0: { cellWidth: 20, fontStyle: 'bold' },        // COD
                1: { cellWidth: 78 },                            // Descricao
                2: { cellWidth: 22 },                            // NCM
                3: { cellWidth: 18 },                            // CEST
                4: { cellWidth: 12, halign: 'center' },          // Origem
                5: { cellWidth: 16, halign: 'center' },          // CST
                6: { cellWidth: 22, halign: 'right' },           // Aliq ICMS
                7: { cellWidth: 22, halign: 'right' },           // Aliq PIS
                8: { cellWidth: 22, halign: 'right' },           // Aliq COFINS
                9: { cellWidth: 41 }                             // Status (texto, sem cor)
            },
            theme: 'plain',
            tableLineColor: [200, 200, 200],
            tableLineWidth: 0.1,
            showHead: 'everyPage'
        });

        // ─── FOOTER em TODAS as paginas (capa + tabelas) ────────────────────
        var totalPg = doc.internal.getNumberOfPages();
        for (var p = 1; p <= totalPg; p++) {
            doc.setPage(p);
            doc.setDrawColor(180, 180, 180);
            doc.setLineWidth(0.1);
            doc.line(margem, H - 10, W - margem, H - 10);
            doc.setFont('helvetica', 'normal');
            doc.setFontSize(8);
            doc.setTextColor(80, 80, 80);
            doc.text('Pagina ' + p + ' de ' + totalPg, margem, H - 5);
            doc.text('Gerado pelo Fire Sistemas em ' + stamp, W - margem, H - 5, { align: 'right' });
        }

        var nome = 'cadastro-fiscal-' + slug(lojaNome) + '-' + carimboArquivo() + '.pdf';
        doc.save(nome);
    }

    // ════════════════════════════════════════════════════════════════════════
    // Depto de Engenharia e Automacao - Master Automacao - Autor: Derlivon Silva
    //
    // Injeta opcao "Cadastro Fiscal (PDF)" no FAB do pbi-export.js.
    // Mesma logica de retry/idempotencia do Executivo e do Limpo.
    // Icone bi-file-medical-alt cor #1e40af (azul escuro fiscal).
    // ════════════════════════════════════════════════════════════════════════
    (function injetarOpcaoFiscal() {
        function tentar() {
            var menu = document.getElementById('pbi-fab-menu');
            if (!menu) return false;
            if (menu.querySelector('#opt-pdf-fiscal')) return true; // ja injetado

            // Pega o estilo dos itens existentes pra ficar igual visualmente
            var ref = menu.querySelector('a, button');
            var classeRef = ref ? ref.className : '';

            // Cria a opcao nova como ultima do menu (apos a Limpo)
            var a = document.createElement('a');
            a.id = 'opt-pdf-fiscal';
            a.href = '#';
            a.className = classeRef;
            a.innerHTML = '<i class="bi bi-file-medical-alt" style="color:#1e40af;margin-right:.5rem"></i>Cadastro Fiscal por Produto (PDF)';
            a.style.cssText = 'display:flex;align-items:center;padding:.5rem .9rem;text-decoration:none;color:#1e293b;border-radius:6px';
            a.onclick = function (ev) {
                ev.preventDefault();
                if (typeof window.toggleFabMenu === 'function') window.toggleFabMenu(); // fecha menu
                if (typeof window.gerarPDFFiscal === 'function') {
                    window.gerarPDFFiscal();
                } else {
                    alert('Funcao do PDF fiscal nao carregou. Recarregue a pagina (Ctrl+F5).');
                }
                return false;
            };

            // Hover sutil
            a.addEventListener('mouseenter', function () { a.style.background = '#f1f5f9'; });
            a.addEventListener('mouseleave', function () { a.style.background = ''; });

            menu.appendChild(a);
            return true;
        }

        var tentativas = 0;
        var iv = setInterval(function () {
            tentativas++;
            if (tentar() || tentativas >= 20) clearInterval(iv);
        }, 250);

        document.addEventListener('DOMContentLoaded', function () { setTimeout(tentar, 600); });
    })();

    // ════════════════════════════════════════════════════════════════════════
    // Esconde a opcao "Imprimir / PDF" do FAB global SO nesta tela
    // (Derlivon nao quer confundir o cliente — usar "Exportar PDF" do card).
    // pbi-export.js NAO e tocado; apagamos somente o item na DOM local.
    // Idempotente; retry com setInterval ate 5s pra pegar o FAB carregando.
    // ════════════════════════════════════════════════════════════════════════
    (function esconderImprimir() {
        var ESCONDIDO_ATTR = 'data-pbi-imprimir-escondido';

        function tentar() {
            var menu = document.getElementById('pbi-fab-menu');
            if (!menu) return false;

            // Ja escondido? entao seguir.
            if (menu.getAttribute(ESCONDIDO_ATTR) === '1') return true;

            // Acha o item cujo texto contem "Imprimir" (case-insensitive)
            var itens = menu.querySelectorAll('a, button');
            var alvo  = null;
            for (var i = 0; i < itens.length; i++) {
                var txt = (itens[i].textContent || '').toLowerCase();
                if (txt.indexOf('imprimir') !== -1) {
                    alvo = itens[i];
                    break;
                }
            }
            if (!alvo) return false;

            // Esconde o <hr> imediatamente anterior (separador), se houver.
            var prev = alvo.previousElementSibling;
            if (prev && prev.tagName && prev.tagName.toLowerCase() === 'hr') {
                prev.style.display = 'none';
            }
            alvo.style.display = 'none';
            menu.setAttribute(ESCONDIDO_ATTR, '1');
            return true;
        }

        var tentativas = 0;
        var iv = setInterval(function () {
            tentativas++;
            // 20 x 250ms = 5s
            if (tentar() || tentativas >= 20) clearInterval(iv);
        }, 250);

        document.addEventListener('DOMContentLoaded', function () { setTimeout(tentar, 600); });
    })();
})();
</script>
