<?php
// ---------- INICIALIZAÇÃO ----------
ob_start();
ini_set('display_errors', 1);
error_reporting(E_ALL);

include 'autentica.php';

require 'vendor/autoload.php';

use Smalot\PdfParser\Parser;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

//------- FUNÇÕES AUXILIARES -------
function normalize($str) {
    $str = mb_strtolower(trim($str), 'UTF-8');
    $str = preg_replace('/[áàãâä]/u', 'a', $str);
    $str = preg_replace('/[éèêë]/u', 'e', $str);
    $str = preg_replace('/[íìîï]/u', 'i', $str);
    $str = preg_replace('/[óòõôö]/u', 'o', $str);
    $str = preg_replace('/[úùûü]/u', 'u', $str);
    $str = preg_replace('/ç/u', 'c', $str);
    $str = preg_replace('/ñ/u', 'n', $str);
    return $str;
}
function isTextoAdministrativo($str) {
    $admin = [
        '/centralizadora/i','/licit[çc][aã]o de joias?/i','/data da licit[çc][aã]o/i',
        '/anota[çc][oõ]es?/i','/p[aá]gina \\d+ de \\d+/i','/n[ou]m?ero/i','/processo/i','/^c[óo]digo/i'
    ];
    foreach ($admin as $p) if (preg_match($p, $str)) return true;
    return false;
}
function extrai_peso_descricao($descricao) {
    if (preg_match('/PESO\\s*LOTE\\s*[: ]+\\s*([\\d.,]+)\\s*[gG]/u', $descricao, $m)) {
        $peso = str_replace(',', '.', $m[1]);
        return is_numeric($peso) ? $peso : '';
    }
    if (preg_match('/PESO\\s*LOTE\\s*[: ]+\\s*([\\d.,]+)/u', $descricao, $m)) {
        $peso = str_replace(',', '.', $m[1]);
        return is_numeric($peso) ? $peso : '';
    }
    return '';
}
function isAvariaDes($desc){
    return preg_match('/amassad[as]*|amolgad[as]*|defeito[s]*|partid[ao]s*|falta(?!ndo)[s]?|faltando/i',$desc);
}
function isDescricaoExcluida($desc_norm) {
    $termos_excluidos = [
        '10k','12k','14k','16k','aco','aco-ouro','aço','aço-ouro','banhado','banho',
        'bijuterias','cobre','cristal','cristais','esmalte','fecho de metal nao nobre','fecho metal nao nobre',
        'folheado','massa','metal n nobre','metal nao nobre','metal não nobre','nao nobre','não nobre',
        'oxidacao','oxidação','oxidado','ouro baixo','ouro branco baixo','paladiu','paladio',
        'perola falsa','perolas cultivadas','prata','prata 925','prata 950','prata paladio',
        'rodio','zircônias'
    ];
    foreach ($termos_excluidos as $pal) {
        if (preg_match('/(?:\\b|\\W)'.preg_quote($pal, '/').'(?:\\b|\\W)/u', $desc_norm)) {
            return true;
        }
    }
    return false;
}

// =========== FRONTEND ===========
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_FILES['pdf_file'])):
?>
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="utf-8">
<title>Ferramenta Inteligente | Gerador de Planilha Inteligente</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
html,body { min-height: 100vh; margin: 0; padding: 0; background: #f8fafc;}
body { display: flex; align-items: center; justify-content: center; min-height: 100vh;}
.main-box {box-sizing: border-box; background: #fff; border-radius: 26px; box-shadow: 0 2px 22px #0001;
    width: 97vw; max-width: 430px; padding: 35px 18px 28px 18px; margin: 18px 0;
    display: flex; flex-direction: column; align-items: center;}
.title-flex { display: flex; flex-direction: row; align-items: flex-end; justify-content: flex-start; width: 100%; gap: 9px; margin-bottom: 0;}
.title-main {font-family: 'Inter', Arial, sans-serif; font-size: 1.28rem; font-weight: 800; letter-spacing: -.01em; line-height: 1.04; color: #22228a; margin: 0; padding: 0;}
.title-side {font-family: 'Inter', Arial, sans-serif; font-size: 1.13rem; font-weight: 700; color: #6C53DD; margin: 0 0 0 4px; padding: 0; line-height: 1.04;}
.main-box .desc {color: #1d1e26; text-align: justify; font-size: 1.09rem; margin: 30px 0 22px 0; font-weight: 400; line-height: 1.49;}
.upload-box { width: 100%; min-height: 92px; border: 2px dashed #dad8e7; border-radius: 15px;
    background: #fafafd; color: #afb5cc; display: flex; align-items: center; justify-content: center;
    text-align: center; font-size: 1.10rem; cursor: pointer; margin-bottom: 28px; transition: border-color .22s, background .22s, color .2s; font-weight: 500;}
.upload-box.dragover { border-color: #6c53dd; background: #edebfd; color: #454473;}
.upload-box.filled { background: #e6faea !important; color: #24663a !important; border-color: #e6faea !important; }
.upload-box input[type="file"] { display: none;}
.main-box button { width: 100%; max-width: 100%; display: block; margin: 0 auto;
    background: #6c53dd; color: #fff; font-weight: 800; border: none; font-size: 1.18rem; border-radius: 12px;
    padding: 17px 0; margin-top: 0; margin-bottom: 0; box-shadow: 0 1px 8px #0001; cursor: pointer; transition: background .17s; letter-spacing: 0.01em;}
.main-box button:hover, .main-box button:focus { background: #421db6;}
.main-box .note { margin-top: 23px; color: #545d6e; background: none; text-align: center; font-size: 1.01rem; line-height: 1.38;}
.msg-erro { color: #b11421; background: #ffe5e5; padding: 13px; margin-bottom: 18px; border-radius: 10px; text-align: center; font-size: 1.09rem;}
@media (max-width:600px) {.main-box {padding:12vw 3vw 7vw 3vw;}.title-main {font-size:1.01rem;}.title-side {font-size:.87rem;}}
</style>
    <script src="protecao_min.js"></script>   
</head>
<body>
    <a class="btn btn-secondary d-inline-flex align-items-center">← Retornar ao Dashboard</a><br>
<div class="main-box">
    <div class="title-flex">
    <a class="btn btn-secondary mb-2" href="dashboard.php">← Retornar ao Dashboard</a><br>
    <span class="title-main">Ferramenta Inteligente</span>
        <span class="title-side">Planilha Inteligente</span>
    </div>
    <div class="desc">
        Faça o download o catálogo de licitação de joias do leilão da Caixa Econômica Federal, em formato PDF, e utilize nossa Planilha Inteligente para transformar o documento em uma análise estruturada. A ferramenta processa automaticamente os dados, extraindo e organizando informações essenciais para facilitar a avaliação dos lotes de joias do catálogo.
    </div>
    <?php if (isset($_SESSION['erro'])) { echo "<div class='msg-erro'>{$_SESSION['erro']}</div>"; unset($_SESSION['erro']); } ?>
    <form method="post" enctype="multipart/form-data" style="width:100%;" id="form-main">
        <label class="upload-box" id="drop-area">
            <span id="upload-text">Clique ou arraste o arquivo (.pdf) aqui</span>
            <input type="file" name="pdf_file" id="pdf_file" accept="application/pdf" required>
        </label>
        <button type="submit">Analisar PDF e Baixar Planilha</button>
    </form>
    <div class="note">
        Compatível exclusivamente com o catálogo de licitação de joias da Caixa Econômica Federal.
    </div>
</div>
<script>
const dropArea = document.getElementById('drop-area');
const uploadText = document.getElementById('upload-text');
const fileInput = document.getElementById('pdf_file');
dropArea.addEventListener('dragover', (e)=>{e.preventDefault(); dropArea.classList.add('dragover');});
dropArea.addEventListener('dragleave', (e)=>{e.preventDefault(); dropArea.classList.remove('dragover');});
dropArea.addEventListener('drop', (e)=>{
    e.preventDefault(); dropArea.classList.remove('dragover');
    if (e.dataTransfer.files.length) {
        fileInput.files = e.dataTransfer.files;
        uploadText.textContent = e.dataTransfer.files[0].name;
        dropArea.classList.add('filled');
    }
});
dropArea.addEventListener('click', ()=>{fileInput.click();});
fileInput.addEventListener('change', ()=>{
    if (fileInput.files.length) {
        uploadText.textContent = fileInput.files[0].name;
        dropArea.classList.add('filled');
    } else {
        uploadText.textContent = 'Arraste e solte aqui ou clique para fazer o download do arquivo em PDF';
        dropArea.classList.remove('filled');
    }
});
</script>
</body>
</html>
<?php
exit; endif;

// =========== BACKEND ===========
try {
    // ### INÍCIO DA CORREÇÃO ###
    // Aumenta o tempo limite de execução para evitar o erro de timeout.
    set_time_limit(0);
    // ### FIM DA CORREÇÃO ###

    $parser = new Parser();
    $pdf = $parser->parseFile($_FILES['pdf_file']['tmp_name']);
    $lines = preg_split('/\r\n|\n|\r/', $pdf->getText());
    unset($parser);

    $linesok = [];
    foreach ($lines as $l) {
        $lt = preg_replace('/([0-9])\s+([0-9])/', '$1$2', $l);
        $lt = preg_replace('/([0-9])\s*\.\s*([0-9])/', '$1.$2', $lt);
        $linesok[] = trim($lt);
    }
    $lines = $linesok;

    $pattern_lote     = '/(\\d{4}\\.\\d{6}-\\d)/';
    $pattern_contrato = '/(\\d{4,6}\\.\\d{3,6}\\.\\d{8,10}-\\d)/';

    $lotes = [];
    for ($i=0; $i<count($lines); $i++) {
        $linha = trim($lines[$i]);
        if (!preg_match($pattern_lote, $linha, $match_lote)) continue;
        $lote_code = preg_replace('/[^0-9\\.\\-]/', '', $match_lote[1]);
        $contrato_line = null; $kcontrato = null;
        for ($j=$i+1; $j<$i+6 && $j<count($lines); $j++) {
            $proxima = trim($lines[$j]);
            if (preg_match($pattern_contrato, $proxima, $match_contrato)) {
                $contrato_line = preg_replace('/[^0-9\\.\\-]/', '', $match_contrato[1]);
                $kcontrato = $j;
                break;
            }
        }
        if (!$contrato_line) continue;
        $descBuffer = [];
        for ($j=$kcontrato+1;$j<count($lines);$j++) {
            $desc = trim($lines[$j]);
            if (preg_match($pattern_lote, $desc) || preg_match($pattern_contrato, $desc) ||
                preg_match('/^p[eê]so\\s*lote[:\\s]/i', $desc) ||
                preg_match('/^r\\$[\\s\\d]/i', $desc) ||
                preg_match('/^valor:?/i', $desc) ||
                isTextoAdministrativo($desc)
            ) break;
            if ($desc!=='') $descBuffer[] = $desc;
        }
        $descFinal = trim(implode(" ", $descBuffer));
        $peso = extrai_peso_descricao($descFinal);

        $valor = null;
        for ($j = $kcontrato+1; $j < $kcontrato+20 && $j < count($lines); $j++) {
            $lk = trim($lines[$j]);
            if (
                preg_match($pattern_lote, $lk) || preg_match($pattern_contrato, $lk) ||
                preg_match('/^p[eê]so\\s*lote[:\\s]/i', $lk) ||
                preg_match('/^valor:?/i', $lk) || isTextoAdministrativo($lk)
            ) break;
            if (!$valor && preg_match('/^R\$\s*([\d\.\,]+)/', $lk, $mV)) {
                $val = str_replace(['.', ','], ['', '.'], $mV[1]);
                $valor = floatval($val);
            }
        }
        if ($valor === null) {
            if (preg_match('/R\$\s*([\d\.\,]+)/', $descFinal, $mVdesc)) {
                $val = str_replace(['.', ','], ['', '.'], $mVdesc[1]);
                $valor = floatval($val);
                $descFinal = preg_replace('/\\s*R\$\s*[\d\.\,]+/', '', $descFinal);
                $descFinal = trim($descFinal);
            }
        }
        $lotes[] = [
            'Lote'=>$lote_code,
            'Contrato'=>$contrato_line,
            'Descrição'=>$descFinal,
            'Peso'=>$peso,
            'Valor'=>$valor
        ];
    }

    $marcas_famosas = [
    'AERODIN',
    'AIDA',
    'ALEXORA',
    'ALLYNE',
    'ALPINUS',
    'ALTAIR',
    'ALTO WATCH',
    'ANCHOR',
    'ANCRE',
    'ANCORA SUIZA',
    'ANTONIO BERNARDO',
    'ANVICO',
    'ARISTON',
    'ASCOT',
    'ASTROLUX',
    'ATIC',
    'AUDEMARS PIGUET',
    'AUREOLE',
    'AVIA',
    'AYRTON SENNA',
    'BAUME & MERCIER',
    'BAUME E MERCIER',
    'BEGUELIN',
    'BELFORT',
    'BELL & ROSS',
    'BENFRE',
    'BERTANI CO',
    'BILU',
    'BIRMA',
    'BLANCPAIN',
    'BONHEUR',
    'BRAMA',
    'BREGUET',
    'BREITLING',
    'BRESSAN',
    'BRITIX',
    'BUCCELLATI',
    'BUCHERER',
    'BULGARI',
    'BULOVA',
    'BUTEX',
    'BVLGARI',
    'BWC',
    'CAMY',
    'CAPELLO',
    'CARLA AMORIM',
    'CARTIER',
    'CARTIER MUST 21',
    'CASIO',
    'CAUNY',
    'C.E. LARDET',
    'CHANDLER',
    'CHATEL',
    'CHOPARD',
    'CHRONOGRAPHE SUISSE',
    'CHRONO SUISS',
    'CITIZEN',
    'CITRA',
    'CLASSIC',
    'CODINA',
    'CONCORD',
    'CORNANVIM',
    'CORUM',
    'CYMA',
    'DE GRISOGONO',
    'DELBANA',
    'DELUXE QUARTZ',
    'DEN-RO',
    'DENRO',
    'DESTAK',
    'DIESEL',
    'DOCKER',
    'DODANE',
    'DODY',
    'DOINA',
    'DOXA',
    'DREYFUSS',
    'DRYZUN',
    'DUBEY',
    'DUBEY & SCHALDENBRAND',
    'EBEL',
    'EBERHARD & CO',
    'EDELTO',
    'EIDLTO',
    'ELECTION',
    'ELGA',
    'ELGIN',
    'ELGÉ',
    'ELIZ',
    'ELOGA',
    'EMBE',
    'ENICAR',
    'EOOX',
    'ERGUEL',
    'ESKA',
    'ETERNA',
    'ETERNA MATIC',
    'ETERNAΜΑΤIC',
    'ETERNAMATIC',
    'ETTA',
    'EXTRA',
    'F.O.S.A',
    'FARO',
    'FELLOW WATCH',
    'FELIZ',
    'FIEL',
    'FLEUR',
    'FLORAL',
    'FLUA',
    'FLUVA',
    'FOREST',
    'FORTIS',
    'FORTRESS',
    'FOSSIL',
    'FRANCK MULLER',
    'FUTURA',
    'G.U.E',
    'GENE WATCH',
    'GENEVE',
    'GERALD GENTA',
    'GIRARD PERREGAUX',
    'GLYCINE',
    'GOLDMATIC',
    'GOLDTEX',
    'GONDOLO LABOURIAN',
    'GRAFF',
    'GRAHAM',
    'GUCCI',
    'GUESS',
    'GVILLEREUSE',
    'HAMILTON',
    'HARRY WINSTON',
    'H. STERN',
    'H STERN',
    'HEBE',
    'HELOISA',
    'HELVETIA',
    'HERALD',
    'HUBLOT',
    'HUMBERT RAMUZ & CO.',
    'HY MOSER & CE',
    'IMPERATOR AVSTRIAE',
    'IMPERIAL',
    'INTERNACIONAL WATCH CO.',
    'INTERNATIONAL WATCH',
    'INVINCIBLE',
    'IOANNES XXIII',
    'IWC',
    'JAEGER LE COULTRE',
    'JAEGER-LECOULTRE',
    'JEAN-PIERRE',
    'JENCO',
    'JOHN KENNEDY',
    'J. POOL LIVERPOOL',
    'J.W.B',
    'KADE',
    'KORA WATCH',
    'LANÇET',
    'LANCO',
    'LAORA',
    'LARDET',
    'LAXEY',
    'LE COUTRE REVERSO',
    'LEONARD',
    'LEVIS',
    'LINCOLN',
    'LIVESTAR',
    'LONGINES',
    'LUMIGE',
    'MAPPIN',
    'MARVIN',
    'MASSON',
    'MEISTERSTUCK',
    'MEISTERTUCK',
    'MENVIS',
    'MERCO',
    'MICHAEL KORS',
    'MIDO',
    'MIRVAINE',
    'MODAIN',
    'MONDAINE',
    'MONT BLANC MEISTERSTUCK 149',
    'MONTBLANC',
    'MORNY',
    'MOVADO',
    'MOVADO ZENITH',
    'MUDU',
    'MUST DE CARTIER',
    'NATAN',
    'NAVY',
    'NEUVCHATEL',
    'NOREXA',
    'ODINA',
    'OINEGUE',
    'OLVINO',
    'OMEGA',
    'OMEGA CONSTELLATION',
    'OMEGA SEAMASTER',
    'OMODOX',
    'ONDINA',
    'ORATOR',
    'ORIS',
    'ORVIN',
    'OYSTER PERPETUAL',
    'OYSTER PERPETUAL DATEJUST',
    'OYSTER PERPETUAL DATEJUST MIDSIZE',
    'OYSTER PERPETUAL LADY DATEJUST',
    'PALAIS ROYAL',
    'PANAMERAI',
    'PANERAI',
    'PANERAI RADIOMIR',
    'PARKER',
    'PARKER 61',
    'PATECK PHILIPPE',
    'PATEK PHELIPPE',
    'PATEK PHILIPPE',
    'PATEK PHILIPPE GENEVE',
    'PATEX PHILLIPPE',
    'PAUL BUHRE',
    'PERFECTA',
    'PEREGRINE',
    'PHILIP WATCH',
    'PIAGET',
    'PLAZA',
    'POLICE',
    'PRECIMAX',
    'PRIMUS',
    'QUARTZ',
    'RADO',
    'RADO JUBILE',
    'RAYMOND WEIL',
    'RAYMOND WEIL CHRONOMETER',
    'REMONTOIR EYLINDRE',
    'RENE',
    'RENNA',
    'RET',
    'RICHARD',
    'RICHARD MILLE',
    'RIGI',
    'ROBERT CART',
    'ROGER DUBUIS',
    'ROLEX',
    'ROTOS',
    'ROVENA',
    'ROYCE',
    'ROX',
    'SALERO',
    'SAMETIC',
    'SANDOZ',
    'SARCAR',
    'SAUER',
    'SCARLET',
    'SCHALDENBRAND',
    'SECULUS',
    'SEIKO',
    'SELLIΤΑ',
    'SELLITA',
    'SEMAG',
    'SILITEX',
    'SIVER PRIM',
    'SONATA',
    'SOREL',
    'STYLIST',
    'SULTAN',
    'SULTANA',
    'SUPER ATIC',
    'SUPERATIC',
    'SUPERMATIC',
    'SURENA',
    'SUZUKI GOLD EDITION',
    'SWISS WATCH',
    'TAG HEUER',
    'TAURIST',
    'TECHNOS',
    'TELL',
    'TERIAM',
    'THE MERIDIAN- J. LIVINGSTONE',
    'THOURY',
    'TIFFANY & CO',
    'TISSOT',
    'TITUS',
    'TONODOR',
    'TORRIGOLD QUARTZ ITALI',
    'TOVARE',
    'TRESSA',
    'TRUCE',
    'TUDOR',
    'ULISSES NARDIN',
    'ULYSSE NARDIN',
    'UNIVERSAL',
    'UNIVERSAL GENEVE',
    'VACHERON E CONSTANTIN GENEVE',
    'VALENTINO',
    'VAN CLEEF & ARPELS',
    'VANCOX',
    'VENUS',
    'VERONI',
    'VERONI ANCRE',
    'VERONICA',
    'VICEROY',
    'VILLEREUSE',
    'VINCENCE',
    'VITOR INOX',
    'VIVARA',
    'VOLKSWAGENEERK',
    'VULCAIN',
    'WALTHAM',
    'WATERMAN',
    'WEGA WATCH',
    'WEMBLEY',
    'WHITE STAR',
    'ZALGER',
    'ZALGUR',
    'ZENITH'
];

    $lotes_ouro        = [];
    $lotes_marcas      = [];
    $lotes_perolas     = [];
    $lotes_semperolas  = [];
    $lotes_diamantes   = [];
    $lotes_naoprec     = [];
    $lotes_avarias     = [];
    $lotes_purezas     = [];

    foreach ($lotes as $lote) {
        $desc_norm = normalize($lote['Descrição']);
        if (isDescricaoExcluida($desc_norm)) continue;
        if (empty($lote['Peso']) || empty($lote['Lote']) || empty($lote['Contrato'])) continue;

        $peso_num  = $lote['Peso'];
        $valor_num = $lote['Valor'];
        $valor_g   = ($valor_num && $peso_num > 0) ? ($valor_num / $peso_num) : null;

        if (!preg_match('/\bouro\b/i', $desc_norm)) continue;

        $tem_marca      = false;
        foreach ($marcas_famosas as $marca) {
            if (strpos($desc_norm, normalize($marca)) !== false) {
                $tem_marca = true;
                break;
            }
        }
        
        $tem_perola        = preg_match('/perolas?|barrocas?/',$desc_norm);
        $tem_diamante      = preg_match('/diamant/',$desc_norm);
        $nao_precificado   = preg_match('/na.?o precificad[oa]s?/',$desc_norm);
        $has_avaria        = isAvariaDes($lote['Descrição']) ? 'SIM':'NÃO';

        $linha = [
            'Lote'               => $lote['Lote'],
            'Contrato'           => $lote['Contrato'],
            'Descrição'          => trim($lote['Descrição']),
            'Peso (g)'           => $peso_num,
            'Valor (R$)'         => $valor_num,
            'Valor/g (R$)'       => ($valor_g!==null?round($valor_g,2):'N/A'),
            'Marca Famosa'       => ($tem_marca?'SIM':'NÃO'),
            'Contém Pérola'      => ($tem_perola?'SIM':'NÃO'),
            'Contém Diamante'    => ($tem_diamante?'SIM':'NÃO'),
            'Não Precificado'    => ($nao_precificado?'SIM':'NÃO'),
            'Avarias'            => $has_avaria
        ];
        $lotes_ouro[] = $linha;
        if ($tem_marca) $lotes_marcas[] = $linha;
        if ($tem_perola) $lotes_perolas[] = $linha;
        if (!$tem_perola) $lotes_semperolas[] = $linha;
        if ($tem_diamante) $lotes_diamantes[] = $linha;
        if ($nao_precificado) $lotes_naoprec[] = $linha;

        if ($has_avaria === 'SIM') {
            $lotes_avarias[] = [
                'Lote'        => $lote['Lote'],
                'Contrato'    => $lote['Contrato'],
                'Descrição'   => trim($lote['Descrição']),
                'Peso (g)'    => $peso_num,
                'Valor (R$)'  => $valor_num,
                'Valor/g (R$)'=> ($valor_g!==null?round($valor_g,2):'N/A')
            ];
        }
    }

    $regex_purezas = '/(\\b18k\\b|\\b19k\\b|\\b20k\\b|\\b21k\\b|\\b22k\\b|\\b23k\\b|\\b24k\\b|\\bouro\\s*999\\b)/i';
    foreach ($lotes_ouro as $linha) {
        $desc_norm = normalize($linha['Descrição']);
        if (preg_match($regex_purezas, $desc_norm, $match)) {
            $lotes_purezas[] = [
                'Lote'          => $linha['Lote'],
                'Contrato'      => $linha['Contrato'],
                'Descrição'     => $linha['Descrição'],
                'Peso (g)'      => $linha['Peso (g)'],
                'Valor (R$)'    => $linha['Valor (R$)'],
                'Valor/g (R$)'  => $linha['Valor/g (R$)']
            ];
        }
    }

    $headers_ouro = [
        'Lote','Contrato','Descrição','Peso (g)','Valor (R$)','Valor/g (R$)',
        'Marca Famosa','Contém Pérola','Contém Diamante','Não Precificado','Avarias'
    ];
    $headers_other = [
        'Lote','Contrato','Descrição','Peso (g)','Valor (R$)','Valor/g (R$)'
    ];
    function remCols($lista) {
        return array_map(function($linha){
            return [
                'Lote'=>$linha['Lote'], 'Contrato'=>$linha['Contrato'], 'Descrição'=>$linha['Descrição'],
                'Peso (g)'=>$linha['Peso (g)'],'Valor (R$)'=>$linha['Valor (R$)'],'Valor/g (R$)'=>$linha['Valor/g (R$)']
            ];
        }, $lista);
    }

    $lotes_spnp = array_filter($lotes_naoprec, function($linha) {
        $d = isset($linha['Descrição']) ? mb_strtolower($linha['Descrição'], 'UTF-8') : '';
        $d_norm = strtr($d, [
            'á'=>'a','à'=>'a','ã'=>'a','â'=>'a','ä'=>'a', 'é'=>'e','è'=>'e','ê'=>'e','ë'=>'e',
            'í'=>'i','ì'=>'i','î'=>'i','ï'=>'i', 'ó'=>'o','ò'=>'o','õ'=>'o','ô'=>'o','ö'=>'o',
            'ú'=>'u','ù'=>'u','û'=>'u','ü'=>'u', 'ç'=>'c'
        ]);
        return !preg_match('/\b(perola|cultivada|barroca)s?\b/u', $d_norm);
    });

    function sortByValorG($a, $b) {
        $val_a = isset($a['Valor/g (R$)']) && is_numeric($a['Valor/g (R$)']) ? (float)$a['Valor/g (R$)'] : INF;
        $val_b = isset($b['Valor/g (R$)']) && is_numeric($b['Valor/g (R$)']) ? (float)$b['Valor/g (R$)'] : INF;
        return $val_a <=> $val_b;
    }

    usort($lotes_ouro, 'sortByValorG');
    usort($lotes_purezas, 'sortByValorG');
    usort($lotes_marcas, 'sortByValorG');
    usort($lotes_perolas, 'sortByValorG');
    usort($lotes_semperolas, 'sortByValorG');
    usort($lotes_diamantes, 'sortByValorG');
    usort($lotes_naoprec, 'sortByValorG');
    $lotes_spnp_array = array_values($lotes_spnp);
    usort($lotes_spnp_array, 'sortByValorG');
    usort($lotes_avarias, 'sortByValorG');

    $abas_ordem = [
        ['OURO', $lotes_ouro, $headers_ouro],
        ['PUREZAS', $lotes_purezas, $headers_other],
        ['MARCAS', remCols($lotes_marcas), $headers_other],
        ['PÉROLAS', remCols($lotes_perolas), $headers_other],
        ['SEM PÉROLAS', remCols($lotes_semperolas), $headers_other],
        ['DIAMANTES', remCols($lotes_diamantes), $headers_other],
        ['NÃO PRECIFICADOS', remCols($lotes_naoprec), $headers_other],
        ['SPNP', remCols($lotes_spnp_array), $headers_other],
        ['AVARIAS', remCols($lotes_avarias), $headers_other]
    ];
    $tabColors = [
        'OURO' => 'FFD700', 'PUREZAS' => 'c7f0be', 'MARCAS' => '93c9ff',
        'PÉROLAS' => 'f3daeb', 'SEM PÉROLAS' => 'eaeaea', 'DIAMANTES' => 'd0e1f8',
        'NÃO PRECIFICADOS' => 'ffe48e', 'SPNP' => 'febacf', 'AVARIAS' => 'fca1a1'
    ];

    $spreadsheet = new Spreadsheet();
    foreach ($abas_ordem as $idx => $tabData) {
        list($tab, $dados, $headers) = $tabData;
        if ($idx === 0) {
            $sheet = $spreadsheet->getActiveSheet();
            $sheet->setTitle($tab);
        } else {
            $sheet = new Worksheet($spreadsheet, $tab);
            $spreadsheet->addSheet($sheet);
        }
        $sheet->fromArray($headers, null, 'A1');
        $row = 2;
        foreach ($dados as $lote) $sheet->fromArray(array_values($lote), null, 'A'.$row++);
        $letterLast = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex(count($headers));
        $headerRange = "A1:{$letterLast}1";
        $sheet->getStyle($headerRange)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER);
        $sheet->getStyle($headerRange)->getFont()->setBold(true)->setSize(12);
        $sheet->getStyle($headerRange)->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB('2d2f7f');
        $sheet->getStyle($headerRange)->getFont()->getColor()->setARGB('FFFFFFFF');
        for ($r=2;$r<$row;$r++) {
            $fill = ($r%2==0)?'f2f6fc':'ffffff';
            $sheet->getStyle("A{$r}:{$letterLast}{$r}")->getFill()->setFillType(Fill::FILL_SOLID)->getStartColor()->setARGB($fill);
        }
        $sheet->getStyle("A1:{$letterLast}".($row-1))->getBorders()->getAllBorders()
            ->setBorderStyle(Border::BORDER_THIN)->setColor(new \PhpOffice\PhpSpreadsheet\Style\Color('cccccc'));
        $colJustify = 3; $colCount = count($headers);
        for ($col=1;$col<=$colCount;$col++) {
            $range = \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col)."2:".
                \PhpOffice\PhpSpreadsheet\Cell\Coordinate::stringFromColumnIndex($col).($row-1);
            if ($col==$colJustify)
                $sheet->getStyle($range)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT)
                    ->setVertical(Alignment::VERTICAL_TOP)->setWrapText(true);
            else
                $sheet->getStyle($range)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER)
                    ->setVertical(Alignment::VERTICAL_CENTER);
        }
        if (isset($tabColors[$tab])) $sheet->getTabColor()->setRGB($tabColors[$tab]);
        for ($col=1;$col<=$colCount;$col++) {
            if ($col==$colJustify) $sheet->getColumnDimensionByColumn($col)->setWidth(40);
            else $sheet->getColumnDimensionByColumn($col)->setAutoSize(true);
        }
    }
    $spreadsheet->setActiveSheetIndex(0);
    $tmpExcel = tempnam(sys_get_temp_dir(), 'planilha_inteligente_') . '.xlsx';
    $writer = new Xlsx($spreadsheet);
    $writer->save($tmpExcel);

    while (ob_get_level()) ob_end_clean();
    header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    header('Content-Disposition: attachment; filename="Planilha_Inteligente.xlsx"');
    header('Content-Length: '.filesize($tmpExcel));
    readfile($tmpExcel);
    unlink($tmpExcel);
    exit;
} catch(Exception $e) {
    while(ob_get_level()){ob_end_clean();}
    $_SESSION['erro'] = "Erro ao analisar PDF: ".htmlspecialchars($e->getMessage());
    header('Location: '.$_SERVER['PHP_SELF']); exit;
}
?>

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: