<?php
// includes/admin/admin-import-royalties.php

if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * Renderiza a Página de Importação de Royalties.
 * Passo 1: Upload.
 * Passo 2: Dashboard de Análise (Raio-X do CSV).
 */
function rmbz_render_import_royalties_page() {
    
    // Se o formulário do Passo 1 foi enviado, mostramos o Passo 2 (Preview Inteligente)
    if ( isset($_POST['action']) && $_POST['action'] === 'preview_import' && !empty($_FILES['royalties_csv']) ) {
        rmbz_render_preview_analysis();
        return;
    }

    // [DS 1.5.115] Reentrada para additional import / unrevert: o utilizador
    // chega aqui via GET com ?temp_file=... a apontar para um CSV já no
    // /uploads/rmbz_temp_imports/. Renderizamos o preview directamente.
    if ( isset($_GET['temp_file']) && ( isset($_GET['from_additional']) || isset($_GET['from_unrevert']) ) ) {
        $tmp_name = sanitize_file_name( $_GET['temp_file'] );
        if ( ! empty($tmp_name) ) {
            $upload_dir = wp_upload_dir();
            $tmp_path = $upload_dir['basedir'] . '/rmbz_temp_imports/' . $tmp_name;
            if ( file_exists($tmp_path) ) {
                // Banner consoante origem
                $from_additional = (int) ($_GET['from_additional'] ?? 0);
                $from_unrevert   = (int) ($_GET['from_unrevert']   ?? 0);
                if ( $from_additional > 0 ) {
                    echo '<div class="notice notice-info" style="margin:20px 0; border-left:4px solid #0073aa; padding:16px;">'
                       . '<h3 style="margin-top:0;">↻ Re-importar do mesmo CSV — apanhar linhas em falta</h3>'
                       . '<p>Estás a reabrir o CSV da importação <strong>#' . $from_additional . '</strong>. '
                       . 'As linhas que <strong>já foram importadas</strong> aparecem marcadas com 🔒 e estão '
                       . 'desmarcadas por defeito (para evitar duplicação). '
                       . 'As que tinham sido desmarcadas ou que ainda não estão no sistema podem ser seleccionadas e importadas.</p>'
                       . '</div>';
                } elseif ( $from_unrevert > 0 ) {
                    echo '<div class="notice notice-info" style="margin:20px 0; border-left:4px solid #0073aa; padding:16px;">'
                       . '<h3 style="margin-top:0;">↶ Desfazer Anulação — re-processar CSV original</h3>'
                       . '<p>Estás a reprocessar o CSV da importação anulada <strong>#' . $from_unrevert . '</strong>. '
                       . 'Vai ser criada uma importação nova com os dados originais.</p>'
                       . '</div>';
                }
                rmbz_render_preview_analysis( $tmp_path, $tmp_name );
                return;
            } else {
                echo '<div class="notice notice-error"><p>O ficheiro temporário não foi encontrado. Pode ter expirado — tenta de novo.</p></div>';
            }
        }
    }

    // ==========================================================================
    // PASSO 1: UPLOAD DO FICHEIRO
    // ==========================================================================
    ?>
    <div class="rmbz-imp">

        <?php if ( isset($_GET['import_status']) && $_GET['import_status'] === 'done' ): ?>
            <div class="rmbz-imp-success">
                <span class="rmbz-imp-success-ico">✅</span>
                <div><strong>Importação concluída.</strong> O relatório foi processado e o dinheiro distribuído pelos artistas.</div>
            </div>
        <?php endif; ?>

        <!-- HERO -->
        <div class="rmbz-imp-hero">
            <div class="rmbz-imp-hero-glow"></div>
            <span class="rmbz-imp-hero-ico">📊</span>
            <h2>Importar relatório financeiro</h2>
            <p>Carrega o CSV da distribuidora — analisamos linha a linha, detetamos a moeda e o período, e distribuímos os royalties automaticamente pelos artistas certos.</p>
        </div>

        <!-- PASSOS DO PROCESSO -->
        <div class="rmbz-imp-steps">
            <div class="rmbz-imp-step is-current">
                <span class="rmbz-imp-step-n">1</span>
                <div><strong>Carregar</strong><span>Escolhe a distribuidora e o ficheiro CSV.</span></div>
            </div>
            <span class="rmbz-imp-step-arrow">→</span>
            <div class="rmbz-imp-step">
                <span class="rmbz-imp-step-n">2</span>
                <div><strong>Analisar</strong><span>Pré-visualizas totais, lojas, países e faixas.</span></div>
            </div>
            <span class="rmbz-imp-step-arrow">→</span>
            <div class="rmbz-imp-step">
                <span class="rmbz-imp-step-n">3</span>
                <div><strong>Distribuir</strong><span>Confirmas e o valor cai nas carteiras.</span></div>
            </div>
        </div>

        <form method="post" enctype="multipart/form-data" id="rmbz-imp-form" class="rmbz-imp-card">
            <input type="hidden" name="action" value="preview_import">
            <?php wp_nonce_field('rmbz_import_step1_nonce'); ?>

            <?php if ( function_exists('rmbz_render_profile_selector') ) rmbz_render_profile_selector( 'amadea' ); ?>

            <label class="rmbz-imp-drop" id="rmbz-imp-drop">
                <input type="file" name="royalties_csv" id="csv_file" accept=".csv" required hidden>
                <span class="rmbz-imp-drop-ico">📎</span>
                <span class="rmbz-imp-drop-title" id="rmbz-imp-drop-title">Arrasta o CSV para aqui</span>
                <span class="rmbz-imp-drop-sub" id="rmbz-imp-drop-sub">ou clica para escolher · apenas ficheiros .csv</span>
                <span class="rmbz-imp-drop-file" id="rmbz-imp-drop-file" hidden></span>
            </label>

            <div class="rmbz-imp-actions">
                <button type="submit" class="button button-primary button-hero rmbz-imp-submit" id="rmbz-imp-submit" disabled>
                    Analisar ficheiro →
                </button>
            </div>

            <div class="rmbz-imp-tips">
                <span>🔒 Nada é distribuído nesta fase — só vais ver uma pré-visualização.</span>
                <span>🔁 Ficheiros repetidos são detetados por hash para evitar pagamentos em duplicado.</span>
            </div>
        </form>
    </div>

    <!-- OVERLAY DE PROGRESSO -->
    <div class="rmbz-imp-overlay" id="rmbz-imp-overlay" aria-hidden="true">
        <div class="rmbz-imp-overlay-card">
            <div class="rmbz-imp-spinner"></div>
            <h3 id="rmbz-imp-phase">A enviar o ficheiro…</h3>
            <div class="rmbz-imp-bar"><span id="rmbz-imp-bar-fill"></span></div>
            <ul class="rmbz-imp-phaselist" id="rmbz-imp-phaselist">
                <li data-phase="0">A enviar o ficheiro para o servidor</li>
                <li data-phase="1">A ler as linhas do CSV</li>
                <li data-phase="2">A detetar a distribuidora e a moeda</li>
                <li data-phase="3">A calcular totais por loja, país e faixa</li>
                <li data-phase="4">A preparar a pré-visualização</li>
            </ul>
            <p class="rmbz-imp-overlay-note">Não feches esta janela — ficheiros grandes podem demorar alguns segundos.</p>
        </div>
    </div>

    <style>
    .rmbz-imp { max-width: 920px; margin-left: auto; margin-right: auto; }
    .rmbz-imp-success {
        display: flex; align-items: center; gap: 14px; margin: 18px 0;
        background: linear-gradient(135deg, #ecfdf3, #f6fef9);
        border: 1px solid #a6f4c5; border-radius: 16px; padding: 16px 20px;
        animation: rmbz-imp-rise .5s cubic-bezier(.4,0,.2,1) both;
    }
    .rmbz-imp-success-ico { font-size: 26px; }
    .rmbz-imp-success strong { color: #08653a; }
    @keyframes rmbz-imp-rise { from { opacity:0; transform: translateY(12px); } to { opacity:1; transform:none; } }

    /* Hero */
    .rmbz-imp-hero {
        position: relative; overflow: hidden; text-align: center;
        margin: 20px 0; padding: 34px 28px;
        border-radius: 24px; color: #fff;
        background: linear-gradient(135deg, #6e61f0, #5243dc 55%, #2c2196);
        box-shadow: 0 14px 36px rgba(82,67,220,.28);
        animation: rmbz-imp-rise .5s cubic-bezier(.4,0,.2,1) both;
    }
    .rmbz-imp-hero-glow { position: absolute; width: 220px; height: 220px; right: -50px; top: -80px; border-radius: 50%; background: radial-gradient(circle, rgba(255,255,255,.18), transparent 70%); }
    .rmbz-imp-hero-ico { font-size: 40px; display: block; }
    .rmbz-imp-hero h2 { margin: 10px 0 6px; font-size: 24px; font-weight: 800; color: #fff; }
    .rmbz-imp-hero p { margin: 0 auto; max-width: 560px; font-size: 13px; line-height: 1.6; color: rgba(255,255,255,.82); }

    /* Passos */
    .rmbz-imp-steps { display: flex; align-items: stretch; justify-content: center; gap: 8px; flex-wrap: wrap; margin: 18px 0; }
    .rmbz-imp-step { display: flex; align-items: center; gap: 11px; background: #fff; border: 1px solid #e6e8eb; border-radius: 14px; padding: 12px 16px; flex: 1; min-width: 200px; box-shadow: 0 1px 2px rgba(16,24,40,.04); }
    .rmbz-imp-step.is-current { border-color: #c7c0fb; background: #f6f5ff; }
    .rmbz-imp-step-n { width: 28px; height: 28px; border-radius: 50%; background: #eef0f3; color: #6b7280; font-weight: 800; font-size: 13px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
    .rmbz-imp-step.is-current .rmbz-imp-step-n { background: linear-gradient(135deg,#7c6df2,#5a4be0); color: #fff; box-shadow: 0 3px 8px rgba(99,86,229,.3); }
    .rmbz-imp-step strong { display: block; font-size: 13px; color: #16181d; }
    .rmbz-imp-step span { font-size: 11px; color: #6b7280; }
    .rmbz-imp-step-arrow { display: flex; align-items: center; color: #c2c7cf; font-size: 18px; }
    @media (max-width: 700px) { .rmbz-imp-step-arrow { display: none; } }

    /* Card de upload */
    .rmbz-imp-card { background: #fff; border: 1px solid #e6e8eb; border-radius: 22px; padding: 24px; margin: 18px 0; box-shadow: 0 1px 3px rgba(16,24,40,.05); animation: rmbz-imp-rise .5s cubic-bezier(.4,0,.2,1) both; }

    /* Dropzone */
    .rmbz-imp-drop {
        display: flex; flex-direction: column; align-items: center; gap: 4px;
        padding: 38px 24px; margin-top: 8px; cursor: pointer; text-align: center;
        border: 2px dashed #cdd2da; border-radius: 18px; background: #fafbfc;
        transition: all .2s cubic-bezier(.4,0,.2,1);
    }
    .rmbz-imp-drop:hover { border-color: #6356E5; background: #f6f5ff; }
    .rmbz-imp-drop.is-dragover { border-color: #6356E5; background: #efecff; transform: scale(1.01); }
    .rmbz-imp-drop.has-file { border-style: solid; border-color: #34c98e; background: #f0fdf6; }
    .rmbz-imp-drop-ico { font-size: 34px; transition: transform .25s cubic-bezier(.34,1.56,.64,1); }
    .rmbz-imp-drop:hover .rmbz-imp-drop-ico { transform: translateY(-4px); }
    .rmbz-imp-drop-title { font-size: 15px; font-weight: 800; color: #16181d; }
    .rmbz-imp-drop-sub { font-size: 12px; color: #8a909a; }
    .rmbz-imp-drop-file { margin-top: 8px; font-size: 13px; font-weight: 700; color: #08653a; background: #d1fadf; padding: 5px 12px; border-radius: 999px; }

    .rmbz-imp-actions { text-align: center; margin-top: 18px; }
    .rmbz-imp-submit { border-radius: 12px !important; transition: transform .1s, filter .15s, box-shadow .2s !important; box-shadow: 0 4px 14px rgba(99,86,229,.28); }
    .rmbz-imp-submit:not(:disabled):hover { filter: brightness(1.04); }
    .rmbz-imp-submit:not(:disabled):active { transform: scale(.97); }
    .rmbz-imp-submit:disabled { opacity: .5; }

    .rmbz-imp-tips { display: flex; flex-wrap: wrap; gap: 8px 18px; justify-content: center; margin-top: 16px; font-size: 11.5px; color: #6b7280; }

    /* Overlay de progresso */
    .rmbz-imp-overlay { position: fixed; inset: 0; z-index: 99999; display: none; align-items: center; justify-content: center; background: rgba(15,18,28,.55); backdrop-filter: blur(3px); }
    .rmbz-imp-overlay.is-on { display: flex; animation: rmbz-imp-fade .25s ease both; }
    @keyframes rmbz-imp-fade { from { opacity:0; } to { opacity:1; } }
    .rmbz-imp-overlay-card { width: 90%; max-width: 420px; background: #fff; border-radius: 22px; padding: 28px 26px; text-align: center; box-shadow: 0 24px 60px rgba(0,0,0,.3); animation: rmbz-imp-pop .3s cubic-bezier(.34,1.56,.64,1) both; }
    @keyframes rmbz-imp-pop { from { opacity:0; transform: scale(.92); } to { opacity:1; transform: none; } }
    .rmbz-imp-spinner { width: 46px; height: 46px; margin: 0 auto 14px; border-radius: 50%; border: 4px solid #eef0f3; border-top-color: #6356E5; animation: rmbz-imp-spin .8s linear infinite; }
    @keyframes rmbz-imp-spin { to { transform: rotate(360deg); } }
    .rmbz-imp-overlay-card h3 { margin: 0 0 14px; font-size: 17px; font-weight: 800; color: #16181d; }
    .rmbz-imp-bar { height: 8px; background: #eef0f3; border-radius: 999px; overflow: hidden; margin-bottom: 16px; }
    .rmbz-imp-bar span { display: block; height: 100%; width: 0; border-radius: 999px; background: linear-gradient(90deg,#7c6df2,#5a4be0); transition: width .5s cubic-bezier(.4,0,.2,1); }
    .rmbz-imp-phaselist { list-style: none; margin: 0; padding: 0; text-align: left; }
    .rmbz-imp-phaselist li { font-size: 13px; color: #9aa1ad; padding: 5px 0 5px 26px; position: relative; transition: color .2s; }
    .rmbz-imp-phaselist li::before { content: '○'; position: absolute; left: 4px; color: #cdd2da; }
    .rmbz-imp-phaselist li.is-done { color: #16181d; }
    .rmbz-imp-phaselist li.is-done::before { content: '✓'; color: #34c98e; font-weight: 800; }
    .rmbz-imp-phaselist li.is-active { color: #5a4be0; font-weight: 700; }
    .rmbz-imp-phaselist li.is-active::before { content: '◉'; color: #5a4be0; }
    .rmbz-imp-overlay-note { margin: 16px 0 0; font-size: 11px; color: #9aa1ad; }
    </style>

    <script>
    (function() {
        var drop   = document.getElementById('rmbz-imp-drop');
        var input  = document.getElementById('csv_file');
        var submit = document.getElementById('rmbz-imp-submit');
        var fileEl = document.getElementById('rmbz-imp-drop-file');
        var titleEl= document.getElementById('rmbz-imp-drop-title');
        var subEl  = document.getElementById('rmbz-imp-drop-sub');
        var form   = document.getElementById('rmbz-imp-form');
        if (!drop || !input || !form) return;

        function showFile(f) {
            if (!f) return;
            var kb = f.size > 1048576 ? (f.size/1048576).toFixed(1)+' MB' : Math.round(f.size/1024)+' KB';
            fileEl.textContent = '📄 ' + f.name + ' · ' + kb;
            fileEl.hidden = false;
            titleEl.textContent = 'Ficheiro pronto';
            subEl.textContent = 'Clica para trocar de ficheiro';
            drop.classList.add('has-file');
            submit.disabled = false;
        }
        input.addEventListener('change', function() { if (input.files[0]) showFile(input.files[0]); });
        ['dragenter','dragover'].forEach(function(e){ drop.addEventListener(e, function(ev){ ev.preventDefault(); drop.classList.add('is-dragover'); }); });
        ['dragleave','drop'].forEach(function(e){ drop.addEventListener(e, function(ev){ ev.preventDefault(); drop.classList.remove('is-dragover'); }); });
        drop.addEventListener('drop', function(ev) {
            var f = ev.dataTransfer.files[0];
            if (f) { input.files = ev.dataTransfer.files; showFile(f); }
        });

        // Overlay de progresso com fases ao submeter
        form.addEventListener('submit', function() {
            if (!input.files[0]) return;
            var overlay = document.getElementById('rmbz-imp-overlay');
            var phaseTxt = document.getElementById('rmbz-imp-phase');
            var barFill = document.getElementById('rmbz-imp-bar-fill');
            var items = document.querySelectorAll('#rmbz-imp-phaselist li');
            var labels = [
                'A enviar o ficheiro…',
                'A ler as linhas do CSV…',
                'A detetar a distribuidora e a moeda…',
                'A calcular totais…',
                'A preparar a pré-visualização…'
            ];
            overlay.classList.add('is-on');
            overlay.setAttribute('aria-hidden','false');
            var cur = 0;
            function advance() {
                items.forEach(function(li, idx) {
                    li.classList.toggle('is-done', idx < cur);
                    li.classList.toggle('is-active', idx === cur);
                });
                if (phaseTxt) phaseTxt.textContent = labels[Math.min(cur, labels.length-1)];
                if (barFill) barFill.style.width = Math.min((cur+1)/labels.length*92, 92) + '%';
                cur++;
                if (cur <= labels.length) setTimeout(advance, cur === 1 ? 600 : 850);
            }
            advance();
            // O servidor responde com a página de preview — a overlay sai com o reload.
        });
    })();
    </script>
    <?php
}

/**
 * ==========================================================================
 * PASSO 2: DASHBOARD DE ANÁLISE (O RELATÓRIO INTELIGENTE)
 * ==========================================================================
 */

/**
 * ==========================================================================
 * PASSO 2: DASHBOARD PROFISSIONAL DE ANÁLISE
 * ==========================================================================
 * Reescrito para ser um painel completo estilo distribuidora profissional:
 *   - 4 KPIs com valores duplos EUR+USD
 *   - Top lojas com ícones de marca
 *   - Top países com bandeiras emoji
 *   - Top 10 faixas com receita
 *   - Detecção automática de moeda e período
 *   - Duplicate check por hash do ficheiro
 */
function rmbz_render_preview_analysis( $existing_file = null, $existing_temp_name = null ) {
    // [DS 1.5.115] Modo re-entrada (additional/unrevert): se o ficheiro
    // já está no disco, pulamos o upload step e o nonce check.
    $is_reentry = ( $existing_file !== null && $existing_temp_name !== null );

    if ( ! $is_reentry ) {
        check_admin_referer('rmbz_import_step1_nonce');
    }
    global $wpdb;

    if ( $is_reentry ) {
        // Detectar perfil pelo header
        $tmp_handle = fopen($existing_file, 'r');
        $tmp_header = $tmp_handle ? fgetcsv($tmp_handle) : null;
        if ( $tmp_handle ) fclose($tmp_handle);
        if ( $tmp_header && isset($tmp_header[0]) ) {
            $tmp_header[0] = preg_replace('/^\xEF\xBB\xBF/', '', $tmp_header[0]);
        }
        $tmp_lower = $tmp_header ? array_map('strtolower', array_map('trim', $tmp_header)) : [];

        // [FEAT 1.6.9] FIX BUG RE-IMPORT — profile não devia ser re-detectado
        //
        // Quando o admin re-importa via botão (?from_additional=N), o ficheiro
        // é o MESMO que foi importado originalmente. Logo, devia usar o MESMO
        // perfil do log original (Amadea, Zebralution, etc).
        //
        // A tabela rmbz_distro_import_logs NÃO tem coluna 'profile_id' — em
        // vez disso tem 'source_name' com o nome humano (ex: "Amadea Music").
        // Para converter para a chave do perfil, iteramos rmbz_get_all_profiles()
        // e procuramos o que tem `distributor` igual ao source_name.
        $profile_id = null;
        if ( isset($_GET['from_additional']) && (int) $_GET['from_additional'] > 0 ) {
            global $wpdb;
            $orig_log_id = (int) $_GET['from_additional'];

            // Buscar o source_name (não profile_id — essa coluna não existe)
            $orig_source = $wpdb->get_var( $wpdb->prepare(
                "SELECT source_name FROM {$wpdb->prefix}rmbz_distro_import_logs WHERE id = %d",
                $orig_log_id
            ) );

            if ( ! empty($orig_source) && function_exists('rmbz_get_import_profiles') ) {
                // Iterar perfis e achar o que tem o mesmo distributor
                $all_profiles = rmbz_get_import_profiles();
                foreach ( (array) $all_profiles as $pid => $pdata ) {
                    $dist = $pdata['distributor'] ?? ($pdata['name'] ?? '');
                    // Comparação case-insensitive e ignora pequenas variações
                    if ( strcasecmp( $dist, $orig_source ) === 0 ) {
                        $profile_id = $pid;
                        break;
                    }
                }
                // Fallback: comparar com o 'name' completo se distributor não bateu
                if ( $profile_id === null ) {
                    foreach ( (array) $all_profiles as $pid => $pdata ) {
                        if ( strcasecmp( $pdata['name'] ?? '', $orig_source ) === 0 ) {
                            $profile_id = $pid;
                            break;
                        }
                    }
                }
                // Fallback adicional: comparar com 'short'
                if ( $profile_id === null ) {
                    foreach ( (array) $all_profiles as $pid => $pdata ) {
                        if ( ! empty($pdata['short']) && stripos($orig_source, $pdata['short']) !== false ) {
                            $profile_id = $pid;
                            break;
                        }
                    }
                }
            }
        }
        if ( $profile_id === null ) {
            // Fallback ao comportamento antigo (detectar do header)
            $profile_id = function_exists('rmbz_detect_profile_from_header')
                ? rmbz_detect_profile_from_header($tmp_lower)
                : 'auto';
        }
    } else {
        $profile_id = sanitize_key( $_POST['profile_id'] ?? 'auto' );
    }
    $profile    = function_exists('rmbz_get_profile') ? rmbz_get_profile($profile_id) : null;

    if ( $is_reentry ) {
        // Reusar o ficheiro existente em vez de fazer upload
        $temp_filename = $existing_temp_name;
        $target_file   = $existing_file;
        $file = [ 'name' => basename($existing_file), 'size' => @filesize($existing_file) ];
    } else {
        $file = $_FILES['royalties_csv'];
        if ( $file['error'] !== UPLOAD_ERR_OK ) wp_die('Erro no upload: código ' . $file['error']);

        $upload_dir = wp_upload_dir();
        $target_dir = $upload_dir['basedir'] . '/rmbz_temp_imports/';
        if ( ! file_exists($target_dir) ) wp_mkdir_p($target_dir);

        $temp_filename = 'analysis_' . time() . '_' . wp_generate_password(8, false) . '.csv';
        $target_file   = $target_dir . $temp_filename;

        if ( ! move_uploaded_file($file['tmp_name'], $target_file) ) wp_die('Erro ao salvar ficheiro temporário.');
    }

    // [FEAT 1.6.11] VALIDAÇÃO PROACTIVA DO CSV
    // Antes de processar, fazer scan rápido para detectar problemas comuns:
    // encoding errado, separador inconsistente, colunas desalinhadas, etc.
    // Se houver erro crítico, mostra painel vermelho e bloqueia.
    // Se só houver warnings, deixa continuar e mostra-os na preview.
    $csv_validation = null;
    if ( function_exists('rmbz_validate_csv_file') ) {
        $csv_validation = rmbz_validate_csv_file( $target_file );
        if ( ! $csv_validation['ok'] ) {
            // Erro crítico — bloquear e mostrar painel
            echo '<div class="wrap" style="max-width:900px; margin-top:20px;">';
            echo '<h1 style="margin-bottom:14px;">⚠ Importação bloqueada — problemas no CSV</h1>';
            rmbz_render_csv_validation_panel( $csv_validation );
            echo '<p style="margin-top:14px;"><a href="' . esc_url( admin_url('admin.php?page=rmbz-admin-distribution&tab=import') ) . '" class="button button-primary">← Voltar ao upload</a></p>';
            echo '</div>';
            if ( ! $is_reentry ) @unlink( $target_file ); // só apaga se foi upload novo (não re-import)
            return;
        }
    }

    $file_hash = md5_file( $target_file );
    $already_imported = false;
    $log_table = $wpdb->prefix . 'rmbz_distro_import_logs';
    if ( $wpdb->get_var("SHOW TABLES LIKE '$log_table'") === $log_table ) {
        $already_imported = (bool) $wpdb->get_var( $wpdb->prepare(
            "SELECT id FROM $log_table WHERE file_hash = %s LIMIT 1", $file_hash
        ) );
    }

    $handle = fopen( $target_file, 'r' );
    if ( ! $handle ) wp_die('Erro ao abrir o ficheiro.');
    $header = fgetcsv($handle);
    if ( ! $header ) { fclose($handle); wp_die('CSV vazio ou inválido.'); }
    if ( isset($header[0]) ) $header[0] = preg_replace('/^\xEF\xBB\xBF/', '', $header[0]);
    $header_lower = array_map('strtolower', array_map('trim', $header));

    // Validar perfil contra CSV e detectar desalinhamentos
    $profile_match = null;
    $profile_suggested = null;
    if ( $profile && function_exists('rmbz_validate_profile_match') ) {
        $profile_match = rmbz_validate_profile_match($profile_id, $header_lower);
        $profile_suggested = function_exists('rmbz_detect_profile_from_header')
            ? rmbz_detect_profile_from_header($header_lower) : 'auto';

        if ( ! $profile_match['valid'] ) {
            fclose($handle);
            @unlink($target_file);
            $profiles_all = rmbz_get_import_profiles();
            $suggestion = $profile_suggested && isset($profiles_all[$profile_suggested]) ? $profiles_all[$profile_suggested] : null;
            $found_cols = implode(', ', array_map('esc_html', $header_lower));

            wp_die(
                '<div class="notice notice-error" style="padding:20px; max-width:900px; margin:20px auto;">' .
                '<h2 style="margin-top:0; color:var(--rmbz-danger, #cc0000);">⚠ CSV não compatível com o perfil "' . esc_html($profile['name']) . '"</h2>' .
                '<p>O perfil seleccionado espera estas colunas obrigatórias, mas algumas estão em falta:</p>' .
                '<ul>' .
                implode('', array_map(function($m){ return '<li><code style="color:var(--rmbz-danger, #cc0000);">✗ ' . esc_html($m) . '</code></li>'; }, $profile_match['missing'])) .
                '</ul>' .
                ( $suggestion && $suggestion['id'] !== $profile_id
                    ? '<div style="background:#eef7ff; padding:14px; border-left:4px solid #3498db; border-radius:4px; margin:16px 0;">' .
                      '<strong>💡 Sugestão:</strong> o seu CSV parece ser do perfil <strong>' . esc_html($suggestion['name']) . '</strong>. ' .
                      'Volte e seleccione esse perfil em vez de "' . esc_html($profile['name']) . '".' .
                      '</div>'
                    : '' ) .
                '<p><strong>Colunas do seu CSV:</strong></p>' .
                '<p style="background:#f0f0f0; padding:12px; border-radius:4px; font-family:monospace; font-size:12px;">' . $found_cols . '</p>' .
                '<p><a href="?page=rmbz-admin-distribution&tab=import" class="button button-primary">← Voltar e escolher outro perfil</a></p>' .
                '</div>'
            );
        }
    }

    // [DS 1.5.115] Para additional import, descobrir que ISRCs já foram
    // importados no log original. Será usado adiante para marcar visualmente
    // as faixas e desmarcá-las por defeito.
    //
    // [FIX 1.6.10] Normalizar ISRCs (remover hífens e espaços) — alguns
    // distribuidores (ex: Amadea Music) guardam ISRCs com hífens (BG-A47-25-24672)
    // mas no CSV vêm compactos (BGA472524672). Para comparar sem falsos
    // negativos, removemos tudo o que não é alfanumérico em ambos os lados.
    $already_imported_isrcs = [];
    $additional_log_id = 0;
    if ( $is_reentry && isset($_GET['from_additional']) ) {
        $additional_log_id = (int) $_GET['from_additional'];
        if ( $additional_log_id > 0 && function_exists('rmbz_get_already_imported_keys') ) {
            $keys = rmbz_get_already_imported_keys( $additional_log_id );
            foreach ( $keys as $key => $_v ) {
                $parts = explode('|', $key);
                if ( ! empty($parts[0]) ) {
                    // Normalizar: maiúsculas + remover não-alfanuméricos
                    $isrc_norm = strtoupper( preg_replace('/[^A-Za-z0-9]/', '', $parts[0]) );
                    if ( $isrc_norm !== '' ) {
                        $already_imported_isrcs[ $isrc_norm ] = true;
                    }
                }
            }
        }
    }

    // Desvio especial para Data Reports do TuneCore (sem ISRC)
    if ( $profile && $profile['type'] === 'aggregate_monthly' ) {
        fclose($handle);
        rmbz_render_aggregate_preview( $target_file, $temp_filename, $header, $header_lower, $profile, $already_imported, $file_hash, $file );
        return;
    }

    // Resolver índices de colunas usando o perfil seleccionado (com fallbacks genéricos)
    $cols = function_exists('rmbz_resolve_column_indices')
        ? rmbz_resolve_column_indices($header_lower, $profile)
        : [];
    $idx_isrc       = $cols['isrc']       ?? false;
    $idx_amount     = $cols['amount']     ?? false;
    $idx_store      = $cols['store']      ?? false;
    $idx_country    = $cols['country']    ?? false;
    $idx_streams    = $cols['streams']    ?? false;
    $idx_track_name = $cols['track_name'] ?? false;
    $idx_artist     = $cols['artist']     ?? false;
    $idx_currency   = $cols['currency']   ?? false;
    $idx_start      = $cols['date']       ?? false;
    // Adicionado para detector multi-camada
    $idx_upc        = $cols['upc']        ?? false;
    $idx_album      = $cols['album']      ?? false;

    if ( $idx_isrc === false || $idx_amount === false ) {
        fclose($handle);
        @unlink($target_file);
        $found_cols = implode(', ', array_map('esc_html', $header_lower));
        wp_die(
            '<div class="notice notice-error" style="padding:20px; max-width:800px; margin:20px auto;">' .
            '<h2 style="margin-top:0; color:var(--rmbz-danger, #cc0000);">Colunas obrigatórias não encontradas</h2>' .
            '<p><strong>Precisamos de:</strong></p>' .
            '<ul>' .
            '<li><code>ISRC</code> — ' . ( $idx_isrc === false ? '<span style="color:var(--rmbz-danger, #cc0000);">✗ não encontrada</span>' : '<span style="color:var(--rmbz-success-strong, #166534);">✓ encontrada</span>' ) . '</li>' .
            '<li>Valor (<code>Profit</code>, <code>Total Earned</code>, <code>Royalties</code>, <code>Amount</code>, <code>Net Revenue</code>, <code>Payable</code>, <code>Earnings</code>) — ' . ( $idx_amount === false ? '<span style="color:var(--rmbz-danger, #cc0000);">✗ não encontrada</span>' : '<span style="color:var(--rmbz-success-strong, #166534);">✓ encontrada</span>' ) . '</li>' .
            '</ul>' .
            '<p><strong>Colunas do seu CSV:</strong></p>' .
            '<p style="background:#f0f0f0; padding:12px; border-radius:4px; font-family:monospace; font-size:12px;">' . $found_cols . '</p>' .
            '<p><a href="?page=rmbz-admin-distribution&tab=import" class="button button-primary">← Voltar</a></p>' .
            '</div>'
        );
    }

    $total_money = 0.0;
    $total_streams = 0;
    $rows_count = 0;
    $by_store = [];
    $by_country = [];
    $by_track = [];
    // [DS 1.5.94] Agrupamentos extra para mais detalhe no preview:
    //   $by_artist  → agrupa receita+músicas por nome de artista (do CSV).
    //                 Ajuda admin a ver "este import vai pagar X ao artista Y".
    //   $by_service → detecta serviços multi-fonte na coluna "store"
    //                 (YouTube tem normal + Content ID, Meta tem FB+IG, etc).
    //                 Cada fonte aparece em separado para o admin saber a
    //                 origem real do dinheiro.
    $by_artist = [];
    $by_service = [];
    $unique_isrcs = [];
    $detected_currency = 'USD';
    $date_min = null;
    $date_max = null;
    $preview_rows = [];

    while ( ($row = fgetcsv($handle)) !== FALSE ) {
        $isrc = trim( $row[$idx_isrc] ?? '' );
        $val_raw = (string) ($row[$idx_amount] ?? '');
        $val = (float) str_replace([',','$','€','£'], ['.','','',''], $val_raw);
        if ( empty($isrc) || $val <= 0 ) continue;

        $total_money += $val;
        $isrc_u = strtoupper( preg_replace('/[^A-Z0-9]/i', '', $isrc) );
        $unique_isrcs[ $isrc_u ] = true;
        $rows_count++;

        if ( $idx_store !== false && ! empty($row[$idx_store]) ) {
            $s = trim($row[$idx_store]);
            if ( ! isset($by_store[$s]) ) $by_store[$s] = ['revenue' => 0, 'streams' => 0];
            $by_store[$s]['revenue'] += $val;

            // [DS 1.5.94] Classificar fonte de monetização (Content ID, FB/IG, etc)
            $service_key = rmbz_classify_service_source( $s );
            if ( ! isset($by_service[$service_key]) ) {
                $by_service[$service_key] = ['revenue' => 0, 'streams' => 0, 'tracks' => [], 'is_special' => rmbz_is_special_service($service_key)];
            }
            $by_service[$service_key]['revenue'] += $val;
            $by_service[$service_key]['tracks'][$isrc_u] = true;
        }
        if ( $idx_country !== false && ! empty($row[$idx_country]) ) {
            $cc = strtoupper(trim($row[$idx_country]));
            if ( ! isset($by_country[$cc]) ) $by_country[$cc] = 0;
            $by_country[$cc] += $val;
        }
        if ( $idx_streams !== false && is_numeric($row[$idx_streams] ?? '') ) {
            $q = (int) $row[$idx_streams];
            $total_streams += $q;
            if ( isset($by_store[$s ?? '']) ) $by_store[$s]['streams'] += $q;
            if ( isset($service_key) && isset($by_service[$service_key]) ) {
                $by_service[$service_key]['streams'] += $q;
            }
        }
        if ( ! isset($by_track[$isrc_u]) ) {
            $by_track[$isrc_u] = [
                'title'   => $idx_track_name !== false ? ($row[$idx_track_name] ?? '') : '',
                'artist'  => $idx_artist !== false ? ($row[$idx_artist] ?? '') : '',
                'isrc'    => $isrc,
                'upc'     => $idx_upc !== false ? trim($row[$idx_upc] ?? '') : '',
                'album'   => $idx_album !== false ? trim($row[$idx_album] ?? '') : '',
                'revenue' => 0,
                'streams' => 0,
            ];
        }
        $by_track[$isrc_u]['revenue'] += $val;
        if ( $idx_streams !== false ) $by_track[$isrc_u]['streams'] += (int) ($row[$idx_streams] ?? 0);

        // [DS 1.5.94] Agregar por nome do artista (do CSV).
        // Usa o nome bruto como veio. Faixas sem artista vão para "(Sem artista)".
        if ( $idx_artist !== false && ! empty(trim($row[$idx_artist] ?? '')) ) {
            $artist_name = trim( $row[$idx_artist] );
            $artist_key = mb_strtolower( $artist_name ); // case-insensitive
            if ( ! isset($by_artist[$artist_key]) ) {
                $by_artist[$artist_key] = [
                    'display_name' => $artist_name,
                    'revenue'      => 0,
                    'streams'      => 0,
                    'tracks'       => [], // chave = isrc_u → ['title' => ..., 'revenue' => ...]
                ];
            }
            $by_artist[$artist_key]['revenue'] += $val;
            if ( $idx_streams !== false ) $by_artist[$artist_key]['streams'] += (int) ($row[$idx_streams] ?? 0);
            if ( ! isset($by_artist[$artist_key]['tracks'][$isrc_u]) ) {
                $by_artist[$artist_key]['tracks'][$isrc_u] = [
                    'title'   => $idx_track_name !== false ? ($row[$idx_track_name] ?? '') : '',
                    'isrc'    => $isrc,
                    // [1.5.187] Incluir UPC para mostrar na tabela de drilldown.
                    // Útil para o admin verificar releases sem ISRC mas com UPC.
                    'upc'     => $idx_upc !== false ? trim($row[$idx_upc] ?? '') : '',
                    'revenue' => 0,
                ];
            }
            $by_artist[$artist_key]['tracks'][$isrc_u]['revenue'] += $val;
        }

        if ( $idx_currency !== false && ! empty($row[$idx_currency]) && $detected_currency === 'USD' ) {
            $cur = strtoupper(trim($row[$idx_currency]));
            if ( in_array($cur, ['USD','EUR','BRL','GBP','ZAR','MZN','AOA','CHF','JPY','CAD','AUD'], true) ) {
                $detected_currency = $cur;
            }
        }

        if ( $idx_start !== false && ! empty($row[$idx_start]) ) {
            $t = strtotime($row[$idx_start]);
            if ( $t ) {
                if ( $date_min === null || $t < $date_min ) $date_min = $t;
                if ( $date_max === null || $t > $date_max ) $date_max = $t;
            }
        }

        if ( $rows_count <= 5 ) $preview_rows[] = $row;
    }
    fclose($handle);

    $unique_isrcs_list = array_keys($unique_isrcs);
    $total_tracks_csv = count($unique_isrcs_list);
    $linked_count = 0;
    $linked_isrcs = [];

    // ──────────────────────────────────────────────────────────────────────
    // DETECÇÃO MULTI-CAMADA — ANTES: lookup só por ISRC, marcava tudo do
    // TuneCore como "Nova" porque o "Optional ISRC" deles é fake (TC Song ID).
    // AGORA: usa o detector que tenta ISRC → UPC+Título → Fuzzy → UPC só.
    //
    // Corre em $by_track (já agregado por ISRC) e categoriza cada faixa
    // pelo método de match. Resultado vai para $track_match_results para
    // a UI mostrar badge correcto (Vinculada / UPC+Título / Fuzzy / UPC só
    // / Nova).
    // ──────────────────────────────────────────────────────────────────────
    $track_match_results = []; // chave = $isrc_u → method/confidence
    $match_counts = [
        'isrc' => 0, 'upc_title' => 0, 'fuzzy_artist_title' => 0,
        'upc_only' => 0, 'none' => 0,
        'alias_learned' => 0, // [FEAT 1.6.6] novos: matches via alias aprendido
    ];
    // [FEAT 1.6.6] Detalhes dos aliases aprendidos para mostrar no aviso
    $learned_alias_hits = []; // [ ['isrc_csv', 'title', 'artist_csv', 'revenue', 'artist_name_db', 'alias_type'] ]

    if ( $total_tracks_csv > 0 && function_exists('rmbz_match_track') ) {
        foreach ( $by_track as $isrc_u => $t ) {
            // [DS 1.5.90] Override manual sobrepõe match normal
            // [DS 1.5.96] Verifica também UPC aliases
            $override = function_exists('rmbz_lookup_isrc_override')
                ? rmbz_lookup_isrc_override( $t['isrc'] ?? '' )
                : null;
            $alias_type_hit = $override ? 'isrc' : null;
            if ( ! $override && ! empty($t['upc']) && function_exists('rmbz_lookup_upc_alias') ) {
                $override = rmbz_lookup_upc_alias( $t['upc'] );
                if ( $override ) $alias_type_hit = 'upc';
            }
            if ( $override ) {
                $track_match_results[ $isrc_u ] = [
                    'method'          => 'alias_learned',
                    'confidence'      => 100,
                    'artist_conflict' => false,
                    'matched'         => true,
                    'is_override'     => true,
                ];
                $match_counts['alias_learned'] = ($match_counts['alias_learned'] ?? 0) + 1;
                $linked_isrcs[ $isrc_u ] = true;
                $linked_count++;

                // [FEAT 1.6.6] Recolher detalhes do alias para o aviso visual
                // O $override deve ter track_id; vamos buscar o nome do artista
                // associado para mostrar ao admin "vai pagar a XXXX".
                $hit_track_id = is_object($override) ? ($override->track_id ?? 0) : ( $override['track_id'] ?? 0 );
                $artist_db = '';
                if ( $hit_track_id ) {
                    global $wpdb;
                    $artist_db = (string) $wpdb->get_var( $wpdb->prepare(
                        "SELECT COALESCE(w.user_nome, r.artist_telemovel)
                           FROM {$wpdb->prefix}rmbz_distro_tracks tk
                           JOIN {$wpdb->prefix}rmbz_distro_releases r ON tk.release_id = r.id
                           LEFT JOIN {$wpdb->prefix}rmbz_wallets w ON r.artist_telemovel = w.user_telemovel
                          WHERE tk.id = %d",
                        (int) $hit_track_id
                    ) );
                }
                $learned_alias_hits[] = [
                    'isrc_csv'    => $t['isrc'] ?? '',
                    'upc_csv'     => $t['upc'] ?? '',
                    'title'       => $t['title'] ?? '',
                    'artist_csv'  => $t['artist'] ?? '',
                    'revenue'     => (float) ( $by_track[ $isrc_u ]['revenue'] ?? 0 ),
                    'streams'     => (int)   ( $by_track[ $isrc_u ]['streams'] ?? 0 ),
                    'artist_db'   => $artist_db ?: '—',
                    'alias_type'  => $alias_type_hit,
                ];
                continue;
            }

            $result = rmbz_match_track([
                'isrc'        => $t['isrc'] ?? '',
                'upc'         => $t['upc'] ?? '',
                'track_title' => $t['title'] ?? '',
                'artist'      => $t['artist'] ?? '',
                'album'       => $t['album'] ?? '',
            ]);

            $track_match_results[ $isrc_u ] = [
                'method'          => $result['method'],
                'confidence'      => $result['confidence'],
                'artist_conflict' => ! empty($result['artist_conflict']),
                'matched'         => ! empty($result['track']),
            ];

            $match_counts[ $result['method'] ] = ( $match_counts[ $result['method'] ] ?? 0 ) + 1;

            // Marcar como "linked" só se foi ISRC (auto-aprovado).
            // Os outros métodos vão para fila de revisão depois do import.
            if ( $result['method'] === 'isrc' && ! empty($result['track']) ) {
                $linked_isrcs[ $isrc_u ] = true;
                $linked_count++;
            }
        }
    } else {
        // Fallback antigo: lookup só por ISRC se o detector não estiver carregado
        $chunks = array_chunk($unique_isrcs_list, 500);
        foreach ( $chunks as $chunk ) {
            $placeholders = implode(',', array_fill(0, count($chunk), '%s'));
            $rows = $wpdb->get_col( $wpdb->prepare(
                "SELECT UPPER(REPLACE(isrc_code, '-', '')) FROM {$wpdb->prefix}rmbz_distro_tracks
                 WHERE UPPER(REPLACE(isrc_code, '-', '')) IN ($placeholders)",
                $chunk
            ) );
            foreach ( $rows as $r ) { $linked_isrcs[ $r ] = true; $linked_count++; }
        }
    }
    $unlinked_count = $total_tracks_csv - $linked_count;
    $black_box_eur  = 0.0;
    foreach ( $by_track as $k => $t ) {
        if ( ! isset($linked_isrcs[$k]) ) $black_box_eur += $t['revenue'];
    }

    $rate = rmbz_default_exchange_rate( $detected_currency );
    $total_usd = $total_money * $rate;
    $black_box_usd = $black_box_eur * $rate;

    arsort($by_store);
    uasort($by_store, function($a,$b){ return $b['revenue'] <=> $a['revenue']; });
    arsort($by_country);
    uasort($by_track, function($a,$b){ return $b['revenue'] <=> $a['revenue']; });

    $cur_symbol = rmbz_currency_symbol($detected_currency);
    $period_label = '';
    if ( $date_min && $date_max ) {
        if ( date('Y-m', $date_min) === date('Y-m', $date_max) ) {
            $period_label = ucfirst( rmbz_month_name_pt( date('n', $date_min) ) ) . ' ' . date('Y', $date_min);
        } else {
            $period_label = date('d/m/Y', $date_min) . ' → ' . date('d/m/Y', $date_max);
        }
    }

    // [FEAT 1.6.7] Período em formato Y-m-01 (primeiro dia do mês) para comparar
    // com daily_stats.report_date. Só é definido se TODAS as linhas do CSV são
    // do mesmo mês — caso contrário não conseguimos comparar exactamente e o
    // detector de re-import faz uma comparação mais relaxada (qualquer data).
    $csv_period_first_day = null;
    if ( $date_min && $date_max && date('Y-m', $date_min) === date('Y-m', $date_max) ) {
        $csv_period_first_day = date('Y-m-01', $date_min);
    }

    // ────────────────────────────────────────────────────────────────────────
    // [1.5.178] DETECÇÃO DE ARTISTAS REGISTADOS COM POSSÍVEIS LANÇAMENTOS EM FALTA
    //
    // Compara nomes de artistas no CSV com artistas registados em wp_rmbz_wallets.
    // Faz 3 níveis de matching para o admin verificar manualmente:
    //   1. Exacto (case-insensitive)
    //   2. Normalizado (remove pontuação/acentos/espaços extra)
    //   3. Fuzzy (Levenshtein <= 2 chars de diferença)
    //
    // Para cada artista detectado, conta:
    //   - Quantas faixas no CSV
    //   - Quantas estão vinculadas no sistema (ISRC já em rmbz_distro_tracks)
    //   - Quantas faltam (potencial novo lançamento ou faixa não importada)
    // ────────────────────────────────────────────────────────────────────────
    $registered_artists_match = [];
    if ( ! empty( $by_artist ) ) {
        $t_wallets = $wpdb->prefix . 'rmbz_wallets';
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_wallets'") === $t_wallets ) {
            // Helper de normalização — remove pontuação, acentos, lowercase, espaços extra
            $normalize_name = function( $s ) {
                $s = (string) $s;
                $s = mb_strtolower( $s );
                // Remover acentos comuns (best-effort sem iconv)
                $accents_map = [
                    'á'=>'a','à'=>'a','ã'=>'a','â'=>'a','ä'=>'a',
                    'é'=>'e','è'=>'e','ê'=>'e','ë'=>'e',
                    'í'=>'i','ì'=>'i','î'=>'i','ï'=>'i',
                    'ó'=>'o','ò'=>'o','õ'=>'o','ô'=>'o','ö'=>'o',
                    'ú'=>'u','ù'=>'u','û'=>'u','ü'=>'u',
                    'ç'=>'c','ñ'=>'n',
                ];
                $s = strtr( $s, $accents_map );
                // Remover pontuação e caracteres não alphanum (manter espaços)
                $s = preg_replace('/[^a-z0-9\s]/', '', $s);
                // Normalizar espaços
                $s = preg_replace('/\s+/', ' ', $s);
                return trim( $s );
            };

            // [1.5.201] Helper para extrair APENAS o artista principal de um nome
            // que pode ter "featuring/feat./ft./with" inline.
            //
            // Exemplos:
            //   "Mr Ama Featuring Vovote"  → "Mr Ama"
            //   "Mr. Ama feat. DJ X"        → "Mr. Ama"
            //   "Mr Ama ft Vovote"          → "Mr Ama"
            //   "Mr Ama & Vovote"           → "Mr Ama"
            //   "Mr Ama with Vovote"        → "Mr Ama"
            //   "Mr. Ama"                   → "Mr. Ama" (sem mudança)
            //
            // O CSV de distribuidores frequentemente tem este formato em vez de
            // separar artista principal e feat em colunas distintas. Sem este
            // strip, "Mr Ama Featuring Vovote" não bate com "Mr. Ama" registado.
            $strip_features = function( $s ) {
                $s = (string) $s;
                // Marcadores que separam artista principal do(s) featured.
                // \b garante boundary de palavra (não corta "feature" no meio).
                // /i = case-insensitive. Apanha tudo desde o marcador até ao fim.
                $patterns = [
                    '/\s+\bfeaturing\b.*$/i',
                    '/\s+\bfeat\.?\b.*$/i',
                    '/\s+\bft\.?\b.*$/i',
                    '/\s+\bwith\b.*$/i',
                    '/\s+&\s+.*$/i',         // "Artist & Other"
                    '/\s+x\s+.*$/i',          // "Artist x Other" (comum em rap)
                    '/\s+vs\.?\s+.*$/i',      // "Artist vs Other"
                ];
                foreach ( $patterns as $p ) {
                    $s = preg_replace( $p, '', $s );
                }
                return trim( $s );
            };

            // Buscar todos os artistas registados (limit defensivo de 5000)
            $registered = $wpdb->get_results(
                "SELECT user_telemovel, user_nome FROM $t_wallets
                 WHERE user_nome IS NOT NULL AND user_nome != ''
                 LIMIT 5000"
            );

            // Construir índice: nome normalizado → [{ telemovel, display_name }]
            // Pode haver homónimos — guardar todos.
            $reg_index_normalized = [];
            $reg_index_exact      = [];
            // [1.5.201] Índice extra por main_artist (sem feat./featuring)
            $reg_index_main_artist = [];
            foreach ( (array) $registered as $reg ) {
                $exact_key = mb_strtolower( $reg->user_nome );
                $norm_key  = $normalize_name( $reg->user_nome );
                if ( $exact_key === '' ) continue;
                $reg_index_exact[ $exact_key ][] = [
                    'telemovel'    => $reg->user_telemovel,
                    'display_name' => $reg->user_nome,
                ];
                if ( $norm_key !== '' ) {
                    $reg_index_normalized[ $norm_key ][] = [
                        'telemovel'    => $reg->user_telemovel,
                        'display_name' => $reg->user_nome,
                    ];
                }
                // Índice por main_artist — útil quando registado também tem feat. inline
                $main_only = $strip_features( $reg->user_nome );
                $main_norm = $normalize_name( $main_only );
                if ( $main_norm !== '' && $main_norm !== $norm_key ) {
                    $reg_index_main_artist[ $main_norm ][] = [
                        'telemovel'    => $reg->user_telemovel,
                        'display_name' => $reg->user_nome,
                    ];
                }
            }

            // Para cada artista do CSV, fazer match
            foreach ( $by_artist as $csv_key => $csv_data ) {
                $csv_name      = $csv_data['display_name'];
                $csv_norm      = $normalize_name( $csv_name );
                // [1.5.201] Versão sem featuring inline para fase de match adicional
                $csv_main_only = $strip_features( $csv_name );
                $csv_main_norm = $normalize_name( $csv_main_only );
                $matches_found = []; // lista de matches com nível de confiança

                // 1. MATCH EXACTO (case-insensitive)
                if ( isset( $reg_index_exact[ $csv_key ] ) ) {
                    foreach ( $reg_index_exact[ $csv_key ] as $reg ) {
                        $matches_found[] = [
                            'level'        => 'exact',
                            'confidence'   => 100,
                            'telemovel'    => $reg['telemovel'],
                            'display_name' => $reg['display_name'],
                        ];
                    }
                }

                // 2. MATCH NORMALIZADO (só se não houve exacto)
                if ( empty( $matches_found ) && $csv_norm !== '' && isset( $reg_index_normalized[ $csv_norm ] ) ) {
                    foreach ( $reg_index_normalized[ $csv_norm ] as $reg ) {
                        $matches_found[] = [
                            'level'        => 'normalized',
                            'confidence'   => 90,
                            'telemovel'    => $reg['telemovel'],
                            'display_name' => $reg['display_name'],
                        ];
                    }
                }

                // [1.5.201] 2.5 MATCH POR ARTISTA PRINCIPAL — útil quando CSV tem
                // "Mr Ama Featuring Vovote" mas registado é "Mr. Ama".
                //
                // Tira "feat./featuring/ft./with/&/x/vs" inline antes de comparar.
                // Confiança 85 (entre normalized=90 e fuzzy=75).
                if ( empty( $matches_found )
                     && $csv_main_norm !== ''
                     && $csv_main_norm !== $csv_norm  // só vale a pena se strip mudou alguma coisa
                ) {
                    // Tentar contra reg_index_normalized (registado sem feats)
                    if ( isset( $reg_index_normalized[ $csv_main_norm ] ) ) {
                        foreach ( $reg_index_normalized[ $csv_main_norm ] as $reg ) {
                            $matches_found[] = [
                                'level'        => 'main_artist',
                                'confidence'   => 85,
                                'telemovel'    => $reg['telemovel'],
                                'display_name' => $reg['display_name'],
                            ];
                        }
                    }
                    // E contra reg_index_main_artist (caso registado também tenha feat.)
                    if ( empty( $matches_found ) && isset( $reg_index_main_artist[ $csv_main_norm ] ) ) {
                        foreach ( $reg_index_main_artist[ $csv_main_norm ] as $reg ) {
                            $matches_found[] = [
                                'level'        => 'main_artist',
                                'confidence'   => 85,
                                'telemovel'    => $reg['telemovel'],
                                'display_name' => $reg['display_name'],
                            ];
                        }
                    }
                }

                // 3. MATCH FUZZY — só se nenhum dos anteriores e nome com >= 4 chars
                // (nomes curtos dão muitos falsos positivos)
                // [1.5.201] Tentar fuzzy não só no nome inteiro mas também na
                // versão sem features — apanha "Mr Ama Featuring Vovote" vs "Mr Ama"
                // mesmo com pequenos typos.
                //
                // [1.5.202] Skip fuzzy se há demasiados artistas registados —
                // O(N×M) com N=registados e M=por-CSV-artista pode esgotar
                // memória em sites grandes. Acima de 2000 artistas, confiamos
                // só nos matches exact/normalized/main_artist.
                if ( empty( $matches_found ) && mb_strlen( $csv_norm ) >= 4 && count($reg_index_normalized) <= 2000 ) {
                    $fuzzy_candidates = [ $csv_norm ];
                    if ( $csv_main_norm !== '' && $csv_main_norm !== $csv_norm && mb_strlen($csv_main_norm) >= 4 ) {
                        $fuzzy_candidates[] = $csv_main_norm;
                    }
                    foreach ( $reg_index_normalized as $reg_norm => $reg_list ) {
                        // skip nomes muito curtos no índice
                        if ( mb_strlen( $reg_norm ) < 4 ) continue;
                        $best_dist = PHP_INT_MAX;
                        foreach ( $fuzzy_candidates as $cand ) {
                            // Se a diferença de tamanho é > 3, levenshtein vai retornar > 2 — skip rápido
                            if ( abs( mb_strlen( $reg_norm ) - mb_strlen( $cand ) ) > 3 ) continue;
                            // levenshtein PHP nativa é fast em strings curtas
                            $dist = levenshtein( $cand, $reg_norm );
                            if ( $dist < $best_dist ) $best_dist = $dist;
                        }
                        if ( $best_dist > 0 && $best_dist <= 2 ) {
                            // Calcular confiança baseada na distância (menor = mais confiança)
                            $conf = $best_dist === 1 ? 75 : 60;
                            foreach ( $reg_list as $reg ) {
                                $matches_found[] = [
                                    'level'        => 'fuzzy',
                                    'confidence'   => $conf,
                                    'distance'     => $best_dist,
                                    'telemovel'    => $reg['telemovel'],
                                    'display_name' => $reg['display_name'],
                                ];
                            }
                        }
                    }
                }

                if ( ! empty( $matches_found ) ) {
                    // [1.5.202] OPTIMIZAÇÃO MEMÓRIA — antes fazíamos 2 queries
                    // SQL por cada match (47 artistas × ~2 matches × 2 queries
                    // = ~190 queries com JOIN pesados). Em sites grandes isto
                    // esgotava memória PHP (Fatal error: Allowed memory size).
                    //
                    // Agora pré-fetchamos os counts UMA VEZ por unique telemovel
                    // antes do foreach interno, e usamos cache.
                    foreach ( $matches_found as &$m ) {
                        // Contar quantos ISRCs do CSV deste artista estão registados
                        // como tracks deste artista_telemovel.
                        $csv_isrcs = array_keys( $csv_data['tracks'] );
                        $linked_to_artist = 0;
                        $registered_track_count = 0;
                        $artist_phone = $m['telemovel'];

                        // [FEAT 1.6.7 + 1.6.8] Re-import detection.
                        // Dois cenários:
                        //   A) Re-import pelo botão "Re-importar do mesmo CSV" → já existe
                        //      o array $already_imported_isrcs (vem do log original).
                        //      É a verdade direta — preferimos isto.
                        //   B) Upload novo do mesmo CSV (ou outro CSV com sobreposição) →
                        //      $already_imported_isrcs vem vazio; caímos na query a
                        //      daily_stats por (track_id, periodo).
                        $already_imported_count = 0;
                        $already_imported_revenue = 0.0;

                        if ( ! empty( $csv_isrcs ) ) {
                            $isrc_placeholders = implode(',', array_fill(0, count($csv_isrcs), '%s'));
                            $sql_params = array_merge( [ $artist_phone ], $csv_isrcs );
                            $linked_to_artist = (int) $wpdb->get_var( $wpdb->prepare(
                                "SELECT COUNT(DISTINCT t.id)
                                 FROM {$wpdb->prefix}rmbz_distro_tracks t
                                 INNER JOIN {$wpdb->prefix}rmbz_distro_releases r ON t.release_id = r.id
                                 WHERE r.artist_telemovel = %s
                                   AND UPPER(t.isrc_code) IN ($isrc_placeholders)",
                                $sql_params
                            ) );

                            // CENÁRIO A — already_imported_isrcs disponível
                            if ( ! empty( $already_imported_isrcs ) && is_array( $already_imported_isrcs ) ) {
                                foreach ( $csv_isrcs as $cisrc ) {
                                    // [FIX 1.6.10] Normalizar ISRC do CSV: maiúsculas + sem hífens/espaços
                                    // O lado already_imported_isrcs já foi normalizado quando foi carregado.
                                    $cisrc_norm = strtoupper( preg_replace('/[^A-Za-z0-9]/', '', $cisrc) );
                                    if ( $cisrc_norm !== '' && isset( $already_imported_isrcs[ $cisrc_norm ] ) ) {
                                        $already_imported_count++;
                                        // Receita: somar do $by_track (o $by_track usa a chave original
                                        // do CSV, não a normalizada — por isso usamos $cisrc).
                                        $cisrc_u = strtoupper( $cisrc );
                                        if ( isset( $by_track[ $cisrc_u ]['revenue'] ) ) {
                                            $already_imported_revenue += (float) $by_track[ $cisrc_u ]['revenue'];
                                        } elseif ( isset( $by_track[ $cisrc ]['revenue'] ) ) {
                                            $already_imported_revenue += (float) $by_track[ $cisrc ]['revenue'];
                                        }
                                    }
                                }
                            } else {
                                // CENÁRIO B — fallback à query daily_stats
                                $t_daily = $wpdb->prefix . 'rmbz_distro_daily_stats';
                                $has_daily = $wpdb->get_var("SHOW TABLES LIKE '$t_daily'") === $t_daily;
                                if ( $has_daily ) {
                                    $period_clause = '';
                                    if ( isset($csv_period_first_day) && $csv_period_first_day ) {
                                        $period_clause = $wpdb->prepare(
                                            " AND ds.report_date = %s",
                                            $csv_period_first_day
                                        );
                                    }
                                    $already_q = $wpdb->prepare(
                                        "SELECT COUNT(DISTINCT t.id) AS c,
                                                COALESCE(SUM(ds.sales), 0) AS rev
                                         FROM {$wpdb->prefix}rmbz_distro_tracks t
                                         INNER JOIN {$wpdb->prefix}rmbz_distro_releases r ON t.release_id = r.id
                                         INNER JOIN $t_daily ds ON ds.track_id = t.id
                                         WHERE r.artist_telemovel = %s
                                           AND UPPER(t.isrc_code) IN ($isrc_placeholders)
                                           AND ds.reverted_at IS NULL
                                         " . $period_clause,
                                        $sql_params
                                    );
                                    $row_already = $wpdb->get_row( $already_q );
                                    if ( $row_already ) {
                                        $already_imported_count = (int) $row_already->c;
                                        $already_imported_revenue = (float) $row_already->rev;
                                    }
                                }
                            }
                        }

                        // [1.5.202] Cached registered_track_count (1 query por
                        // telemovel único em vez de 1 por match). Evita queries
                        // duplicadas quando há vários matches para mesmo artista.
                        static $reg_count_cache = [];
                        if ( ! isset( $reg_count_cache[ $artist_phone ] ) ) {
                            $reg_count_cache[ $artist_phone ] = (int) $wpdb->get_var( $wpdb->prepare(
                                "SELECT COUNT(t.id)
                                 FROM {$wpdb->prefix}rmbz_distro_tracks t
                                 INNER JOIN {$wpdb->prefix}rmbz_distro_releases r ON t.release_id = r.id
                                 WHERE r.artist_telemovel = %s",
                                $artist_phone
                            ) );
                        }
                        $registered_track_count = $reg_count_cache[ $artist_phone ];

                        $m['csv_track_count']            = count( $csv_isrcs );
                        $m['linked_to_artist']           = $linked_to_artist;
                        // [FIX 1.6.17] "Em falta" = CSV − Vinculadas − Já importadas.
                        // Antes subtraíamos só $linked_to_artist (faixas com match
                        // automático no catálogo). Mas em re-imports, as faixas
                        // já processadas no log original também NÃO estão "em
                        // falta" — estão protegidas com cadeado 🔒 e nada vai ser
                        // duplicado. Logo, não devem entrar no contador.
                        $m['unlinked_count']             = max( 0,
                            count( $csv_isrcs ) - $linked_to_artist - $already_imported_count
                        );
                        $m['registered_track_count']     = $registered_track_count;
                        $m['csv_revenue']                = (float) $csv_data['revenue'];
                        // [FEAT 1.6.7] Re-import flags
                        $m['already_imported_count']     = $already_imported_count;
                        $m['already_imported_revenue']   = $already_imported_revenue;
                        // Severity: full = >70% das faixas já estão; partial = >0 e ≤70%; clean = 0
                        $linked_total = max(1, $linked_to_artist); // evitar div/0
                        $reimport_ratio = $already_imported_count / $linked_total;
                        if ( $already_imported_count > 0 && $reimport_ratio >= 0.7 ) {
                            $m['reimport_severity'] = 'full';
                        } elseif ( $already_imported_count > 0 ) {
                            $m['reimport_severity'] = 'partial';
                        } else {
                            $m['reimport_severity'] = 'clean';
                        }
                    }
                    unset( $m );

                    $registered_artists_match[ $csv_key ] = [
                        'csv_display_name' => $csv_name,
                        'csv_revenue'      => (float) $csv_data['revenue'],
                        'csv_track_count'  => count( $csv_data['tracks'] ),
                        'csv_streams'      => (int) ( $csv_data['streams'] ?? 0 ),
                        'matches'          => $matches_found,
                    ];
                }
            }
        }
    }

    // ────────────────────────────────────────────────────────────────────────
    // [FEAT 1.6.19] DETECTOR DE RECEITA ANÓMALA
    //
    // Para cada artista detectado no CSV (com match para artista registado),
    // comparar a receita deste import com a MÉDIA dos últimos 3 meses
    // (excluindo o mês actual, excluindo imports revertidos).
    //
    // Critérios:
    //   - "spike"  → receita ≥ 3× a média histórica
    //   - "drop"   → receita ≤ 0.2× a média histórica (1/5)
    //   - skip    → histórico tem <2 meses de dados OU média < $1 USD
    //               (estatisticamente irrelevante, gera falsos positivos)
    //
    // Útil para detectar: erros de match (artista A apanha dinheiro do B),
    // fraude (artista forçou inflação), ou imports parciais (queda
    // anómala porque metade do CSV foi perdida).
    // ────────────────────────────────────────────────────────────────────────
    $anomalies = []; // [ csv_key => ['type', 'current', 'avg', 'ratio', 'months_with_data'] ]
    if ( ! empty( $registered_artists_match ) ) {
        $t_ledger_anom = $wpdb->prefix . 'rmbz_distro_ledger';
        $t_logs_anom   = $wpdb->prefix . 'rmbz_distro_import_logs';

        // Determinar a janela: 3 meses ANTES do período actual deste CSV.
        // Se o CSV é multi-mês, usar o $date_min como referência.
        if ( isset($csv_period_first_day) && $csv_period_first_day ) {
            $period_anchor = $csv_period_first_day; // Y-m-01
        } else {
            $period_anchor = $date_min ? date('Y-m-01', $date_min) : date('Y-m-01');
        }
        // Janela: 3 meses anteriores (exclui o próprio período)
        $window_end = date('Y-m', strtotime( $period_anchor . ' -1 month' )); // mês anterior
        $window_start = date('Y-m', strtotime( $period_anchor . ' -3 months' ));

        $has_ledger = $wpdb->get_var("SHOW TABLES LIKE '$t_ledger_anom'") === $t_ledger_anom;
        if ( $has_ledger ) {
            // Recolher todos os telemoveis de artistas com match
            $tels_anom = [];
            foreach ( $registered_artists_match as $entry ) {
                foreach ( $entry['matches'] as $m ) {
                    if ( ! empty($m['telemovel']) ) $tels_anom[ $m['telemovel'] ] = true;
                }
            }
            if ( ! empty( $tels_anom ) ) {
                $tel_list = array_keys( $tels_anom );
                $placeholders = implode(',', array_fill(0, count($tel_list), '%s'));

                // Query: agrupa receita por artista e período no histórico
                // (excluindo revertidos e o próprio período actual).
                // Só conta linhas de imports aprovados (não pendentes nem rejeitados).
                $params = array_merge(
                    $tel_list,
                    [ $window_start . '-01', $window_end . '-31', $period_anchor ]
                );
                $hist_rows = $wpdb->get_results( $wpdb->prepare(
                    "SELECT l.artist_telemovel,
                            l.reporting_period,
                            SUM(l.amount) AS total
                       FROM $t_ledger_anom l
                  LEFT JOIN $t_logs_anom lg ON lg.id = l.import_log_id
                      WHERE l.artist_telemovel IN ($placeholders)
                        AND l.reverted_at IS NULL
                        AND l.reporting_period >= %s
                        AND l.reporting_period <= %s
                        AND l.reporting_period != %s
                        AND ( lg.id IS NULL OR lg.approval_status = 'approved' )
                        AND ( lg.id IS NULL OR lg.status IS NULL OR lg.status = 'active' )
                      GROUP BY l.artist_telemovel, l.reporting_period",
                    $params
                ) );

                // Agregar: telemovel => [ período => total ]
                $hist_by_tel = [];
                foreach ( $hist_rows as $r ) {
                    $hist_by_tel[ $r->artist_telemovel ][ $r->reporting_period ] = (float) $r->total;
                }

                // Para cada artista detectado no CSV, calcular média e anomalia
                foreach ( $registered_artists_match as $csv_key => $entry ) {
                    // Pegar o telemovel do primeiro match (artista único após
                    // dedup). Se houver vários matches, usamos o de maior confiança.
                    if ( empty( $entry['matches'] ) ) continue;
                    $best_match = $entry['matches'][0];
                    foreach ( $entry['matches'] as $m ) {
                        if ( ( $m['confidence'] ?? 0 ) > ( $best_match['confidence'] ?? 0 ) ) {
                            $best_match = $m;
                        }
                    }
                    $tel = $best_match['telemovel'] ?? '';
                    if ( ! $tel || ! isset( $hist_by_tel[ $tel ] ) ) continue;

                    $hist = $hist_by_tel[ $tel ];
                    $months_with_data = count( $hist );
                    if ( $months_with_data < 2 ) continue; // histórico insuficiente

                    $avg = array_sum( $hist ) / $months_with_data;
                    if ( $avg < 1.0 ) continue; // média estatisticamente irrelevante

                    $current = (float) $entry['csv_revenue'];
                    // Converter EUR/outros para USD para comparação consistente
                    if ( isset($exchange_rate) && $exchange_rate > 0 ) {
                        $current = $current * $exchange_rate;
                    }
                    $ratio = $avg > 0 ? ( $current / $avg ) : 0;

                    $type = null;
                    if ( $ratio >= 3.0 ) {
                        $type = 'spike';
                    } elseif ( $ratio <= 0.2 && $current >= 0.01 ) {
                        // Só "drop" se houver receita > 0 — quebra completa
                        // já é tratada noutro lado (faixas silenciosas).
                        $type = 'drop';
                    } elseif ( $ratio === 0.0 && $avg >= 5.0 ) {
                        // Drop total: $0 vs média ≥ $5 — alta confiança de problema
                        $type = 'drop_total';
                    }
                    if ( $type ) {
                        $anomalies[ $csv_key ] = [
                            'type'             => $type,
                            'current'          => $current,
                            'avg'              => $avg,
                            'ratio'            => $ratio,
                            'months_with_data' => $months_with_data,
                            'display_name'     => $entry['csv_display_name'],
                            'db_name'          => $best_match['display_name'] ?? '—',
                            'window_label'     => $window_start . ' → ' . $window_end,
                        ];
                    }
                }
            }
        }
    }

    ?>
    <div class="wrap rmbz-import-v2">

        <?php
        // [FEAT 1.6.11] Painel de validação do CSV no topo (só se houver warnings —
        // erros críticos já bloquearam antes de chegar aqui).
        if ( ! empty( $csv_validation ) && function_exists('rmbz_render_csv_validation_panel') ) {
            rmbz_render_csv_validation_panel( $csv_validation );
        }
        ?>

        <div class="rmbz-iv-head">
            <div>
                <div class="rmbz-iv-kicker">Distribuição Digital · Importar</div>
                <h1>Relatório de Pré-Importação</h1>
            </div>
            <div class="rmbz-iv-pills">
                <span class="rmbz-iv-pill neutral">📄 <?php echo esc_html( basename($file['name']) ); ?></span>
                <?php if ( $profile ): ?>
                    <span class="rmbz-iv-pill info" style="background: <?php echo esc_attr($profile['badge_color']); ?>; color:var(--rmbz-text-on-color, #fff); border-color: <?php echo esc_attr($profile['badge_color']); ?>;">
                        <?php echo esc_html($profile['badge_initial']); ?> <?php echo esc_html($profile['short']); ?>
                    </span>
                <?php endif; ?>
                <?php if ( $detected_currency !== 'USD' ): ?>
                    <span class="rmbz-iv-pill info">✓ <?php echo esc_html($detected_currency); ?> detectado</span>
                <?php endif; ?>
                <?php if ( $period_label ): ?>
                    <span class="rmbz-iv-pill neutral">📅 <?php echo esc_html($period_label); ?></span>
                <?php endif; ?>
                <?php if ( $already_imported ): ?>
                    <span class="rmbz-iv-pill warning">⚠ Ficheiro já importado antes</span>
                <?php endif; ?>
            </div>
        </div>

        <div class="rmbz-iv-kpis">
            <div class="rmbz-iv-kpi green">
                <div class="lbl">Receita Total</div>
                <div class="val"><?php echo esc_html($cur_symbol); ?><?php echo number_format($total_money, 2); ?></div>
                <?php if ( $detected_currency !== 'USD' ): ?>
                    <div class="sub">≈ $<?php echo number_format($total_usd, 2); ?> USD · taxa <?php echo number_format($rate, 4); ?></div>
                <?php else: ?>
                    <div class="sub">Valor bruto no ficheiro</div>
                <?php endif; ?>
            </div>

            <div class="rmbz-iv-kpi blue">
                <div class="lbl">Streams / Quantidade</div>
                <div class="val"><?php echo rmbz_fmt_compact($total_streams); ?></div>
                <div class="sub"><?php echo number_format($rows_count); ?> linhas · <?php echo $total_tracks_csv; ?> faixas únicas</div>
            </div>

            <div class="rmbz-iv-kpi purple">
                <div class="lbl">Alcance</div>
                <div class="val"><?php echo count($by_store); ?> · <?php echo count($by_country); ?></div>
                <div class="sub">Lojas · Países</div>
            </div>

            <?php if ( $unlinked_count > 0 ): ?>
                <div class="rmbz-iv-kpi red">
                    <div class="lbl">Black Box (sem dono)</div>
                    <div class="val"><?php echo $unlinked_count; ?></div>
                    <div class="sub">
                        <?php echo esc_html($cur_symbol); ?><?php echo number_format($black_box_eur, 2); ?> retidos
                        <?php if ( $detected_currency !== 'USD' ): ?>
                            · $<?php echo number_format($black_box_usd, 2); ?>
                        <?php endif; ?>
                    </div>
                </div>
            <?php else: ?>
                <div class="rmbz-iv-kpi green">
                    <div class="lbl">Vinculados</div>
                    <div class="val"><?php echo $linked_count; ?> / <?php echo $total_tracks_csv; ?></div>
                    <div class="sub">100% identificados ✓</div>
                </div>
            <?php endif; ?>
        </div>

        <?php
        // [FEAT 1.6.7] BANNER DE RE-IMPORT — alerta global se há artistas que
        // já tiveram TODAS as faixas importadas no mesmo período. Significa
        // que o admin está a re-importar e provavelmente vai DUPLICAR dinheiro
        // se confirmar o import.
        $reimport_full_artists = [];
        $reimport_full_revenue = 0.0;
        if ( ! empty( $registered_artists_match ) ) {
            foreach ( $registered_artists_match as $entry ) {
                foreach ( $entry['matches'] as $m ) {
                    if ( ( $m['reimport_severity'] ?? 'clean' ) === 'full' ) {
                        $reimport_full_artists[] = [
                            'csv_name'   => $entry['csv_display_name'],
                            'db_name'    => $m['display_name'] ?? '—',
                            'already'    => (int) ( $m['already_imported_count'] ?? 0 ),
                            'total_csv'  => (int) ( $m['csv_track_count'] ?? 0 ),
                            'revenue'    => (float) ( $m['already_imported_revenue'] ?? 0 ),
                        ];
                        $reimport_full_revenue += (float) ( $m['already_imported_revenue'] ?? 0 );
                        break; // Um match por artista CSV chega
                    }
                }
            }
        }
        if ( ! empty( $reimport_full_artists ) ):
            // [FEAT 1.6.8] Detectar se é re-import explícito (via botão "Re-importar do mesmo CSV")
            // — neste caso adapta-se a mensagem para ser ainda mais clara.
            $is_explicit_reimport = isset($_GET['from_additional']) && (int) ($_GET['from_additional'] ?? 0) > 0;
        ?>
        <div class="rmbz-iv-reimport-banner">
            <div class="rmbz-iv-rb-head">
                <div class="rmbz-iv-rb-icon">🚫</div>
                <div class="rmbz-iv-rb-text">
                    <div class="rmbz-iv-rb-title">
                        <?php if ( $is_explicit_reimport ): ?>
                            Re-importação do mesmo CSV — atenção a duplicação
                        <?php else: ?>
                            ATENÇÃO — Re-importação detectada
                        <?php endif; ?>
                        <span class="rmbz-iv-rb-badge"><?php echo count($reimport_full_artists); ?> artista<?php echo count($reimport_full_artists) === 1 ? '' : 's'; ?></span>
                    </div>
                    <div class="rmbz-iv-rb-sub">
                        <?php if ( $is_explicit_reimport ): ?>
                            Estás a reabrir o CSV da importação <strong>#<?php echo (int) $_GET['from_additional']; ?></strong>.
                            <strong><?php echo count($reimport_full_artists); ?> artista<?php echo count($reimport_full_artists) === 1 ? '' : 's'; ?></strong>
                            <?php echo count($reimport_full_artists) === 1 ? 'tem' : 'têm'; ?>
                            todas as faixas já processadas — marcadas com <strong>🔒 já importado</strong> na lista abaixo
                            e <strong>desmarcadas por defeito</strong> para evitar duplicação.
                        <?php else: ?>
                            <strong><?php echo count($reimport_full_artists); ?> artista<?php echo count($reimport_full_artists) === 1 ? '' : 's'; ?></strong>
                            <?php echo count($reimport_full_artists) === 1 ? 'já tem' : 'já têm'; ?>
                            todas as faixas importadas para o período
                            <?php if ( $period_label ): ?>
                                <strong><?php echo esc_html($period_label); ?></strong>
                            <?php else: ?>
                                deste CSV
                            <?php endif; ?>.
                            Continuar pode <strong style="color:#7f1d1d;">duplicar receita</strong>
                            no valor de aproximadamente
                            <strong><?php echo esc_html($cur_symbol); ?><?php echo number_format($reimport_full_revenue, 2); ?></strong>.
                        <?php endif; ?>
                    </div>
                </div>
            </div>
            <div class="rmbz-iv-rb-list">
                <strong style="font-size:11px; text-transform:uppercase; color:#7f1d1d; letter-spacing:0.04em;">
                    Artistas afectados:
                </strong>
                <ul>
                    <?php foreach ( $reimport_full_artists as $rfa ): ?>
                    <li>
                        <strong><?php echo esc_html($rfa['db_name']); ?></strong>
                        — <?php echo $rfa['already']; ?>/<?php echo $rfa['total_csv']; ?> faixas já importadas
                        (<?php echo esc_html($cur_symbol); ?><?php echo number_format($rfa['revenue'], 2); ?>)
                    </li>
                    <?php endforeach; ?>
                </ul>
            </div>
            <div class="rmbz-iv-rb-hint">
                💡 <strong>O que fazer:</strong> Se este é um CSV legítimo com correcções (não duplicação),
                podes prosseguir, mas vais ver linhas duplicadas no analítico. O mais comum é o admin ter
                enviado por engano o mesmo ficheiro que já foi importado — nesse caso, <strong>cancela</strong>
                e verifica em <em>Importações</em> a lista dos CSVs já processados.
            </div>
        </div>
        <style>
        .rmbz-iv-reimport-banner {
            background: linear-gradient(135deg, #fee2e2 0%, #fef2f2 100%);
            border: 1px solid #fca5a5;
            border-left: 4px solid #dc2626;
            border-radius: 10px;
            padding: 16px 20px;
            margin: 0 0 20px 0;
        }
        .rmbz-iv-rb-head {
            display: flex; align-items: flex-start; gap: 14px; margin-bottom: 12px;
        }
        .rmbz-iv-rb-icon { font-size: 30px; line-height: 1; flex-shrink: 0; }
        .rmbz-iv-rb-text { flex: 1; min-width: 0; }
        .rmbz-iv-rb-title {
            font-size: 16px; font-weight: 700; color: #7f1d1d;
            display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
        }
        .rmbz-iv-rb-badge {
            background: #dc2626; color: #fff;
            padding: 2px 9px; border-radius: 10px;
            font-size: 11px; font-weight: 700;
        }
        .rmbz-iv-rb-sub {
            font-size: 13px; color: #991b1b; margin-top: 4px; line-height: 1.55;
        }
        .rmbz-iv-rb-list {
            background: #fff; border-radius: 7px;
            padding: 10px 14px; margin-bottom: 10px;
        }
        .rmbz-iv-rb-list ul {
            margin: 6px 0 0 0; padding-left: 20px;
            font-size: 12.5px; color: #1a1a1a; line-height: 1.7;
        }
        .rmbz-iv-rb-list ul li { padding: 2px 0; }
        .rmbz-iv-rb-hint {
            background: #fef2f2; border-radius: 6px;
            padding: 9px 12px; font-size: 11.5px;
            color: #7f1d1d; line-height: 1.55;
        }
        </style>
        <?php endif; // reimport_full_artists ?>

        <?php
        // [FEAT 1.6.19] BANNER DE RECEITA ANÓMALA
        // Mostrar apenas se houver pelo menos 1 artista com desvio significativo
        // vs média histórica (≥3× ou ≤0.2×). Ordenar por gravidade.
        if ( ! empty( $anomalies ) ):
            // Ordenar: spike grandes primeiro, depois drops
            uasort( $anomalies, function ( $a, $b ) {
                // Quem foge mais da média (em ratio absoluto) primeiro
                $da = $a['type'] === 'spike' ? $a['ratio'] : 1 / max(0.01, $a['ratio']);
                $db = $b['type'] === 'spike' ? $b['ratio'] : 1 / max(0.01, $b['ratio']);
                return $db <=> $da;
            } );
            $anom_spike_count = 0;
            $anom_drop_count = 0;
            foreach ( $anomalies as $a ) {
                if ( $a['type'] === 'spike' ) $anom_spike_count++;
                else $anom_drop_count++;
            }
        ?>
        <div class="rmbz-iv-anomaly">
            <div class="rmbz-iv-anom-head">
                <div class="rmbz-iv-anom-icon">📊</div>
                <div class="rmbz-iv-anom-text">
                    <div class="rmbz-iv-anom-title">
                        Receita anómala detectada
                        <?php if ( $anom_spike_count > 0 ): ?>
                            <span class="rmbz-iv-anom-badge spike">⬆ <?php echo $anom_spike_count; ?> aumento<?php echo $anom_spike_count === 1 ? '' : 's'; ?></span>
                        <?php endif; ?>
                        <?php if ( $anom_drop_count > 0 ): ?>
                            <span class="rmbz-iv-anom-badge drop">⬇ <?php echo $anom_drop_count; ?> queda<?php echo $anom_drop_count === 1 ? '' : 's'; ?></span>
                        <?php endif; ?>
                    </div>
                    <div class="rmbz-iv-anom-sub">
                        <?php echo count($anomalies); ?> artista<?php echo count($anomalies) === 1 ? '' : 's'; ?>
                        <?php echo count($anomalies) === 1 ? 'tem' : 'têm'; ?>
                        variação significativa vs média dos últimos 3 meses.
                        <strong>Verifica antes de aprovar</strong> — pode ser erro de match, ISRC mal mapeado, ou import parcial.
                    </div>
                </div>
                <button type="button" class="rmbz-iv-anom-toggle" onclick="document.getElementById('rmbz-anom-detail').classList.toggle('is-open'); this.classList.toggle('is-open');">
                    Ver detalhe <span class="rmbz-iv-anom-chevron">▾</span>
                </button>
            </div>
            <div class="rmbz-iv-anom-detail" id="rmbz-anom-detail">
                <table class="rmbz-iv-anom-table">
                    <thead>
                        <tr>
                            <th>Artista</th>
                            <th class="rmbz-num">Média histórica</th>
                            <th class="rmbz-num">Neste import</th>
                            <th class="rmbz-num">Variação</th>
                            <th>Base</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php foreach ( $anomalies as $a ):
                            $is_spike = ( $a['type'] === 'spike' );
                            $is_drop  = in_array( $a['type'], ['drop', 'drop_total'], true );
                            // Variação % formatada
                            if ( $a['avg'] > 0 ) {
                                $change_pct = ( ( $a['current'] - $a['avg'] ) / $a['avg'] ) * 100;
                                $change_str = ( $change_pct >= 0 ? '+' : '' ) . number_format($change_pct, 0) . '%';
                            } else {
                                $change_str = 'n/d';
                            }
                        ?>
                        <tr class="<?php echo $is_spike ? 'rmbz-anom-spike' : 'rmbz-anom-drop'; ?>">
                            <td>
                                <?php if ( $is_spike ): ?>
                                    <span class="rmbz-anom-arrow up">⬆</span>
                                <?php else: ?>
                                    <span class="rmbz-anom-arrow down">⬇</span>
                                <?php endif; ?>
                                <strong><?php echo esc_html($a['db_name']); ?></strong>
                                <?php if ( $a['display_name'] !== $a['db_name'] ): ?>
                                    <span class="rmbz-anom-csv-name">(CSV: <?php echo esc_html($a['display_name']); ?>)</span>
                                <?php endif; ?>
                            </td>
                            <td class="rmbz-num">$<?php echo number_format($a['avg'], 2); ?></td>
                            <td class="rmbz-num"><strong>$<?php echo number_format($a['current'], 2); ?></strong></td>
                            <td class="rmbz-num">
                                <strong class="rmbz-anom-change-<?php echo $is_spike ? 'up' : 'down'; ?>">
                                    <?php echo $change_str; ?>
                                </strong>
                                <?php if ( $a['ratio'] >= 1 ): ?>
                                    <br><small><?php echo number_format($a['ratio'], 1); ?>× a média</small>
                                <?php else: ?>
                                    <br><small>1/<?php echo number_format(1/max(0.01,$a['ratio']), 1); ?> da média</small>
                                <?php endif; ?>
                            </td>
                            <td><small><?php echo (int) $a['months_with_data']; ?> mês(es) · <?php echo esc_html($a['window_label']); ?></small></td>
                        </tr>
                        <?php endforeach; ?>
                    </tbody>
                </table>

                <div class="rmbz-iv-anom-hint">
                    💡 <strong>Como interpretar:</strong>
                    <strong>Aumento &gt;3×</strong> pode indicar ISRC mal mapeado (apanhou dinheiro doutro artista) ou hit viral.
                    <strong>Queda &lt;1/5</strong> pode indicar import parcial, ficheiro incompleto, ou faixas dropadas das lojas.
                    Compara sempre antes de aprovar — para confirmar uma anomalia legítima, vê o cartão do artista mais abaixo.
                </div>
            </div>
        </div>
        <style>
        .rmbz-iv-anomaly {
            background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%);
            border: 1px solid #fcd34d;
            border-left: 4px solid #f59e0b;
            border-radius: 10px;
            padding: 16px 20px;
            margin: 0 0 20px 0;
        }
        .rmbz-iv-anom-head {
            display: flex; align-items: flex-start; gap: 14px;
        }
        .rmbz-iv-anom-icon { font-size: 28px; line-height: 1; flex-shrink: 0; }
        .rmbz-iv-anom-text { flex: 1; min-width: 0; }
        .rmbz-iv-anom-title {
            font-size: 15px; font-weight: 700; color: #92400e;
            display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
        }
        .rmbz-iv-anom-badge {
            padding: 2px 9px; border-radius: 10px;
            font-size: 11px; font-weight: 700; color: #fff;
        }
        .rmbz-iv-anom-badge.spike { background: #dc2626; }
        .rmbz-iv-anom-badge.drop  { background: #2563eb; }
        .rmbz-iv-anom-sub {
            font-size: 13px; color: #78350f; margin-top: 4px; line-height: 1.55;
        }
        .rmbz-iv-anom-toggle {
            background: #fff; border: 1px solid #fcd34d; color: #92400e;
            padding: 6px 12px; border-radius: 6px; cursor: pointer;
            font-size: 12px; font-weight: 600; flex-shrink: 0;
        }
        .rmbz-iv-anom-toggle:hover { background: #fef3c7; }
        .rmbz-iv-anom-chevron { display: inline-block; transition: transform 0.2s; margin-left: 3px; }
        .rmbz-iv-anom-toggle.is-open .rmbz-iv-anom-chevron { transform: rotate(180deg); }
        .rmbz-iv-anom-detail {
            max-height: 0; overflow: hidden; transition: max-height 0.3s ease;
        }
        .rmbz-iv-anom-detail.is-open {
            max-height: 2000px;
            margin-top: 14px;
            padding-top: 14px;
            border-top: 1px dashed #fcd34d;
        }
        .rmbz-iv-anom-table {
            width: 100%; border-collapse: collapse; font-size: 12px;
            background: #fff; border-radius: 7px; overflow: hidden;
        }
        .rmbz-iv-anom-table th {
            text-align: left; padding: 7px 10px;
            font-size: 10px; text-transform: uppercase;
            letter-spacing: 0.04em; color: #92400e; font-weight: 700;
            background: #fef3c7;
            border-bottom: 1px solid #fcd34d;
        }
        .rmbz-iv-anom-table .rmbz-num { text-align: right; font-variant-numeric: tabular-nums; }
        .rmbz-iv-anom-table td {
            padding: 7px 10px; border-bottom: 1px solid #f3f4f6;
        }
        .rmbz-iv-anom-table tr:last-child td { border-bottom: none; }
        .rmbz-anom-spike td { background: #fef2f2; }
        .rmbz-anom-drop td  { background: #eff6ff; }
        .rmbz-anom-arrow {
            display: inline-block;
            padding: 1px 7px; border-radius: 9px;
            font-size: 11px; font-weight: 700;
            margin-right: 5px;
        }
        .rmbz-anom-arrow.up   { background: #fee2e2; color: #991b1b; }
        .rmbz-anom-arrow.down { background: #dbeafe; color: #1e40af; }
        .rmbz-anom-csv-name { font-size: 10px; color: #6b7280; margin-left: 5px; }
        .rmbz-anom-change-up   { color: #991b1b; }
        .rmbz-anom-change-down { color: #1e40af; }
        .rmbz-iv-anom-hint {
            margin-top: 12px;
            background: #fef3c7; border-radius: 6px;
            padding: 9px 12px; font-size: 11.5px;
            color: #78350f; line-height: 1.55;
        }
        </style>
        <?php endif; // anomalies ?>

        <?php
        // [FEAT 1.6.6] AVISO DE APRENDIZAGEM AUTOMÁTICA
        // Mostrar APENAS se houver matches via alias aprendido. Lista quais
        // faixas vão ser atribuídas automaticamente porque uma aprovação
        // manual num import anterior memorizou a regra.
        $learned_count = (int) ( $match_counts['alias_learned'] ?? 0 );
        if ( $learned_count > 0 ):
            // Calcular receita total + agrupar por artista_db para sumário
            $learned_revenue = 0.0;
            $learned_by_artist = []; // artista_db => ['count' => N, 'revenue' => X]
            foreach ( $learned_alias_hits as $h ) {
                $learned_revenue += (float) $h['revenue'];
                $a = $h['artist_db'] ?: '—';
                if ( ! isset($learned_by_artist[$a]) ) $learned_by_artist[$a] = ['count' => 0, 'revenue' => 0.0];
                $learned_by_artist[$a]['count']++;
                $learned_by_artist[$a]['revenue'] += (float) $h['revenue'];
            }
            // Ordenar por receita desc
            uasort( $learned_by_artist, function ($a, $b) { return $b['revenue'] <=> $a['revenue']; } );
        ?>
        <div class="rmbz-iv-learned" id="rmbz-learned-block">
            <div class="rmbz-iv-learned-head">
                <div class="rmbz-iv-learned-icon">🧠</div>
                <div class="rmbz-iv-learned-text">
                    <div class="rmbz-iv-learned-title">
                        Aprendizagem automática activa
                        <span class="rmbz-iv-learned-badge"><?php echo $learned_count; ?> faixa<?php echo $learned_count === 1 ? '' : 's'; ?></span>
                    </div>
                    <div class="rmbz-iv-learned-sub">
                        <?php echo $learned_count; ?> faixa<?php echo $learned_count === 1 ? '' : 's'; ?> do CSV
                        vai ser atribuída automaticamente porque foi mapeada num import anterior
                        (total: <strong><?php echo esc_html($cur_symbol); ?><?php echo number_format($learned_revenue, 2); ?></strong>).
                        Não vão à fila de revisão.
                    </div>
                </div>
                <button type="button" class="rmbz-iv-learned-toggle" onclick="document.getElementById('rmbz-learned-detail').classList.toggle('is-open'); this.classList.toggle('is-open');">
                    Ver detalhe <span class="rmbz-iv-learned-chevron">▾</span>
                </button>
            </div>
            <div class="rmbz-iv-learned-detail" id="rmbz-learned-detail">
                <!-- Sumário por artista -->
                <div class="rmbz-iv-learned-byartist">
                    <div class="rmbz-iv-learned-section-title">Por artista</div>
                    <?php foreach ( $learned_by_artist as $artist_name => $row ): ?>
                        <div class="rmbz-iv-learned-arow">
                            <span class="rmbz-iv-learned-aname">🎤 <?php echo esc_html($artist_name); ?></span>
                            <span class="rmbz-iv-learned-acount"><?php echo $row['count']; ?> faixa<?php echo $row['count'] === 1 ? '' : 's'; ?></span>
                            <span class="rmbz-iv-learned-arevenue"><?php echo esc_html($cur_symbol); ?><?php echo number_format($row['revenue'], 2); ?></span>
                        </div>
                    <?php endforeach; ?>
                </div>

                <!-- Lista das faixas -->
                <div class="rmbz-iv-learned-tracks">
                    <div class="rmbz-iv-learned-section-title">Faixas detectadas</div>
                    <table class="rmbz-iv-learned-table">
                        <thead>
                            <tr>
                                <th>Título (CSV)</th>
                                <th>Artista (CSV)</th>
                                <th>Vai pagar a</th>
                                <th>Tipo</th>
                                <th class="rmbz-num">Streams</th>
                                <th class="rmbz-num">Receita</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ( $learned_alias_hits as $h ): ?>
                            <tr>
                                <td>
                                    <strong><?php echo esc_html($h['title'] ?: '—'); ?></strong>
                                    <?php if ( $h['isrc_csv'] ): ?>
                                        <code class="rmbz-iv-learned-isrc"><?php echo esc_html($h['isrc_csv']); ?></code>
                                    <?php endif; ?>
                                </td>
                                <td><?php echo esc_html($h['artist_csv'] ?: '—'); ?></td>
                                <td><strong><?php echo esc_html($h['artist_db']); ?></strong></td>
                                <td>
                                    <span class="rmbz-iv-learned-type rmbz-iv-learned-type-<?php echo esc_attr($h['alias_type']); ?>">
                                        <?php echo $h['alias_type'] === 'upc' ? 'UPC' : 'ISRC'; ?>
                                    </span>
                                </td>
                                <td class="rmbz-num"><?php echo number_format($h['streams']); ?></td>
                                <td class="rmbz-num"><strong><?php echo esc_html($cur_symbol); ?><?php echo number_format($h['revenue'], 2); ?></strong></td>
                            </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>

                <div class="rmbz-iv-learned-hint">
                    💡 <strong>Como funciona:</strong> Quando aprovas um match manualmente no "Matches a Rever",
                    o sistema memoriza a regra (CSV value → faixa). Em imports seguintes, a regra é aplicada
                    automaticamente. Para cancelar uma regra errada, vai ao <strong>Catálogo de Faixas</strong>,
                    abre a faixa e remove o alias.
                </div>
            </div>
        </div>
        <style>
        .rmbz-iv-learned {
            background: linear-gradient(135deg, #ecfdf5 0%, #f0fdfa 100%);
            border: 1px solid #6ee7b7;
            border-left: 4px solid #10b981;
            border-radius: 10px;
            padding: 16px 20px;
            margin: 0 0 20px 0;
        }
        .rmbz-iv-learned-head {
            display: flex; align-items: flex-start; gap: 14px;
        }
        .rmbz-iv-learned-icon {
            font-size: 28px; line-height: 1; flex-shrink: 0;
        }
        .rmbz-iv-learned-text { flex: 1; min-width: 0; }
        .rmbz-iv-learned-title {
            font-size: 15px; font-weight: 700; color: #065f46;
            display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
        }
        .rmbz-iv-learned-badge {
            background: #10b981; color: #fff;
            padding: 2px 9px; border-radius: 10px;
            font-size: 11px; font-weight: 700;
        }
        .rmbz-iv-learned-sub {
            font-size: 13px; color: #047857; margin-top: 4px;
        }
        .rmbz-iv-learned-toggle {
            background: #fff; border: 1px solid #6ee7b7; color: #065f46;
            padding: 6px 12px; border-radius: 6px; cursor: pointer;
            font-size: 12px; font-weight: 600; flex-shrink: 0;
            transition: all 0.15s;
        }
        .rmbz-iv-learned-toggle:hover { background: #d1fae5; }
        .rmbz-iv-learned-chevron { display: inline-block; transition: transform 0.2s; margin-left: 3px; }
        .rmbz-iv-learned-toggle.is-open .rmbz-iv-learned-chevron { transform: rotate(180deg); }

        .rmbz-iv-learned-detail {
            max-height: 0; overflow: hidden;
            transition: max-height 0.3s ease;
        }
        .rmbz-iv-learned-detail.is-open {
            max-height: 2000px;
            margin-top: 14px;
            padding-top: 14px;
            border-top: 1px dashed #6ee7b7;
        }
        .rmbz-iv-learned-section-title {
            font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em;
            color: #047857; font-weight: 700; margin-bottom: 8px;
        }
        .rmbz-iv-learned-byartist {
            background: #fff; border: 1px solid #d1fae5; border-radius: 8px;
            padding: 10px 14px; margin-bottom: 12px;
        }
        .rmbz-iv-learned-arow {
            display: grid; grid-template-columns: 1fr auto auto;
            gap: 14px; padding: 5px 0;
            border-bottom: 1px dashed #f0fdfa;
            font-size: 12px;
            align-items: center;
        }
        .rmbz-iv-learned-arow:last-child { border-bottom: none; }
        .rmbz-iv-learned-aname { color: #1a1a1a; font-weight: 500; }
        .rmbz-iv-learned-acount { color: #6b7280; font-size: 11px; }
        .rmbz-iv-learned-arevenue { color: #065f46; font-weight: 700; }

        .rmbz-iv-learned-tracks {
            background: #fff; border: 1px solid #d1fae5; border-radius: 8px;
            padding: 10px 14px; margin-bottom: 12px;
        }
        .rmbz-iv-learned-table {
            width: 100%; border-collapse: collapse; font-size: 12px;
        }
        .rmbz-iv-learned-table th {
            text-align: left; padding: 6px 8px;
            font-size: 10px; text-transform: uppercase;
            letter-spacing: 0.04em; color: #6b7280; font-weight: 700;
            border-bottom: 1px solid #d1fae5;
        }
        .rmbz-iv-learned-table td {
            padding: 6px 8px; border-bottom: 1px solid #f3f4f6;
        }
        .rmbz-iv-learned-table tr:last-child td { border-bottom: none; }
        .rmbz-iv-learned-table .rmbz-num { text-align: right; font-variant-numeric: tabular-nums; }
        .rmbz-iv-learned-isrc {
            background: #f3f4f6; padding: 1px 5px;
            border-radius: 3px; font-size: 10px;
            margin-left: 6px;
        }
        .rmbz-iv-learned-type {
            display: inline-block;
            padding: 2px 7px; border-radius: 8px;
            font-size: 10px; font-weight: 700;
            background: #fef3c7; color: #92400e;
        }
        .rmbz-iv-learned-type-upc {
            background: #dbeafe; color: #1e40af;
        }
        .rmbz-iv-learned-hint {
            background: #f0fdfa; border-radius: 6px;
            padding: 10px 12px; font-size: 11.5px;
            color: #065f46; line-height: 1.5;
        }
        </style>
        <?php endif; // learned_count > 0 ?>

        <?php
        $artist_share_pct = function_exists('rmbz_get_artist_share_pct') ? rmbz_get_artist_share_pct() : 70;
        $onemz_pct = 100 - $artist_share_pct;
        $artist_total_eur = round($total_money * $artist_share_pct / 100, 2);
        $onemz_total_eur  = round($total_money - $artist_total_eur, 2);
        $artist_total_usd_calc = round($total_usd * $artist_share_pct / 100, 2);
        $onemz_total_usd_calc  = round($total_usd - $artist_total_usd_calc, 2);
        ?>
        <div class="rmbz-iv-card" style="border-left: 3px solid #9b59b6;">
            <div class="rmbz-iv-card-head">
                <strong>💸 Divisão de receita (1MusicMoz)</strong>
                <span>taxa 1MZ: <?php echo $onemz_pct; ?>% · artistas: <?php echo $artist_share_pct; ?>%</span>
            </div>
            <div class="rmbz-commission-cascade">
                <div class="cc-row">
                    <?php /* [1.5.177] FIX REAL do bug de contraste:
                       Na 1.5.176 mudei o background para var(--rmbz-bg-elevated)
                       pensando que seria cinza médio, mas esse token aponta para
                       PRETO (dark theme). Resultado: barra ficou preta, texto
                       preto invisível.

                       Solução: cores hardcoded apropriadas para esta barra
                       específica — é precisamente o caso onde não há token
                       semântico adequado (cinza neutro de "baseline" para
                       totalizadores).

                       Background #d8dade (cinza médio claro) + texto #1a1a1a
                       (preto sólido) = contraste WCAG AAA. */ ?>
                    <div class="cc-lbl" style="color:#1a1a1a; font-weight:600;">Bruto importado</div>
                    <div class="cc-bar" style="background:#d8dade; color:#1a1a1a; width: 100%;">
                        <span><?php echo esc_html($cur_symbol); ?><?php echo number_format($total_money, 2); ?> · 100%</span>
                    </div>
                </div>
                <div class="cc-row">
                    <div class="cc-lbl" style="color:var(--rmbz-info-strong, #2563eb); font-weight:500;">Taxa 1MZ (<?php echo $onemz_pct; ?>%)</div>
                    <div class="cc-bar" style="width: <?php echo $onemz_pct; ?>%; background: var(--rmbz-info, #3b82f6); color: var(--rmbz-text-on-color, #fff);">
                        <span>
                            <?php echo esc_html($cur_symbol); ?><?php echo number_format($onemz_total_eur, 2); ?>
                            <?php if ( $detected_currency !== 'USD' ): ?>
                                <small>($<?php echo number_format($onemz_total_usd_calc, 2); ?>)</small>
                            <?php endif; ?>
                        </span>
                    </div>
                </div>
                <div class="cc-row">
                    <div class="cc-lbl" style="color:var(--rmbz-success-strong, #059669); font-weight:500;">Artistas recebem (<?php echo $artist_share_pct; ?>%)</div>
                    <div class="cc-bar" style="width: <?php echo $artist_share_pct; ?>%; background: var(--rmbz-success, #10b981); color: var(--rmbz-text-on-color, #fff);">
                        <span>
                            <?php echo esc_html($cur_symbol); ?><?php echo number_format($artist_total_eur, 2); ?>
                            <?php if ( $detected_currency !== 'USD' ): ?>
                                <small>($<?php echo number_format($artist_total_usd_calc, 2); ?>)</small>
                            <?php endif; ?>
                        </span>
                    </div>
                </div>
            </div>
            <div class="cc-hint">
                💡 Ao confirmar, <strong><?php echo esc_html($cur_symbol); ?><?php echo number_format($artist_total_eur, 2); ?></strong> serão distribuídos pelos artistas (por ISRC) e
                <strong><?php echo esc_html($cur_symbol); ?><?php echo number_format($onemz_total_eur, 2); ?></strong> ficam registados como margem 1MusicMoz na auditoria.
            </div>
        </div>

        <div class="rmbz-iv-grid-3-2">

            <div class="rmbz-iv-card">
                <div class="rmbz-iv-card-head">
                    <strong>🏪 Lojas / DSPs (<?php echo count($by_store); ?>)</strong>
                    <span>todas visíveis para auditoria</span>
                </div>
                <div class="rmbz-iv-stores" style="max-height:500px; overflow-y:auto;">
                    <?php
                    // [DS 1.5.99] Mostra TODAS as lojas (sem array_slice).
                    // Crítico para auditoria — admin precisa de ver tudo antes
                    // de aprovar para detectar valores estranhos ou lojas
                    // desconhecidas que possam ser fraudulentas.
                    foreach ( $by_store as $store_name => $data ):
                        $icon = rmbz_store_icon_info($store_name);
                        $pct = $total_money > 0 ? ($data['revenue'] / $total_money * 100) : 0;
                    ?>
                        <div class="store-row">
                            <div class="store-icon" style="background: <?php echo esc_attr($icon['color']); ?>;">
                                <?php echo esc_html($icon['initial']); ?>
                            </div>
                            <div class="store-body">
                                <div class="store-top">
                                    <span class="name"><?php echo esc_html($store_name); ?></span>
                                    <span class="val">
                                        <?php echo esc_html($cur_symbol); ?><?php echo number_format($data['revenue'], 2); ?>
                                        <small>· <?php echo number_format($pct, 1); ?>%</small>
                                    </span>
                                </div>
                                <div class="store-bar">
                                    <div class="fill" style="width: <?php echo number_format($pct, 2); ?>%; background: <?php echo esc_attr($icon['color']); ?>;"></div>
                                </div>
                                <?php if ( $data['streams'] > 0 ): ?>
                                    <div class="store-sub"><?php echo rmbz_fmt_compact($data['streams']); ?> streams</div>
                                <?php endif; ?>
                            </div>
                        </div>
                    <?php endforeach; ?>
                </div>
            </div>

            <div class="rmbz-iv-card">
                <div class="rmbz-iv-card-head">
                    <strong>🌍 Países (<?php echo count($by_country); ?>)</strong>
                    <span>todos visíveis para auditoria</span>
                </div>
                <div class="rmbz-iv-countries" style="max-height:500px; overflow-y:auto;">
                    <?php
                    // [DS 1.5.99] Mostra TODOS os países (sem array_slice nem
                    // agregação "+N outros"). O admin precisa de ver tudo
                    // para detectar países anormais ou fraudulentos antes
                    // de aprovar a distribuição. % calculada por país para
                    // dar contexto visual da distribuição geográfica.
                    foreach ( $by_country as $cc => $rev ):
                        $pct = $total_money > 0 ? ($rev / $total_money * 100) : 0;
                    ?>
                        <div class="country-row">
                            <span class="flag"><?php
                                $cc_l = strtolower( trim( (string) $cc ) );
                                if ( strlen($cc_l) === 2 && ctype_alpha($cc_l) ) {
                                    echo '<img src="https://flagcdn.com/32x24/' . esc_attr($cc_l) . '.png" alt="' . esc_attr($cc) . '" loading="lazy" onerror="this.replaceWith(document.createTextNode(\'🌍\'));">';
                                } else {
                                    echo '🌍';
                                }
                            ?></span>
                            <span class="code"><?php echo esc_html($cc); ?></span>
                            <span class="name"><?php echo esc_html( rmbz_country_name_pt($cc) ); ?></span>
                            <span class="val">
                                <?php echo esc_html($cur_symbol); ?><?php echo number_format($rev, 2); ?>
                                <small style="color:var(--rmbz-text-faint, #888); font-weight:400;">· <?php echo number_format($pct, 1); ?>%</small>
                            </span>
                        </div>
                    <?php endforeach; ?>
                </div>
            </div>

        </div>

        <?php // [DS 1.5.95] Diagnóstico — só aparece quando algo correu mal ?>
        <?php if ( empty($by_service) || empty($by_artist) ): ?>
            <div class="rmbz-iv-card" style="border-left:3px solid #f0b90b; background:#fffaf0;">
                <strong>⚠ Diagnóstico de detecção</strong>
                <p style="margin:8px 0 0; font-size:12px; color:var(--rmbz-text-muted, #666);">
                    Os cards de "Artistas detetados" e "Fontes de monetização" só aparecem quando os dados são detectados no CSV.
                    Estado actual:
                </p>
                <ul style="font-size:12px; color:var(--rmbz-text-primary, #444); margin:8px 0 0 16px; line-height:1.7;">
                    <li>📋 Linhas processadas no loop: <strong><?php echo (int) $rows_count; ?></strong></li>
                    <li>🎤 Artistas detectados: <strong><?php echo count($by_artist); ?></strong>
                        <?php if ( empty($by_artist) ): ?>
                            <span style="color:var(--rmbz-danger, #cc0000);">— vazio! Possível causa: coluna "artist" não detectada (índice = <?php echo var_export($idx_artist, true); ?>).</span>
                        <?php endif; ?>
                    </li>
                    <li>💰 Fontes de monetização: <strong><?php echo count($by_service); ?></strong>
                        <?php if ( empty($by_service) ): ?>
                            <span style="color:var(--rmbz-danger, #cc0000);">— vazio! Possível causa: coluna "store" não detectada (índice = <?php echo var_export($idx_store, true); ?>).</span>
                        <?php endif; ?>
                    </li>
                    <li>🎵 Faixas únicas: <strong><?php echo count($by_track); ?></strong></li>
                    <li>🏪 Lojas: <strong><?php echo count($by_store); ?></strong></li>
                </ul>
            </div>
        <?php endif; ?>

        <?php // [DS 1.5.94] Card de FONTES DE MONETIZAÇÃO — separa Content ID, Meta, etc ?>
        <?php if ( ! empty($by_service) ):
            uasort( $by_service, function($a, $b){ return $b['revenue'] <=> $a['revenue']; });
        ?>
            <div class="rmbz-iv-card">
                <div class="rmbz-iv-card-head">
                    <strong>💰 Fontes de monetização (<?php echo count($by_service); ?>)</strong>
                    <span>destaca fontes UGC (Content ID, Meta, TikTok Monetization)</span>
                </div>
                <p style="margin:0 0 12px 0; font-size:12px; color:var(--rmbz-text-muted, #666);">
                    Os serviços <strong style="color:var(--rmbz-accent, #a855f7);">com fundo roxo</strong> são fontes especiais
                    (UGC/monetização de conteúdo) que merecem atenção extra do admin.
                </p>
                <table class="rmbz-iv-table">
                    <thead>
                        <tr>
                            <th>Fonte</th>
                            <th style="text-align:right;">Faixas</th>
                            <th style="text-align:right;">Streams</th>
                            <th style="text-align:right;">Receita</th>
                            <th style="text-align:right; width:80px;">% do total</th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php foreach ( $by_service as $svc_key => $svc ):
                        $pct = $total_money > 0 ? ( $svc['revenue'] / $total_money * 100 ) : 0;
                        $bg = $svc['is_special'] ? 'background:rgba(155,89,182,0.06);' : '';
                    ?>
                        <tr style="<?php echo $bg; ?>">
                            <td>
                                <strong><?php echo esc_html($svc_key); ?></strong>
                                <?php if ( $svc['is_special'] ): ?>
                                    <span style="background:var(--rmbz-accent, #a855f7); color:var(--rmbz-text-on-color, #fff); padding:2px 7px; border-radius:10px; font-size:9px; font-weight:600; margin-left:6px; text-transform:uppercase; letter-spacing:0.3px;">UGC</span>
                                <?php endif; ?>
                            </td>
                            <td style="text-align:right;"><?php echo count($svc['tracks']); ?></td>
                            <td style="text-align:right;"><?php echo $svc['streams'] > 0 ? number_format($svc['streams']) : '—'; ?></td>
                            <td style="text-align:right;">
                                <strong><?php echo esc_html($cur_symbol); ?><?php echo number_format($svc['revenue'], 2); ?></strong>
                            </td>
                            <td style="text-align:right; color:var(--rmbz-text-muted, #666); font-size:11px;"><?php echo number_format($pct, 1); ?>%</td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            </div>
        <?php endif; ?>

        <?php // [1.5.178] CARD: ARTISTAS REGISTADOS DETECTADOS — possíveis lançamentos em falta ?>
        <?php if ( ! empty( $registered_artists_match ) ):
            // Ordenar por receita CSV desc
            uasort( $registered_artists_match, function($a, $b) {
                return $b['csv_revenue'] <=> $a['csv_revenue'];
            } );
            // Calcular contagem total para badge
            $total_matches = count( $registered_artists_match );
            $total_unlinked = 0;
            foreach ( $registered_artists_match as $r ) {
                foreach ( $r['matches'] as $m ) {
                    $total_unlinked += $m['unlinked_count'];
                }
            }
        ?>
            <div class="rmbz-iv-card" style="border-left:3px solid #f0b90b; background:#fffaf0;">
                <div class="rmbz-iv-card-head">
                    <strong>🔍 Artistas registados detectados — possíveis lançamentos em falta</strong>
                    <span>
                        <?php echo (int) $total_matches; ?> artista(s) ·
                        <?php echo (int) $total_unlinked; ?> faixa(s) por vincular
                    </span>
                </div>
                <p style="margin:0 0 12px 0; font-size:13px; color:var(--rmbz-text-muted, #666); line-height:1.6;">
                    Encontrámos <strong><?php echo (int) $total_matches; ?></strong> artista(s) com nome semelhante a artistas <strong>registados na plataforma</strong>.
                    Pode haver <strong>lançamentos por importar</strong> ou faixas que ainda não foram associadas.
                    <strong>Verifica antes de continuar para não perder música.</strong>
                </p>

                <table class="rmbz-iv-table">
                    <thead>
                        <tr>
                            <th>Artista (CSV)</th>
                            <th>Match com (Registado)</th>
                            <th style="text-align:center; width:90px;">Confiança</th>
                            <th style="text-align:right; width:80px;">CSV</th>
                            <th style="text-align:right; width:90px;">Vinculadas</th>
                            <th style="text-align:right; width:120px;" title="Faixas já importadas anteriormente neste mesmo período — atenção a duplicação!">
                                🔁 Já importadas
                            </th>
                            <th style="text-align:right; width:100px;">⚠ Em falta</th>
                            <th style="text-align:right; width:90px;">Total registadas</th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php foreach ( $registered_artists_match as $csv_key_iter => $entry ): ?>
                        <?php foreach ( $entry['matches'] as $match ):
                            $level = $match['level'];
                            $level_label = '';
                            $level_color = '';
                            switch ( $level ) {
                                case 'exact':
                                    $level_label = 'Exacto';
                                    $level_color = '#10b981'; // verde
                                    break;
                                case 'normalized':
                                    $level_label = 'Normalizado';
                                    $level_color = '#3b82f6'; // azul
                                    break;
                                case 'main_artist':
                                    // [1.5.201] Match após remover featuring/feat./ft. inline
                                    $level_label = 'Sem feat.';
                                    $level_color = '#8b5cf6'; // roxo
                                    break;
                                case 'fuzzy':
                                    $level_label = 'Fuzzy (~' . ( $match['distance'] ?? '?' ) . ' letras)';
                                    $level_color = '#f0b90b'; // âmbar
                                    break;
                            }
                            $needs_attention = ( $match['unlinked_count'] > 0 );
                            // [FEAT 1.6.7] Re-import severity overrides background colour
                            $sev = $match['reimport_severity'] ?? 'clean';
                            // [FEAT 1.6.19] Anomalia de receita
                            $anom = $anomalies[ $csv_key_iter ] ?? null;
                            if ( $sev === 'full' ) {
                                $row_bg = 'background:#fee2e2;'; // vermelho
                            } elseif ( $sev === 'partial' ) {
                                $row_bg = 'background:#fef3c7;'; // amarelo
                            } else {
                                $row_bg = $needs_attention ? 'background:#fff5e6;' : '';
                            }
                        ?>
                            <tr style="<?php echo $row_bg; ?>">
                                <td>
                                    <?php if ( $sev === 'full' ): ?>
                                        <span style="background:#dc2626; color:#fff; padding:1px 7px; border-radius:9px; font-size:10px; font-weight:700; margin-right:5px;">🚫 RE-IMPORT</span>
                                    <?php elseif ( $sev === 'partial' ): ?>
                                        <span style="background:#d97706; color:#fff; padding:1px 7px; border-radius:9px; font-size:10px; font-weight:700; margin-right:5px;">⚠ DUPLICAÇÃO PARCIAL</span>
                                    <?php endif; ?>
                                    <?php if ( $anom && $anom['type'] === 'spike' ): ?>
                                        <span style="background:#dc2626; color:#fff; padding:1px 7px; border-radius:9px; font-size:10px; font-weight:700; margin-right:5px;" title="Receita <?php echo number_format($anom['ratio'], 1); ?>× a média histórica — verifica antes de aprovar">⬆ <?php echo number_format($anom['ratio'], 1); ?>× MÉDIA</span>
                                    <?php elseif ( $anom && in_array($anom['type'], ['drop','drop_total'], true) ): ?>
                                        <span style="background:#2563eb; color:#fff; padding:1px 7px; border-radius:9px; font-size:10px; font-weight:700; margin-right:5px;" title="Receita caiu para <?php echo number_format($anom['ratio'] * 100, 0); ?>% da média histórica — verifica antes de aprovar">⬇ QUEDA <?php echo number_format(100 - $anom['ratio'] * 100, 0); ?>%</span>
                                    <?php endif; ?>
                                    <strong><?php echo esc_html( $entry['csv_display_name'] ); ?></strong>
                                    <br><small style="color:#888;">
                                        <?php echo number_format( $entry['csv_streams'] ); ?> stream(s) ·
                                        <?php echo esc_html( $cur_symbol ); ?><?php echo number_format( $entry['csv_revenue'], 2 ); ?>
                                    </small>
                                </td>
                                <td>
                                    <?php echo esc_html( $match['display_name'] ); ?>
                                    <br><small style="color:#888;"><code><?php echo esc_html( $match['telemovel'] ); ?></code></small>
                                </td>
                                <td style="text-align:center;">
                                    <span style="display:inline-block; padding:3px 10px; border-radius:12px; font-size:11px; font-weight:600; background:<?php echo esc_attr( $level_color ); ?>; color:#fff;">
                                        <?php echo esc_html( $level_label ); ?>
                                    </span>
                                    <br><small style="color:#888; font-size:10px;"><?php echo (int) $match['confidence']; ?>%</small>
                                </td>
                                <td style="text-align:right;"><strong><?php echo (int) $match['csv_track_count']; ?></strong></td>
                                <td style="text-align:right;">
                                    <?php if ( $match['linked_to_artist'] === $match['csv_track_count'] && $match['csv_track_count'] > 0 ): ?>
                                        <span style="color:#10b981; font-weight:700;">✓ <?php echo (int) $match['linked_to_artist']; ?></span>
                                    <?php else: ?>
                                        <strong><?php echo (int) $match['linked_to_artist']; ?></strong>
                                    <?php endif; ?>
                                </td>
                                <td style="text-align:right;">
                                    <?php if ( ($match['already_imported_count'] ?? 0) > 0 ): ?>
                                        <span style="color:<?php echo $sev === 'full' ? '#991b1b' : '#92400e'; ?>; font-weight:700;">
                                            <?php echo (int) $match['already_imported_count']; ?>
                                        </span>
                                        <?php if ( ($match['already_imported_revenue'] ?? 0) > 0 ): ?>
                                            <br><small style="color:#9a3412; font-size:10px;">
                                                ≈<?php echo esc_html( $cur_symbol ); ?><?php echo number_format( $match['already_imported_revenue'], 2 ); ?>
                                            </small>
                                        <?php endif; ?>
                                    <?php else: ?>
                                        <span style="color:#10b981; font-weight:600;">—</span>
                                    <?php endif; ?>
                                </td>
                                <td style="text-align:right;">
                                    <?php if ( $match['unlinked_count'] > 0 ): ?>
                                        <span style="color:#cc4400; font-weight:700;">⚠ <?php echo (int) $match['unlinked_count']; ?></span>
                                    <?php else: ?>
                                        <span style="color:#888;">0</span>
                                    <?php endif; ?>
                                </td>
                                <td style="text-align:right; color:#666;"><?php echo (int) $match['registered_track_count']; ?></td>
                            </tr>
                        <?php endforeach; ?>
                    <?php endforeach; ?>
                    </tbody>
                </table>

                <div style="margin-top:14px; padding:12px 14px; background:#f5f5f5; border-radius:6px; font-size:12px; color:#555; line-height:1.6;">
                    <strong>Como interpretar:</strong>
                    <ul style="margin:6px 0 0 18px; padding:0;">
                        <li><strong>Confiança</strong> = quão certo está o match. <em>Exacto</em> = nome igual case-insensitive. <em>Normalizado</em> = igual ignorando pontuação/acentos. <em>Fuzzy</em> = pequenas variações (1-2 letras), pode ser falso positivo.</li>
                        <li><strong>CSV</strong> = quantas faixas únicas (ISRC) este nome de artista tem no CSV.</li>
                        <li><strong>Vinculadas</strong> = quantas dessas já estão associadas ao artista registado.</li>
                        <li><strong>🔁 Já importadas</strong> = faixas que já foram processadas no log original (em re-imports) e estão protegidas contra duplicação.</li>
                        <li><strong>⚠ Em falta</strong> = faixas que ainda <strong>não estão registadas</strong> nem <strong>já importadas</strong> — possível novo lançamento ou ISRC ainda não importado. Vão para revisão manual ou Não Reclamados.</li>
                        <li><strong>Total registadas</strong> = quantas faixas o artista tem ao todo no sistema (independente do CSV).</li>
                    </ul>
                </div>
            </div>
        <?php endif; ?>

        <?php // [DS 1.5.94] Card de ARTISTAS DETETADOS — agrupa por nome do CSV ?>
        <?php if ( ! empty($by_artist) ):
            uasort( $by_artist, function($a, $b){ return $b['revenue'] <=> $a['revenue']; });
        ?>
            <div class="rmbz-iv-card">
                <div class="rmbz-iv-card-head">
                    <strong>🎤 Artistas detetados no CSV (<?php echo count($by_artist); ?>)</strong>
                    <span>agrupado por nome de artista</span>
                </div>
                <p style="margin:0 0 12px 0; font-size:12px; color:var(--rmbz-text-muted, #666);">
                    Cada artista mostra as músicas que têm receita neste import e o total que vai receber
                    (antes da taxa 1MZ). Marca/desmarca o artista para afetar todas as músicas dele de uma vez.
                    Clica no nome para expandir.
                </p>

                <?php /* [1.5.199] Legenda das cores das linhas */ ?>
                <div style="display:flex; gap:14px; flex-wrap:wrap; margin-bottom:10px; font-size:11px;">
                    <span style="display:inline-flex; align-items:center; gap:5px;">
                        <span style="display:inline-block; width:14px; height:14px; background:#ecfdf5; border-left:3px solid #10b981; border-radius:2px;"></span>
                        <span style="color:#065f46;"><strong>Verde</strong>: artista registado · todas as faixas com match ISRC</span>
                    </span>
                    <span style="display:inline-flex; align-items:center; gap:5px;">
                        <span style="display:inline-block; width:14px; height:14px; background:#fffbeb; border-left:3px solid #f59e0b; border-radius:2px;"></span>
                        <span style="color:#92400e;"><strong>Amarelo</strong>: artista registado mas com faixas em revisão manual</span>
                    </span>
                    <span style="display:inline-flex; align-items:center; gap:5px;">
                        <span style="display:inline-block; width:14px; height:14px; background:#fff; border:1px solid #ddd; border-radius:2px;"></span>
                        <span style="color:#666;"><strong>Branco</strong>: artista não registado (não conhecemos)</span>
                    </span>
                </div>
                <div style="max-height:500px; overflow-y:auto; border:1px solid #eee; border-radius:6px;">
                <table class="rmbz-iv-table" id="rmbz-artists-table">
                    <thead>
                        <tr>
                            <th style="width:36px; text-align:center;" title="Marcar/desmarcar todos os artistas">
                                <input type="checkbox" id="rmbz-artist-master" checked>
                            </th>
                            <th style="width:30px;"></th>
                            <th>Artista (do CSV)</th>
                            <th style="text-align:right; width:80px;">Músicas</th>
                            <th style="text-align:right; width:90px;">Streams</th>
                            <th style="text-align:right; width:120px;">Receita</th>
                            <th style="text-align:right; width:80px;">% do total</th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php
                    $art_idx = 0;
                    foreach ( $by_artist as $art_key => $art ):
                        $art_idx++;
                        $row_id = 'rmbz-art-' . $art_idx;
                        $pct = $total_money > 0 ? ( $art['revenue'] / $total_money * 100 ) : 0;
                        // ordenar tracks por revenue desc
                        uasort( $art['tracks'], function($a,$b){ return $b['revenue'] <=> $a['revenue']; });
                        // [DS 1.5.101] Lista de ISRCs (chaves uppercase) das tracks deste artista
                        // — usado pelo JS para fazer cascade marcar/desmarcar
                        $art_isrc_keys = array_keys( $art['tracks'] );

                        // [1.5.199] Determinar cor da linha baseado em:
                        //   1. Artista do CSV bate com artista registado?
                        //   2. As tracks deste artista têm match automático
                        //      (via ISRC/UPC) ou precisam de revisão manual?
                        //
                        // Cores:
                        //   verde:    registado + 100% das tracks têm match ISRC
                        //   amarelo:  registado mas nem todas as tracks fazem match auto
                        //   sem cor:  artista não registado (desconhecido)
                        $row_status     = 'unknown';   // unknown / registered_full_auto / registered_partial
                        $row_status_msg = '';
                        $artist_is_registered = isset( $registered_artists_match[ $art_key ] );
                        // [FIX 1.6.16] Inicializadas fora do if para o badge poder ler-las
                        $already_imported_count_artist = 0;
                        $total_tracks_art = count( $art['tracks'] );

                        if ( $artist_is_registered ) {
                            // Contar quantas tracks deste artista têm um match
                            // considerado seguro/automático.
                            //
                            // [FIX 1.6.16] Antes contava apenas method='isrc'. Agora
                            // inclui também:
                            //   - 'alias_isrc' / 'alias_upc' / 'alias_learned' →
                            //     match via tabela de aprendizagem (admin já aprovou
                            //     esta correspondência num import anterior).
                            //   - Faixas com cadeado 🔒 (já importadas no log original
                            //     do re-import) — não precisam de revisão porque já
                            //     foram processadas e estão protegidas.
                            //
                            // Outros methods (upc_title, fuzzy, none) continuam a
                            // contar como "precisam revisão".
                            $safe_methods = [
                                'isrc'           => true,
                                'alias_isrc'     => true,
                                'alias_upc'      => true,
                                'alias_learned'  => true,
                            ];
                            $auto_linked_count = 0;
                            foreach ( $art_isrc_keys as $isrc_u ) {
                                // Verificar se está já importada (cadeado)
                                $isrc_norm = strtoupper( preg_replace('/[^A-Za-z0-9]/', '', (string) $isrc_u) );
                                $is_locked = $isrc_norm !== '' && isset( $already_imported_isrcs[ $isrc_norm ] );
                                if ( $is_locked ) {
                                    $already_imported_count_artist++;
                                    $auto_linked_count++; // conta como segura — não precisa revisão
                                    continue;
                                }
                                $mr = $track_match_results[ $isrc_u ] ?? null;
                                $method = $mr['method'] ?? '';
                                if ( isset( $safe_methods[ $method ] ) ) {
                                    $auto_linked_count++;
                                }
                            }

                            if ( $auto_linked_count === $total_tracks_art && $total_tracks_art > 0 ) {
                                $row_status = 'registered_full_auto';
                                // Mensagem adaptada se algumas (ou todas) estão já importadas
                                if ( $already_imported_count_artist === $total_tracks_art ) {
                                    $row_status_msg = '🔒 Artista registado · todas as faixas já foram importadas (re-import detectado)';
                                } elseif ( $already_imported_count_artist > 0 ) {
                                    $row_status_msg = sprintf(
                                        '✓ Artista registado · %d faixa(s) já importadas + %d com match automático',
                                        $already_imported_count_artist,
                                        $total_tracks_art - $already_imported_count_artist
                                    );
                                } else {
                                    $row_status_msg = '✓ Artista registado · todas as faixas serão vinculadas automaticamente';
                                }
                            } else {
                                $row_status = 'registered_partial';
                                $missing = $total_tracks_art - $auto_linked_count;
                                $row_status_msg = sprintf(
                                    '⚠ Artista registado · %d faixa(s) precisa(m) de revisão manual',
                                    $missing
                                );
                            }
                        }

                        // Estilos inline da linha
                        $row_bg = '';
                        $row_border = '';
                        if ( $row_status === 'registered_full_auto' ) {
                            $row_bg = 'background:#ecfdf5;'; // verde claro
                            $row_border = 'border-left:3px solid #10b981;';
                        } elseif ( $row_status === 'registered_partial' ) {
                            $row_bg = 'background:#fffbeb;'; // amarelo claro
                            $row_border = 'border-left:3px solid #f59e0b;';
                        }
                    ?>
                        <tr class="rmbz-artist-row"
                            data-target="<?php echo $row_id; ?>"
                            style="cursor:pointer; <?php echo $row_bg . $row_border; ?>"
                            <?php if ( $row_status_msg ): ?>title="<?php echo esc_attr( $row_status_msg ); ?>"<?php endif; ?>>
                            <td style="text-align:center;" class="rmbz-artist-cb-cell">
                                <input type="checkbox"
                                       class="rmbz-artist-cb"
                                       data-track-isrcs="<?php echo esc_attr( implode(',', $art_isrc_keys) ); ?>"
                                       title="Marcar/desmarcar todas as músicas deste artista"
                                       checked>
                            </td>
                            <td style="text-align:center; color:var(--rmbz-text-faint, #888);">
                                <span class="rmbz-toggle-icon" data-target="<?php echo $row_id; ?>">▶</span>
                            </td>
                            <td>
                                <strong><?php echo esc_html($art['display_name']); ?></strong>
                                <?php if ( $row_status === 'registered_full_auto' ): ?>
                                    <?php
                                    // [FIX 1.6.16] Badge adaptativo: se todas as faixas estão
                                    // com cadeado (já importadas), badge azul "🔒 Já importado".
                                    // Se algumas com alias/cadeado, ainda assim verde "✓ Auto-vinculado".
                                    $all_locked = ( $already_imported_count_artist === $total_tracks_art && $total_tracks_art > 0 );
                                    if ( $all_locked ): ?>
                                        <span style="display:inline-block; margin-left:6px; padding:1px 7px; border-radius:10px; background:#dbeafe; color:#1e40af; font-size:10px; font-weight:600;" title="Todas as faixas deste artista já foram importadas — nada vai ser duplicado.">
                                            🔒 Já importado
                                        </span>
                                    <?php else: ?>
                                        <span style="display:inline-block; margin-left:6px; padding:1px 7px; border-radius:10px; background:#d1fae5; color:#065f46; font-size:10px; font-weight:600;">
                                            ✓ Auto-vinculado
                                        </span>
                                    <?php endif; ?>
                                <?php elseif ( $row_status === 'registered_partial' ): ?>
                                    <span style="display:inline-block; margin-left:6px; padding:1px 7px; border-radius:10px; background:#fef3c7; color:#92400e; font-size:10px; font-weight:600;">
                                        ⚠ Revisão manual
                                    </span>
                                <?php endif; ?>
                            </td>
                            <td style="text-align:right;"><?php echo count($art['tracks']); ?></td>
                            <td style="text-align:right;"><?php echo $art['streams'] > 0 ? number_format($art['streams']) : '—'; ?></td>
                            <td style="text-align:right;">
                                <strong><?php echo esc_html($cur_symbol); ?><?php echo number_format($art['revenue'], 2); ?></strong>
                            </td>
                            <td style="text-align:right; color:var(--rmbz-text-muted, #666); font-size:11px;"><?php echo number_format($pct, 1); ?>%</td>
                        </tr>
                        <tr id="<?php echo $row_id; ?>" class="rmbz-artist-tracks" style="display:none; background:#fafbfc;">
                            <td></td>
                            <td></td>
                            <td colspan="5" style="padding:0;">
                                <table style="width:100%; font-size:11px;">
                                    <thead style="background:#f0f0f0;">
                                        <tr>
                                            <th style="text-align:left; padding:6px 10px;">Música</th>
                                            <th style="text-align:left; padding:6px 10px; width:140px;">ISRC</th>
                                            <th style="text-align:left; padding:6px 10px; width:130px;">UPC</th>
                                            <th style="text-align:right; padding:6px 10px; width:120px;">Receita</th>
                                        </tr>
                                    </thead>
                                    <tbody>
                                    <?php foreach ( $art['tracks'] as $tk ): ?>
                                        <tr>
                                            <td style="padding:5px 10px;"><?php echo esc_html( $tk['title'] ?: '(sem título)' ); ?></td>
                                            <td style="padding:5px 10px;">
                                                <?php if ( ! empty($tk['isrc']) ): ?>
                                                    <code><?php echo esc_html($tk['isrc']); ?></code>
                                                <?php else: ?>
                                                    <span style="color:var(--rmbz-text-faint, #aaa);">—</span>
                                                <?php endif; ?>
                                            </td>
                                            <td style="padding:5px 10px;">
                                                <?php if ( ! empty($tk['upc']) ): ?>
                                                    <code><?php echo esc_html($tk['upc']); ?></code>
                                                <?php else: ?>
                                                    <span style="color:var(--rmbz-text-faint, #aaa);">—</span>
                                                <?php endif; ?>
                                            </td>
                                            <td style="padding:5px 10px; text-align:right;">
                                                <?php echo esc_html($cur_symbol); ?><?php echo number_format($tk['revenue'], 2); ?>
                                            </td>
                                        </tr>
                                    <?php endforeach; ?>
                                    </tbody>
                                </table>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
                </div>
            </div>

            <script>
            (function() {
                // ================================================================
                // [DS 1.5.101] CASCADE BIDIRECIONAL artista ↔ tracks
                // ----------------------------------------------------------------
                // Comportamento:
                //   1. Click no nome/linha do artista → expand/colapsa (já existia)
                //   2. Click no checkbox do artista → NÃO dispara expand (stopPropagation)
                //   3. Marcar artista → marca TODAS as tracks dele
                //   4. Desmarcar artista → desmarca TODAS as tracks dele
                //   5. Marcar 1 track → artista fica marcado (estado: checked)
                //   6. Desmarcar 1 track quando outras estão marcadas → artista
                //      fica em estado "indeterminate" (HTML mostra "−" em vez
                //      de "✓"). Indica visualmente "selecção parcial".
                //   7. Master toggle no header marca/desmarca todos os artistas
                //      (que por sua vez fazem cascade para as tracks)
                //
                // Os eventos disparam 'change' nos checkboxes de track, o que
                // automaticamente faz o total recalcular (script da 1.5.100).
                //
                // [BUGFIX 1.5.102] Os checkboxes de track NÃO existem quando este
                // script corre porque o card de Faixas vem DEPOIS do card de
                // Artistas no HTML. Por isso fazemos lookup TARDIO via
                // getTrackCbs() — só corre quando o user clica algo, momento
                // em que o DOM já está completo.
                // ================================================================

                var artistCbs = document.querySelectorAll('.rmbz-artist-cb');
                var master = document.getElementById('rmbz-artist-master');

                // Lookup tardio — corre quando precisamos, não no início.
                // Cache simples para não fazer querySelectorAll repetido.
                var _trackCbsCache = null;
                function getTrackCbs() {
                    if (_trackCbsCache === null) {
                        _trackCbsCache = document.querySelectorAll('.rmbz-track-cb');
                    }
                    return _trackCbsCache;
                }

                // Mapa ISRC → artistCbs (este sim podemos calcular já porque
                // os artist checkboxes existem no momento que o script corre)
                var isrcToArtists = {};
                artistCbs.forEach(function(artCb) {
                    var isrcs = (artCb.dataset.trackIsrcs || '').split(',').filter(Boolean);
                    isrcs.forEach(function(isrc) {
                        if (!isrcToArtists[isrc]) isrcToArtists[isrc] = [];
                        isrcToArtists[isrc].push(artCb);
                    });
                });
                // === Toggle expansão de cada artista (mantido da versão anterior) ===
                document.querySelectorAll('.rmbz-artist-row').forEach(function(row) {
                    row.addEventListener('click', function(e) {
                        // Se o clique foi no checkbox ou na célula do checkbox,
                        // não fazer expand. O checkbox tem o seu próprio handler.
                        if (e.target.classList.contains('rmbz-artist-cb') ||
                            e.target.classList.contains('rmbz-artist-cb-cell')) {
                            return;
                        }
                        var target = row.dataset.target;
                        var detail = document.getElementById(target);
                        var icon = row.querySelector('.rmbz-toggle-icon');
                        if (!detail) return;
                        var isOpen = detail.style.display !== 'none';
                        detail.style.display = isOpen ? 'none' : '';
                        if (icon) icon.textContent = isOpen ? '▶' : '▼';
                    });
                });

                // === Cascade ARTISTA → TRACKS ===
                artistCbs.forEach(function(artCb) {
                    // Bloquear bubbling para o click handler da row não
                    // disparar expand quando o admin marca/desmarca
                    artCb.addEventListener('click', function(e) {
                        e.stopPropagation();
                    });

                    artCb.addEventListener('change', function() {
                        // Quando o artista muda manualmente, perdemos o estado
                        // indeterminate (browser já trata disto, mas garantimos)
                        artCb.indeterminate = false;
                        var isrcs = (artCb.dataset.trackIsrcs || '').split(',').filter(Boolean);
                        var newState = artCb.checked;
                        isrcs.forEach(function(isrc) {
                            // Encontrar o checkbox da track pelo value (que é a chave ISRC)
                            getTrackCbs().forEach(function(trackCb) {
                                // [FIX 1.6.15] Saltar faixas já importadas (disabled).
                                // Caso contrário, o cascade do artista forçaria a marcar
                                // mesmo as que estão protegidas com cadeado 🔒.
                                if (trackCb.disabled || trackCb.dataset.alreadyImported === '1') return;
                                if (trackCb.value === isrc && trackCb.checked !== newState) {
                                    trackCb.checked = newState;
                                    trackCb.dispatchEvent(new Event('change', { bubbles: true }));
                                }
                            });
                        });
                        // Master também pode precisar de actualizar
                        recalcMasterState();
                    });
                });

                // === Cascade TRACK → ARTISTA ===
                // [BUGFIX 1.5.102] Usamos event delegation no document em vez
                // de attach individual aos checkboxes — as tracks ainda não
                // existem no DOM neste momento (este script corre antes do
                // card de Faixas ser renderizado).
                document.addEventListener('change', function(e) {
                    var t = e.target;
                    if (!t || !t.classList || !t.classList.contains('rmbz-track-cb')) return;
                    var artists = isrcToArtists[t.value] || [];
                    artists.forEach(function(artCb) {
                        recalcArtistState(artCb);
                    });
                    recalcMasterState();
                });

                function recalcArtistState(artCb) {
                    var isrcs = (artCb.dataset.trackIsrcs || '').split(',').filter(Boolean);
                    if (!isrcs.length) return;

                    var checkedCount = 0;
                    var totalCount = 0;
                    isrcs.forEach(function(isrc) {
                        getTrackCbs().forEach(function(trackCb) {
                            if (trackCb.value === isrc) {
                                totalCount++;
                                if (trackCb.checked) checkedCount++;
                            }
                        });
                    });

                    if (checkedCount === 0) {
                        artCb.checked = false;
                        artCb.indeterminate = false;
                    } else if (checkedCount === totalCount) {
                        artCb.checked = true;
                        artCb.indeterminate = false;
                    } else {
                        // Parcial — mostra "−" em vez de "✓"
                        artCb.checked = false;
                        artCb.indeterminate = true;
                    }
                }

                // === MASTER (header) → todos os artistas ===
                if (master) {
                    master.addEventListener('change', function() {
                        master.indeterminate = false;
                        var newState = master.checked;
                        artistCbs.forEach(function(artCb) {
                            if (artCb.checked !== newState || artCb.indeterminate) {
                                artCb.checked = newState;
                                artCb.indeterminate = false;
                                // Disparar change manualmente para correr o cascade
                                // para tracks
                                artCb.dispatchEvent(new Event('change', { bubbles: true }));
                            }
                        });
                    });
                }

                function recalcMasterState() {
                    if (!master) return;
                    var checkedCount = 0;
                    var indetermCount = 0;
                    artistCbs.forEach(function(artCb) {
                        if (artCb.indeterminate) indetermCount++;
                        else if (artCb.checked) checkedCount++;
                    });
                    var total = artistCbs.length;
                    if (indetermCount > 0 || (checkedCount > 0 && checkedCount < total)) {
                        master.checked = false;
                        master.indeterminate = true;
                    } else if (checkedCount === total) {
                        master.checked = true;
                        master.indeterminate = false;
                    } else {
                        master.checked = false;
                        master.indeterminate = false;
                    }
                }
            })();
            </script>
        <?php endif; ?>

        <?php if ( ! empty($by_track) ): ?>
            <div class="rmbz-iv-card">
                <div class="rmbz-iv-card-head">
                    <strong>📋 Faixas detectadas no CSV (<?php echo count($by_track); ?>)</strong>
                    <span>
                        <button type="button" class="button button-small" id="rmbz-sel-all">✓ Selecionar todas</button>
                        <button type="button" class="button button-small" id="rmbz-sel-matched">Só matched</button>
                        <button type="button" class="button button-small" id="rmbz-sel-none">Nenhuma</button>
                    </span>
                </div>
                <p style="margin:0 0 12px 0; font-size:12px; color:var(--rmbz-text-muted, #666);">
                    💡 <strong>Selecciona</strong> as faixas que queres importar. As <strong>desseleccionadas</strong>
                    seguem a regra "Destino dos não-selecionados" definida na configuração mais abaixo.
                </p>
                <div style="max-height:500px; overflow-y:auto; border:1px solid #eee; border-radius:6px;">
                <table class="rmbz-iv-table" id="rmbz-tracks-table">
                    <thead>
                        <tr>
                            <th style="width:36px;"><input type="checkbox" id="rmbz-track-master" checked title="Selecionar/desselecionar todas"></th>
                            <th style="width:30px;">#</th>
                            <th>Título · Artista</th>
                            <th>ISRC</th>
                            <th>UPC</th>
                            <th style="text-align:right;">Streams</th>
                            <th style="text-align:right;">Receita</th>
                            <th style="text-align:center; width:90px;">Status</th>
                            <th style="text-align:center; width:80px;">Mapear</th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php
                    $i = 1;
                    foreach ( $by_track as $isrc_key => $t ):
                        $is_linked = isset($linked_isrcs[$isrc_key]);
                        $mr = $track_match_results[$isrc_key] ?? null;
                        $method = $mr['method'] ?? ($is_linked ? 'isrc' : 'none');
                        $is_unmatched = ( $method === 'none' );
                        // [DS 1.5.115] Esta faixa já foi importada no log original?
                        // [FIX 1.6.15] Normalizar ISRC (sem hífens/espaços) para bater com
                        // as chaves de $already_imported_isrcs (que foram normalizadas no
                        // carregamento — ver linhas ~310). Antes deste fix, o cadeado 🔒
                        // não aparecia para faixas com ISRCs gravados com hífens (formato
                        // do Amadea: "BG-A47-25-24672"), porque a tabela de overrides tem
                        // valores sem hífens ("BGA472524672") e a comparação falhava.
                        $isrc_norm = strtoupper( preg_replace('/[^A-Za-z0-9]/', '', (string)($t['isrc'] ?? '')) );
                        $already_in = ! empty($isrc_norm) && isset($already_imported_isrcs[$isrc_norm]);
                    ?>
                        <tr data-method="<?php echo esc_attr($method); ?>"
                            data-isrc="<?php echo esc_attr($t['isrc']); ?>"
                            <?php if ( $already_in ): ?>
                                class="rmbz-already-imported"
                                style="background:#f0f0f0; opacity:0.65;"
                                title="Esta faixa já foi importada no log #<?php echo (int) $additional_log_id; ?>"
                            <?php endif; ?>>
                            <td>
                                <input type="checkbox" name="selected_isrcs[]"
                                       value="<?php echo esc_attr($isrc_key); ?>"
                                       class="rmbz-track-cb<?php echo $already_in ? ' rmbz-track-cb-locked' : ''; ?>"
                                       data-method="<?php echo esc_attr($method); ?>"
                                       data-revenue="<?php echo esc_attr( number_format($t['revenue'], 4, '.', '') ); ?>"
                                       <?php if ( $already_in ): ?>
                                           data-already-imported="1"
                                           disabled
                                       <?php endif; ?>
                                       form="rmbz-iv-final-form"
                                       <?php echo $already_in ? '' : 'checked'; ?>>
                                <?php if ( $already_in ): ?>
                                    <span style="display:block; font-size:10px; color:var(--rmbz-info-strong, #0073aa); margin-top:2px;" title="Esta faixa já foi importada anteriormente e não pode ser re-importada.">🔒 já importado</span>
                                <?php endif; ?>
                            </td>
                            <td><?php echo $i++; ?></td>
                            <td>
                                <strong><?php echo esc_html( $t['title'] ?: '(sem título)' ); ?></strong>
                                <?php if ( ! empty($t['artist']) ): ?>
                                    <div class="muted"><?php echo esc_html($t['artist']); ?></div>
                                <?php endif; ?>
                            </td>
                            <td>
                                <?php if ( ! empty($t['isrc']) ): ?>
                                    <code><?php echo esc_html($t['isrc']); ?></code>
                                <?php else: ?>
                                    <span style="color:var(--rmbz-text-faint, #aaa);">—</span>
                                <?php endif; ?>
                            </td>
                            <td>
                                <?php if ( ! empty($t['upc']) ): ?>
                                    <code><?php echo esc_html($t['upc']); ?></code>
                                <?php else: ?>
                                    <span style="color:var(--rmbz-text-faint, #aaa);">—</span>
                                <?php endif; ?>
                            </td>
                            <td style="text-align:right;"><?php echo $t['streams'] > 0 ? number_format($t['streams']) : '—'; ?></td>
                            <td style="text-align:right;">
                                <strong><?php echo esc_html($cur_symbol); ?><?php echo number_format($t['revenue'], 2); ?></strong>
                                <?php if ( $detected_currency !== 'USD' ): ?>
                                    <div class="muted" style="font-size:10px;">$<?php echo number_format($t['revenue'] * $rate, 2); ?></div>
                                <?php endif; ?>
                            </td>
                            <td style="text-align:center;">
                                <?php
                                $conflict = ! empty($mr['artist_conflict']);
                                if ( $method === 'isrc' ): ?>
                                    <span class="status-pill linked">✓ Vinculada</span>
                                <?php elseif ( $method === 'upc_title' ): ?>
                                    <span class="status-pill" style="background:#fff3cd; color:#856404;" title="Match por UPC + título — vai para revisão admin">UPC + Título</span>
                                <?php elseif ( $method === 'fuzzy_artist_title' ): ?>
                                    <span class="status-pill" style="background:#fde4e2; color:#921a13;" title="Match por nome do artista + título (fuzzy) — vai para revisão admin">Fuzzy</span>
                                <?php elseif ( $method === 'upc_only' ): ?>
                                    <span class="status-pill" style="background:#e2e3e5; color:#495057;" title="Match só por UPC (títulos diferentes) — vai para revisão admin">UPC só</span>
                                    <?php if ( $conflict ): ?>
                                        <br><span style="background:var(--rmbz-danger, #ef4444); color:var(--rmbz-text-on-color, #fff); padding:1px 5px; border-radius:3px; font-size:9px; font-weight:600; margin-top:2px; display:inline-block;" title="Artista do CSV não bate com artista da BD — possível UPC duplicado">⚠ Conflito</span>
                                    <?php endif; ?>
                                <?php else: ?>
                                    <span class="status-pill unlinked">⚠ Sem match</span>
                                <?php endif; ?>
                            </td>
                            <td style="text-align:center;">
                                <?php if ( $is_unmatched ): ?>
                                    <button type="button"
                                            class="button button-small rmbz-map-isrc-btn"
                                            data-isrc="<?php echo esc_attr($t['isrc']); ?>"
                                            data-upc="<?php echo esc_attr($t['upc'] ?? ''); ?>"
                                            data-title="<?php echo esc_attr($t['title']); ?>"
                                            data-artist="<?php echo esc_attr($t['artist'] ?? ''); ?>"
                                            title="Mapear manualmente este ISRC ou UPC a uma faixa existente">
                                        🔗 Mapear
                                    </button>
                                <?php else: ?>
                                    <span style="color:var(--rmbz-text-faint, #bbb); font-size:11px;">—</span>
                                <?php endif; ?>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
                </div>
                <?php if ( $unlinked_count > 0 ): ?>
                    <div class="rmbz-iv-hint">
                        💡 Resultado da detecção:
                        <strong><?php echo (int)($match_counts['isrc'] ?? 0); ?></strong> auto-vinculadas por ISRC.
                        <?php if ( ! empty($match_counts['upc_title']) || ! empty($match_counts['fuzzy_artist_title']) || ! empty($match_counts['upc_only']) ): ?>
                            <strong><?php echo (int)(($match_counts['upc_title'] ?? 0) + ($match_counts['fuzzy_artist_title'] ?? 0) + ($match_counts['upc_only'] ?? 0)); ?></strong> sugeridas (vão à <a href="?page=rmbz-admin-distribution&tab=match_review">🔍 Matches a Rever</a>).
                        <?php endif; ?>
                        <?php if ( ! empty($match_counts['none']) ): ?>
                            <strong><?php echo (int)$match_counts['none']; ?></strong> sem match → seguem a regra de "Destino" abaixo.
                        <?php endif; ?>
                    </div>
                <?php endif; ?>
            </div>

            <script>
            (function() {
                // [DS 1.5.100] Helper: marca/desmarca um checkbox e dispara o
                // evento 'change' programaticamente para que o recalc do total
                // (no script do botão Confirmar) apanhe a mudança.
                // [FIX 1.6.15] Nunca marca um checkbox locked (já importado).
                function setCb(cb, checked) {
                    if (cb.disabled || cb.dataset.alreadyImported === '1') return;
                    if (cb.checked === checked) return;
                    cb.checked = checked;
                    cb.dispatchEvent(new Event('change', { bubbles: true }));
                }

                // Master checkbox controla todos
                var master = document.getElementById('rmbz-track-master');
                var cbs = document.querySelectorAll('.rmbz-track-cb');
                if (master) {
                    master.addEventListener('change', function() {
                        cbs.forEach(function(cb) { setCb(cb, master.checked); });
                    });
                }
                // Botões de seleção em massa
                document.getElementById('rmbz-sel-all')?.addEventListener('click', function() {
                    cbs.forEach(function(cb) { setCb(cb, true); });
                    if (master) master.checked = true;
                });
                document.getElementById('rmbz-sel-none')?.addEventListener('click', function() {
                    cbs.forEach(function(cb) { setCb(cb, false); });
                    if (master) master.checked = false;
                });
                document.getElementById('rmbz-sel-matched')?.addEventListener('click', function() {
                    cbs.forEach(function(cb) {
                        var shouldBe = (cb.dataset.method === 'isrc' || cb.dataset.method === 'upc_title' || cb.dataset.method === 'fuzzy_artist_title');
                        setCb(cb, shouldBe);
                    });
                });

                // Mapeamento manual de ISRC/UPC — abre modal com pesquisa
                var mapBtns = document.querySelectorAll('.rmbz-map-isrc-btn');
                mapBtns.forEach(function(btn) {
                    btn.addEventListener('click', function() {
                        var isrc = btn.dataset.isrc || '';
                        var upc = btn.dataset.upc || '';
                        var title = btn.dataset.title || '';
                        var artist = btn.dataset.artist || '';
                        rmbzOpenAliasMapModal(isrc, upc, title, artist, btn);
                    });
                });

                // [DS 1.5.97] Modal refeito para suportar ISRC E UPC.
                // Se a faixa só tem ISRC (sem UPC) → modo ISRC directo (sem selector).
                // Se tem ambos → mostra selector ISRC/UPC.
                window.rmbzOpenAliasMapModal = function(isrc, upc, title, artist, sourceBtn) {
                    var existing = document.getElementById('rmbz-alias-map-modal');
                    if (existing) existing.remove();

                    var hasUpc = upc && upc.length > 4;
                    var hasIsrc = isrc && isrc.length > 4;

                    // Helper para mostrar/esconder secções
                    function buildSelectorHtml() {
                        if (!hasUpc) return ''; // sem UPC, não há escolha — modo ISRC
                        return '<div style="margin:0 0 16px; padding:12px; background:#f8f9fa; border-radius:6px;">' +
                            '<div style="font-size:12px; color:var(--rmbz-text-muted, #666); margin-bottom:8px; font-weight:600;">Que identificador queres mapear?</div>' +
                            '<label style="display:inline-flex; align-items:center; gap:6px; margin-right:18px; cursor:pointer;">' +
                              '<input type="radio" name="rmbz-alias-type" value="isrc" checked> ' +
                              '<span><strong>ISRC</strong> <code style="background:var(--rmbz-bg-card, #fff); padding:2px 6px; border-radius:3px; font-size:11px;">' + isrc + '</code></span>' +
                            '</label>' +
                            '<label style="display:inline-flex; align-items:center; gap:6px; cursor:pointer;">' +
                              '<input type="radio" name="rmbz-alias-type" value="upc"> ' +
                              '<span><strong>UPC</strong> <code style="background:var(--rmbz-bg-card, #fff); padding:2px 6px; border-radius:3px; font-size:11px;">' + upc + '</code></span>' +
                            '</label>' +
                          '</div>';
                    }

                    var modal = document.createElement('div');
                    modal.id = 'rmbz-alias-map-modal';
                    modal.innerHTML = '<div class="rmbz-isrc-map-overlay">' +
                        '<div class="rmbz-isrc-map-box">' +
                          '<h3 style="margin:0 0 6px;">🔗 Mapear identificador a faixa existente</h3>' +
                          '<p style="margin:0 0 14px; color:var(--rmbz-text-muted, #666); font-size:13px;">' +
                            'CSV diz: <strong>' + (title || '(sem título)') + '</strong>' +
                            (artist ? ' · ' + artist : '') +
                          '</p>' +
                          buildSelectorHtml() +
                          '<input type="text" id="rmbz-isrc-search" placeholder="Pesquisar faixa interna por título, artista ou ISRC..." ' +
                            'style="width:100%; padding:10px; font-size:14px; border:1px solid #ccc; border-radius:6px; box-sizing:border-box;" autofocus>' +
                          '<div id="rmbz-isrc-results" style="margin-top:10px; max-height:300px; overflow-y:auto;"></div>' +
                          '<div style="margin-top:12px; text-align:right;">' +
                            '<button type="button" class="button" id="rmbz-isrc-cancel">Cancelar</button>' +
                          '</div>' +
                        '</div></div>';
                    document.body.appendChild(modal);
                    document.getElementById('rmbz-isrc-cancel').onclick = function() { modal.remove(); };

                    // Helper que devolve o tipo seleccionado (isrc ou upc)
                    function getSelectedType() {
                        var sel = modal.querySelector('input[name="rmbz-alias-type"]:checked');
                        return sel ? sel.value : 'isrc';
                    }
                    function getSelectedValue() {
                        return getSelectedType() === 'upc' ? upc : isrc;
                    }
                    function getTypeLabel() {
                        return getSelectedType() === 'upc' ? 'UPC' : 'ISRC';
                    }

                    var searchInput = document.getElementById('rmbz-isrc-search');
                    var debounce = null;
                    searchInput.addEventListener('input', function() {
                        clearTimeout(debounce);
                        var q = searchInput.value.trim();
                        if (q.length < 2) {
                            document.getElementById('rmbz-isrc-results').innerHTML = '<p style="color:var(--rmbz-text-faint, #888); font-size:12px;">Mínimo 2 caracteres.</p>';
                            return;
                        }
                        debounce = setTimeout(function() {
                            var fd = new FormData();
                            fd.append('action', 'rmbz_search_tracks_for_mapping');
                            fd.append('q', q);
                            fd.append('_nonce', '<?php echo wp_create_nonce('rmbz_search_tracks'); ?>');
                            fetch('<?php echo admin_url('admin-ajax.php'); ?>', { method:'POST', body:fd, credentials:'same-origin' })
                                .then(function(r){ return r.json(); })
                                .then(function(res){
                                    var box = document.getElementById('rmbz-isrc-results');
                                    if (!res.success || !res.data.tracks || !res.data.tracks.length) {
                                        box.innerHTML = '<p style="color:var(--rmbz-text-faint, #888); font-size:12px;">Sem resultados.</p>';
                                        return;
                                    }
                                    var html = '';
                                    res.data.tracks.forEach(function(t) {
                                        html += '<div class="rmbz-track-result" style="padding:10px; border-bottom:1px solid #eee; cursor:pointer;" ' +
                                                'data-track-id="' + t.id + '">' +
                                                '<strong>' + (t.title || '(sem título)') + '</strong>' +
                                                '<div style="font-size:11px; color:var(--rmbz-text-faint, #888);">' +
                                                  (t.artist_name || t.artist_telemovel || '—') + ' · ISRC: ' + (t.isrc_code || '<em>sem ISRC</em>') +
                                                '</div></div>';
                                    });
                                    box.innerHTML = html;
                                    box.querySelectorAll('.rmbz-track-result').forEach(function(el) {
                                        el.addEventListener('click', function() {
                                            var aliasType = getSelectedType();
                                            var aliasValue = getSelectedValue();
                                            var typeLabel = getTypeLabel();
                                            // Confirmação clara: que tipo + que valor + para que faixa
                                            var trackName = el.querySelector('strong').textContent;
                                            if (!confirm('Mapear este ' + typeLabel + ' do CSV (' + aliasValue + ') para a faixa "' + trackName + '"?\n\nEsta atribuição persiste para todos os imports futuros.')) return;
                                            var fd2 = new FormData();
                                            fd2.append('action', 'rmbz_save_isrc_mapping');
                                            fd2.append('csv_isrc', aliasValue);   // nome legado mantido para compat backend
                                            fd2.append('alias_type', aliasType);  // nova bandeira que diz "isrc" ou "upc"
                                            fd2.append('track_id', el.dataset.trackId);
                                            fd2.append('_nonce', '<?php echo wp_create_nonce('rmbz_map_isrc'); ?>');
                                            fetch('<?php echo admin_url('admin-ajax.php'); ?>', { method:'POST', body:fd2, credentials:'same-origin' })
                                                .then(function(r){ return r.json(); })
                                                .then(function(res2){
                                                    if (res2.success) {
                                                        alert('✓ ' + typeLabel + ' mapeado com sucesso. Recarrega a página para ver o resultado aplicado.');
                                                        modal.remove();
                                                    } else {
                                                        alert('Erro: ' + ((res2.data && res2.data.msg) || 'desconhecido'));
                                                    }
                                                });
                                        });
                                    });
                                });
                        }, 300);
                    });
                };

                // Manter alias antigo para retro-compatibilidade (caso alguma parte do código ainda chame pelo nome antigo)
                window.rmbzOpenIsrcMapModal = function(isrc, title, artist, sourceBtn) {
                    rmbzOpenAliasMapModal(isrc, '', title, artist, sourceBtn);
                };
            })();
            </script>

            <style>
            .rmbz-isrc-map-overlay { position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:99999; display:flex; align-items:center; justify-content:center; }
            .rmbz-isrc-map-box { background:var(--rmbz-bg-card, #fff); border-radius:10px; padding:24px; max-width:600px; width:90%; max-height:80vh; overflow-y:auto; box-shadow:0 8px 24px rgba(0,0,0,0.2); }
            .rmbz-track-result:hover { background:#f5faff; }
            </style>
        <?php endif; ?>

        <?php if ( $already_imported ): ?>
            <div class="notice notice-warning" style="margin:16px 0; padding:12px 16px; border-left-width:4px;">
                <strong>⚠ Ficheiro já importado anteriormente</strong>
                <p style="margin:4px 0 0 0;">Este ficheiro (hash: <code><?php echo substr($file_hash, 0, 12); ?></code>) foi processado antes. Se prosseguires, os valores serão creditados em duplicado. Confirma se é mesmo isto que queres.</p>
            </div>
        <?php endif; ?>

        <form method="post" action="<?php echo admin_url('admin-post.php'); ?>" class="rmbz-iv-form" id="rmbz-iv-final-form">
            <input type="hidden" name="action" value="rmbz_processar_importacao_final">
            <input type="hidden" name="temp_file" value="<?php echo esc_attr($temp_filename); ?>">
            <input type="hidden" name="profile_id" value="<?php echo esc_attr($profile_id); ?>">
            <?php wp_nonce_field('rmbz_import_final_nonce'); ?>

            <div class="rmbz-iv-card" style="margin-bottom:12px; border-left:3px solid #f0b90b;">
                <div class="rmbz-iv-card-head"><strong>📦 Destino dos não-selecionados</strong></div>
                <p style="margin:0 0 12px 0; font-size:12px; color:var(--rmbz-text-muted, #666);">
                    O que fazer com as faixas que <strong>desseleccionaste</strong> na tabela acima?
                </p>
                <label style="display:block; margin-bottom:8px; cursor:pointer;">
                    <input type="radio" name="unselected_destination" value="unclaimed" checked>
                    <strong>Mandar para Não Reclamado</strong>
                    <span style="color:var(--rmbz-text-faint, #888); font-size:11px;">— ficam visíveis na <a href="?page=rmbz-admin-distribution&tab=unclaimed">página de Não Reclamados</a> para serem reclamadas mais tarde</span>
                </label>
                <label style="display:block; cursor:pointer;">
                    <input type="radio" name="unselected_destination" value="exclude">
                    <strong>Excluir totalmente</strong>
                    <span style="color:var(--rmbz-text-faint, #888); font-size:11px;">— ignorar definitivamente, não guardar em lado nenhum</span>
                </label>
            </div>

            <div class="rmbz-iv-config">
                <div class="rmbz-iv-card rmbz-impcfg">
                    <div class="rmbz-iv-card-head"><strong>⚙️ Configuração da importação</strong></div>
                    <div class="rmbz-impcfg-grid">
                        <div class="rmbz-impcfg-field">
                            <label>Fonte / Distribuidora</label>
                            <?php
                            // [1.5.175] Lista dinâmica vinda dos perfis em vez de hardcoded.
                            $source_options = [
                                'Amadea Music', 'TuneCore', 'DistroKid', 'CD Baby',
                                'ONErpm', 'Zebralution', 'The Orchard', 'Outra',
                            ];
                            $default_source = 'Amadea Music';
                            if ( isset($profile['distributor']) && in_array($profile['distributor'], $source_options, true) ) {
                                $default_source = $profile['distributor'];
                            }
                            ?>
                            <select name="source_name" class="widefat">
                                <?php foreach ( $source_options as $opt ): ?>
                                    <option value="<?php echo esc_attr($opt); ?>" <?php selected($default_source, $opt); ?>><?php echo esc_html($opt); ?></option>
                                <?php endforeach; ?>
                            </select>
                        </div>

                        <div class="rmbz-impcfg-field">
                            <label>Mês do relatório</label>
                            <input type="month" name="reporting_period" required class="widefat"
                                   value="<?php echo $date_max ? date('Y-m', $date_max) : ($date_min ? date('Y-m', $date_min) : date('Y-m', strtotime('-1 month'))); ?>">
                            <?php if ( $date_min && $date_max ): ?>
                                <?php if ( date('Y-m', $date_min) === date('Y-m', $date_max) ): ?>
                                    <p class="rmbz-impcfg-hint ok">✓ Detectado automaticamente no CSV</p>
                                <?php else: ?>
                                    <p class="rmbz-impcfg-hint info">
                                        ℹ CSV cobre <strong><?php echo date('M Y', $date_min); ?> → <?php echo date('M Y', $date_max); ?></strong>.
                                        Sugerido: <strong><?php echo date('M Y', $date_max); ?></strong>. Cada faixa fica com a sua data real.
                                    </p>
                                <?php endif; ?>
                            <?php else: ?>
                                <p class="rmbz-impcfg-hint">ℹ Não foi possível detectar — verifica o mês</p>
                            <?php endif; ?>
                        </div>

                        <div class="rmbz-impcfg-field">
                            <label>Moeda original</label>
                            <select name="original_currency" id="currency_selector" class="widefat" onchange="toggleRate()">
                                <option value="USD" <?php selected($detected_currency, 'USD'); ?>>USD (Dólar)</option>
                                <option value="EUR" <?php selected($detected_currency, 'EUR'); ?>>EUR (Euro)</option>
                                <option value="GBP" <?php selected($detected_currency, 'GBP'); ?>>GBP (Libra)</option>
                                <option value="BRL" <?php selected($detected_currency, 'BRL'); ?>>BRL (Real)</option>
                                <option value="ZAR" <?php selected($detected_currency, 'ZAR'); ?>>ZAR (Rand)</option>
                                <option value="MZN" <?php selected($detected_currency, 'MZN'); ?>>MZN (Metical)</option>
                            </select>
                            <?php if ( $detected_currency !== 'USD' ): ?>
                                <p class="rmbz-impcfg-hint ok">✓ Detectada no CSV</p>
                            <?php endif; ?>
                        </div>

                        <div class="rmbz-impcfg-field" id="rate_row" style="display:<?php echo $detected_currency === 'USD' ? 'none' : 'flex'; ?>;">
                            <label>Taxa de câmbio (→ USD)</label>
                            <input type="number" name="exchange_rate" id="exchange_rate_input" value="<?php echo esc_attr( $rate ); ?>" step="0.0001" class="widefat" oninput="updateConversionPreview()">
                            <p class="rmbz-impcfg-hint">
                                1 <?php echo esc_html($detected_currency); ?> = <span id="rate_display"><?php echo number_format($rate, 4); ?></span> USD
                                · <strong><?php echo esc_html($cur_symbol); ?><?php echo number_format($total_money, 2); ?> → $<span id="usd_preview"><?php echo number_format($total_usd, 2); ?></span></strong>
                            </p>
                        </div>
                    </div>
                </div>

                <div class="rmbz-iv-card">
                    <div class="rmbz-iv-card-head"><strong>📋 Amostra dos dados (5 primeiras linhas)</strong></div>
                    <div class="rmbz-imp-sample" style="overflow-x:auto;">
                        <table class="widefat striped" style="font-size:10px; margin:0;">
                            <thead>
                                <tr>
                                    <?php foreach ( $header as $h ) echo '<th>' . esc_html($h) . '</th>'; ?>
                                </tr>
                            </thead>
                            <tbody>
                                <?php foreach ( $preview_rows as $r ): ?>
                                    <tr>
                                        <?php
                                        // [DS 1.5.99] Antes truncava em 30 chars sem aviso.
                                        // Agora 100 chars + tooltip com valor completo
                                        // para o admin poder ver tudo se precisar.
                                        foreach ( $r as $c ):
                                            $full = (string) $c;
                                            $is_truncated = mb_strlen($full) > 100;
                                            $shown = $is_truncated ? mb_substr($full, 0, 100) . '…' : $full;
                                        ?>
                                            <td <?php if ($is_truncated): ?>title="<?php echo esc_attr($full); ?>" style="cursor:help;"<?php endif; ?>>
                                                <?php echo esc_html($shown); ?>
                                            </td>
                                        <?php endforeach; ?>
                                    </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>

            <div class="rmbz-iv-actions">
                <a href="?page=rmbz-admin-distribution&tab=import" class="button button-large">← Cancelar</a>
                <button type="submit" class="button button-primary button-hero rmbz-iv-btn-confirm" id="rmbz-iv-confirm-btn">
                    ✓ Confirmar e distribuir
                    <strong id="rmbz-iv-amount"><?php echo esc_html($cur_symbol); ?><?php echo number_format($total_money, 2); ?></strong>
                    <?php if ( $detected_currency !== 'USD' ): ?>
                        <small id="rmbz-iv-amount-usd">($<?php echo number_format($total_usd, 2); ?>)</small>
                    <?php endif; ?>
                    <span id="rmbz-iv-amount-note" style="display:none; opacity:0.85; font-size:11px; font-weight:400; margin-left:8px;"></span>
                </button>
            </div>
            <?php
            // [DS 1.5.100] Pré-cálculos para o JS recalcular o total em tempo real.
            // Total e câmbio são fixos (vêm do CSV). O JS subtrai a soma dos
            // checkboxes desmarcados em vez de somar os marcados (mais rápido
            // quando quase tudo está marcado, que é o caso normal).
            ?>
            <script>
            (function() {
                var TOTAL_MONEY = <?php echo number_format($total_money, 4, '.', ''); ?>;
                var EXCHANGE_RATE = <?php echo number_format($rate, 6, '.', ''); ?>;
                var IS_NOT_USD = <?php echo $detected_currency !== 'USD' ? 'true' : 'false'; ?>;
                var CUR_SYMBOL = <?php echo wp_json_encode($cur_symbol); ?>;

                var btn = document.getElementById('rmbz-iv-confirm-btn');
                var amountEl = document.getElementById('rmbz-iv-amount');
                var amountUsdEl = document.getElementById('rmbz-iv-amount-usd');
                var noteEl = document.getElementById('rmbz-iv-amount-note');

                function fmt(n) {
                    return n.toLocaleString('en-US', {minimumFractionDigits: 2, maximumFractionDigits: 2});
                }

                function recalc() {
                    var allCbs = document.querySelectorAll('.rmbz-track-cb');
                    if (!allCbs.length) return;

                    var unselectedSum = 0;
                    var unselectedCount = 0;
                    allCbs.forEach(function(cb) {
                        if (!cb.checked) {
                            unselectedSum += parseFloat(cb.dataset.revenue || '0');
                            unselectedCount++;
                        }
                    });

                    var distributedSum = TOTAL_MONEY - unselectedSum;
                    if (distributedSum < 0) distributedSum = 0;

                    // Actualizar valor principal
                    amountEl.textContent = CUR_SYMBOL + fmt(distributedSum);
                    if (amountUsdEl && IS_NOT_USD) {
                        amountUsdEl.textContent = '($' + fmt(distributedSum * EXCHANGE_RATE) + ')';
                    }

                    // Nota explicativa quando há desmarcados
                    if (unselectedCount > 0) {
                        var dest = document.querySelector('input[name="unselected_destination"]:checked');
                        var destVal = dest ? dest.value : 'unclaimed';
                        var destLabel = destVal === 'exclude'
                            ? unselectedCount + ' excluída' + (unselectedCount === 1 ? '' : 's') + ' · ' + CUR_SYMBOL + fmt(unselectedSum)
                            : unselectedCount + ' para Não Reclamado · ' + CUR_SYMBOL + fmt(unselectedSum);
                        noteEl.textContent = '— ' + destLabel;
                        noteEl.style.display = 'inline';
                    } else {
                        noteEl.textContent = '';
                        noteEl.style.display = 'none';
                    }

                    // Desabilitar botão se tudo desmarcado (não há nada para distribuir)
                    var anyChecked = false;
                    allCbs.forEach(function(cb) { if (cb.checked) anyChecked = true; });
                    if (!anyChecked) {
                        btn.disabled = true;
                        btn.style.opacity = '0.5';
                        btn.style.cursor = 'not-allowed';
                    } else {
                        btn.disabled = false;
                        btn.style.opacity = '';
                        btn.style.cursor = '';
                    }
                }

                // Liga aos checkboxes (delegação para apanhar futuros adicionados via JS)
                document.addEventListener('change', function(e) {
                    if (e.target.classList && e.target.classList.contains('rmbz-track-cb')) {
                        recalc();
                    }
                    // Também reage ao radio do destino (muda a label da nota)
                    if (e.target.name === 'unselected_destination') {
                        recalc();
                    }
                    // Master toggle / botões de selecção em massa também disparam recalc
                    // (eles já mudam .checked dos cbs e disparam events em cadeia)
                });

                // Cálculo inicial (caso algum checkbox esteja desmarcado por default no futuro)
                recalc();
            })();
            </script>
        </form>

    </div>

    <style>
    .rmbz-import-v2 { max-width: 1400px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
    .rmbz-iv-head { display: flex; justify-content: space-between; align-items: flex-start; margin: 20px 0 24px 0; gap: 16px; flex-wrap: wrap; }
    .rmbz-iv-kicker { color: var(--rmbz-text-faint, #888); font-size: 10px; text-transform: uppercase; letter-spacing: 1.2px; margin-bottom: 2px; }
    .rmbz-iv-head h1 { font-size: 22px; color: var(--rmbz-text-strong, #222); margin: 0; font-weight: 500; }
    .rmbz-iv-pills { display: flex; gap: 6px; flex-wrap: wrap; }
    .rmbz-iv-pill { padding: 5px 12px; border-radius: 14px; font-size: 11px; font-weight: 500; white-space: nowrap; }
    .rmbz-iv-pill.neutral { background: var(--rmbz-bg-card, #fff); border: 1px solid #ddd; color: var(--rmbz-text-secondary, #555); }
    .rmbz-iv-pill.info { background: #eef7ff; border: 1px solid #3498db; color: #1a5490; }
    .rmbz-iv-pill.warning { background: #fff3cd; border: 1px solid #f0b90b; color: #856404; }

    .rmbz-iv-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 12px; margin-bottom: 16px; }
    .rmbz-iv-kpi { background: var(--rmbz-bg-card, #fff); border: 1px solid #e5e5e5; border-radius: 8px; padding: 14px 16px; border-left: 3px solid #ccc; }
    .rmbz-iv-kpi.green  { border-left-color: var(--rmbz-success, #10b981); }
    .rmbz-iv-kpi.blue   { border-left-color: var(--rmbz-info, #3b82f6); }
    .rmbz-iv-kpi.purple { border-left-color: var(--rmbz-accent, #a855f7); }
    .rmbz-iv-kpi.red    { border-left-color: var(--rmbz-danger, #ef4444); }
    .rmbz-iv-kpi .lbl { font-size: 10px; color: var(--rmbz-text-faint, #888); text-transform: uppercase; letter-spacing: 0.3px; font-weight: 600; }
    .rmbz-iv-kpi .val { font-size: 26px; font-weight: 500; color: var(--rmbz-text-strong, #222); margin: 6px 0 2px 0; line-height: 1.1; }
    .rmbz-iv-kpi.green .val { color: var(--rmbz-success-strong, #059669); }
    .rmbz-iv-kpi.red .val   { color: var(--rmbz-danger-strong, #b91c1c); }
    .rmbz-iv-kpi .sub { font-size: 11px; color: var(--rmbz-text-muted, #666); }

    .rmbz-iv-grid-3-2 { display: grid; grid-template-columns: 3fr 2fr; gap: 12px; margin-bottom: 16px; }
    @media (max-width: 900px) { .rmbz-iv-grid-3-2 { grid-template-columns: 1fr; } }

    .rmbz-iv-card { background: var(--rmbz-bg-card, #fff); border: 1px solid #e5e5e5; border-radius: 8px; padding: 14px 16px; margin-bottom: 12px; }
    .rmbz-iv-card-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid #f0f0f0; }
    .rmbz-iv-card-head strong { font-size: 13px; color: var(--rmbz-text-strong, #222); }
    .rmbz-iv-card-head span { font-size: 11px; color: var(--rmbz-text-faint, #888); }

    .rmbz-iv-stores .store-row { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
    .rmbz-iv-stores .store-icon { width: 26px; height: 26px; border-radius: 5px; display: flex; align-items: center; justify-content: center; color: var(--rmbz-text-on-color, #fff); font-size: 12px; font-weight: 700; flex-shrink: 0; }
    .rmbz-iv-stores .store-body { flex: 1; min-width: 0; }
    .rmbz-iv-stores .store-top { display: flex; justify-content: space-between; align-items: baseline; font-size: 12px; color: var(--rmbz-text-strong, #222); margin-bottom: 3px; }
    .rmbz-iv-stores .store-top .name { font-weight: 500; }
    .rmbz-iv-stores .store-top .val { font-weight: 500; font-variant-numeric: tabular-nums; }
    .rmbz-iv-stores .store-top small { color: var(--rmbz-text-faint, #888); font-weight: 400; }
    .rmbz-iv-stores .store-bar { height: 5px; background: #f0f0f0; border-radius: 3px; overflow: hidden; }
    .rmbz-iv-stores .store-bar .fill { height: 100%; min-width: 2px; transition: width 0.4s ease; }
    .rmbz-iv-stores .store-sub { font-size: 10px; color: var(--rmbz-text-faint, #888); margin-top: 3px; }

    .rmbz-iv-countries .country-row { display: grid; grid-template-columns: 24px 30px 1fr auto; gap: 8px; align-items: center; padding: 5px 0; font-size: 12px; color: var(--rmbz-text-strong, #222); border-bottom: 1px solid #f5f5f5; }
    .rmbz-iv-countries .country-row:last-child { border-bottom: none; }
    .rmbz-iv-countries .country-row.others { color: var(--rmbz-text-faint, #888); }
    .rmbz-iv-countries .flag { font-size: 18px; line-height: 1; }
    .rmbz-iv-countries .code { font-family: monospace; font-size: 10px; color: var(--rmbz-text-faint, #888); text-transform: uppercase; }
    .rmbz-iv-countries .name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .rmbz-iv-countries .val { font-weight: 500; font-variant-numeric: tabular-nums; color: var(--rmbz-text-primary, #444); }

    .rmbz-iv-table { width: 100%; border-collapse: collapse; font-size: 12px; }
    .rmbz-iv-table th { text-align: left; padding: 8px 10px; background: #fafafa; color: var(--rmbz-text-muted, #666); font-size: 10px; text-transform: uppercase; letter-spacing: 0.3px; font-weight: 600; border-bottom: 1px solid #e5e5e5; }
    .rmbz-iv-table td { padding: 10px; border-bottom: 1px solid #f0f0f0; vertical-align: top; }
    .rmbz-iv-table tr:hover td { background: #fafbfc; }
    .rmbz-iv-table td strong { color: var(--rmbz-text-strong, #222); }
    .rmbz-iv-table td .muted { color: var(--rmbz-text-faint, #888); font-size: 11px; margin-top: 2px; }
    .rmbz-iv-table td code { background: #f5f5f5; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-family: monospace; }
    .rmbz-iv-table .status-pill { padding: 3px 10px; border-radius: 10px; font-size: 10px; font-weight: 600; white-space: nowrap; }
    .rmbz-iv-table .status-pill.linked { background: #d4edda; color: #155724; }
    .rmbz-iv-table .status-pill.unlinked { background: #fff3cd; color: #856404; }

    .rmbz-iv-hint { margin-top: 12px; padding: 10px 14px; background: #eef7ff; border-radius: 6px; font-size: 12px; color: #1a5490; border-left: 3px solid #3498db; }

    .rmbz-commission-cascade { display: flex; flex-direction: column; gap: 6px; margin-top: 4px; }
    .rmbz-commission-cascade .cc-row { display: flex; align-items: center; gap: 12px; }
    .rmbz-commission-cascade .cc-lbl { flex: 0 0 180px; font-size: 12px; color: var(--rmbz-text-primary, #444); }
    .rmbz-commission-cascade .cc-bar { height: 32px; border-radius: 5px; display: flex; align-items: center; padding: 0 12px; font-size: 13px; font-weight: 500; color: var(--rmbz-text-primary, #444); white-space: nowrap; min-width: 60px; transition: width 0.4s ease; }
    .rmbz-commission-cascade .cc-bar small { opacity: 0.8; font-weight: 400; font-size: 11px; margin-left: 4px; }
    .cc-hint { margin-top: 12px; padding: 10px 14px; background: #faf7fd; border-radius: 6px; font-size: 12px; color: var(--rmbz-text-secondary, #555); border-left: 3px solid #9b59b6; line-height: 1.6; }
    @media (max-width: 720px) {
        .rmbz-commission-cascade .cc-row { flex-direction: column; align-items: stretch; gap: 4px; }
        .rmbz-commission-cascade .cc-lbl { flex: none; }
    }
    .rmbz-iv-hint a { color: #1a5490; font-weight: 600; }

    .rmbz-iv-config { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-bottom: 16px; }
    @media (max-width: 900px) { .rmbz-iv-config { grid-template-columns: 1fr; } }

    .rmbz-iv-actions { background: var(--rmbz-bg-card, #fff); border: 1px solid #e5e5e5; border-radius: 8px; padding: 14px; display: flex; justify-content: flex-end; gap: 10px; align-items: center; }
    .rmbz-iv-btn-confirm { background: #2ecc71 !important; border-color: #27ae60 !important; color: #fff !important; }
    .rmbz-iv-btn-confirm:hover { background: #27ae60 !important; }
    .rmbz-iv-btn-confirm strong { margin-left: 8px; }
    .rmbz-iv-btn-confirm small { opacity: 0.85; font-size: 11px; margin-left: 4px; }

    /* ════════════════════ [DESIGN 2.0] CAMADA MATERIAL 3 ════════════════════
       Centra a página e moderniza por cima do estilo legado (vem por último). */
    .rmbz-import-v2 { margin-left: auto !important; margin-right: auto !important; animation: rmbz-iv-fade .4s cubic-bezier(.4,0,.2,1) both; }
    @keyframes rmbz-iv-fade { from { opacity: 0; } to { opacity: 1; } }
    @keyframes rmbz-iv-rise { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

    .rmbz-import-v2 .rmbz-iv-head h1 { font-weight: 800 !important; letter-spacing: -.01em; }
    .rmbz-import-v2 .rmbz-iv-kicker { font-weight: 700; }
    .rmbz-import-v2 .rmbz-iv-pill { border-radius: 999px !important; font-weight: 600 !important; }

    /* KPIs — cards M3 com hover-lift e entrada em cascata */
    .rmbz-import-v2 .rmbz-iv-kpi {
        border-radius: 16px !important; border: 1px solid #e6e8eb !important;
        box-shadow: 0 1px 3px rgba(16,24,40,.05) !important;
        animation: rmbz-iv-rise .5s cubic-bezier(.4,0,.2,1) both;
        transition: transform .18s cubic-bezier(.4,0,.2,1), box-shadow .18s cubic-bezier(.4,0,.2,1) !important;
    }
    .rmbz-import-v2 .rmbz-iv-kpi:nth-child(2) { animation-delay: .05s; }
    .rmbz-import-v2 .rmbz-iv-kpi:nth-child(3) { animation-delay: .1s; }
    .rmbz-import-v2 .rmbz-iv-kpi:nth-child(4) { animation-delay: .15s; }
    .rmbz-import-v2 .rmbz-iv-kpi:hover { transform: translateY(-3px); box-shadow: 0 12px 28px rgba(16,24,40,.1) !important; }
    .rmbz-import-v2 .rmbz-iv-kpi .val { font-weight: 900 !important; }

    /* Cards M3 */
    .rmbz-import-v2 .rmbz-iv-card,
    .rmbz-import-v2 .rmbz-iv-actions,
    .rmbz-import-v2 .rmbz-iv-reimport-banner,
    .rmbz-import-v2 .rmbz-iv-learned-section {
        border-radius: 18px !important; border: 1px solid #e6e8eb !important;
        box-shadow: 0 1px 3px rgba(16,24,40,.05) !important;
    }
    .rmbz-import-v2 .rmbz-iv-card-head { border-bottom-color: #eef0f3 !important; }
    .rmbz-import-v2 .rmbz-iv-card-head strong { font-weight: 800 !important; font-size: 13.5px !important; }

    /* Barras (lojas / cascata de comissão / receita) com animação de preenchimento */
    .rmbz-import-v2 .rmbz-iv-stores .store-bar { height: 7px !important; border-radius: 999px !important; background: #eef0f3 !important; }
    .rmbz-import-v2 .rmbz-iv-stores .store-bar .fill { border-radius: 999px !important; transform-origin: left; animation: rmbz-iv-fill .6s cubic-bezier(.4,0,.2,1) both; }
    .rmbz-import-v2 .rmbz-commission-cascade .cc-bar { border-radius: 10px !important; transform-origin: left; animation: rmbz-iv-fill .6s cubic-bezier(.4,0,.2,1) both; }
    @keyframes rmbz-iv-fill { from { transform: scaleX(0); } to { transform: scaleX(1); } }
    .rmbz-import-v2 .rmbz-iv-stores .store-icon { border-radius: 8px !important; box-shadow: 0 2px 6px rgba(16,24,40,.14); }

    /* Linhas de loja / país com hover suave */
    .rmbz-import-v2 .rmbz-iv-stores .store-row { padding: 6px 8px; border-radius: 12px; transition: background .15s; }
    .rmbz-import-v2 .rmbz-iv-stores .store-row:hover { background: #f7f8fa; }
    .rmbz-import-v2 .rmbz-iv-countries .country-row { padding: 6px 8px !important; border-radius: 10px; border-bottom: none !important; transition: background .15s; }
    .rmbz-import-v2 .rmbz-iv-countries .country-row:hover { background: #f7f8fa; }
    .rmbz-import-v2 .rmbz-iv-countries .flag img { width: 24px; height: 18px; border-radius: 3px; box-shadow: 0 1px 3px rgba(0,0,0,.18); object-fit: cover; vertical-align: middle; }

    /* Tabelas (fontes de monetização, mapeamento) */
    .rmbz-import-v2 .rmbz-iv-table { font-size: 12.5px; }
    .rmbz-import-v2 .rmbz-iv-table th { background: #fafbfc !important; border-bottom-color: #e6e8eb !important; }
    .rmbz-import-v2 .rmbz-iv-table td { border-bottom-color: #f0f1f3 !important; }
    .rmbz-import-v2 .rmbz-iv-table tr:hover td { background: #f7f8fa !important; }
    .rmbz-import-v2 .rmbz-iv-table .status-pill { border-radius: 999px !important; }

    /* Botões */
    .rmbz-import-v2 .button { border-radius: 11px !important; transition: transform .1s, filter .15s, box-shadow .2s !important; }
    .rmbz-import-v2 .button:active { transform: scale(.97); }
    .rmbz-import-v2 .rmbz-iv-btn-confirm {
        background: linear-gradient(135deg,#2ecc71,#1fa355) !important; border: 0 !important;
        box-shadow: 0 4px 14px rgba(46,204,113,.32) !important; border-radius: 12px !important;
    }
    .rmbz-import-v2 .rmbz-iv-btn-confirm:hover { filter: brightness(1.05); }

    /* Barra de ações fica colada ao fundo para confirmar sem rolar */
    .rmbz-import-v2 .rmbz-iv-actions {
        position: sticky; bottom: 14px; z-index: 5;
        backdrop-filter: blur(6px); background: rgba(255,255,255,.92) !important;
    }

    /* Config EM CIMA (full-width) e Amostra EM BAIXO — empilhadas */
    .rmbz-import-v2 .rmbz-iv-config { grid-template-columns: 1fr !important; }
    .rmbz-import-v2 .rmbz-iv-config > .rmbz-iv-card { min-width: 0; } /* deixa o overflow-x:auto da amostra funcionar */

    /* Configuração — grelha horizontal de campos Material 3 */
    .rmbz-impcfg-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 16px; }
    .rmbz-impcfg-field { display: flex; flex-direction: column; gap: 6px; }
    .rmbz-impcfg-field > label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: #6b7280; }
    .rmbz-impcfg-field select.widefat,
    .rmbz-impcfg-field input.widefat {
        border-radius: 10px !important; border: 1px solid #d8dce1 !important;
        padding: 9px 11px !important; font-size: 13px !important; box-shadow: none !important;
        transition: border-color .15s, box-shadow .15s;
    }
    .rmbz-impcfg-field select:focus, .rmbz-impcfg-field input:focus {
        border-color: #6356E5 !important; box-shadow: 0 0 0 3px rgba(99,86,229,.14) !important; outline: none;
    }
    .rmbz-impcfg-hint { margin: 0; font-size: 11px; color: #8a909a; line-height: 1.45; }
    .rmbz-impcfg-hint.ok { color: #08894e; }
    .rmbz-impcfg-hint.info { color: #1849a9; }
    .rmbz-impcfg-hint strong { font-weight: 700; }

    /* Amostra dos dados — contida, com scroll horizontal próprio */
    .rmbz-imp-sample { border: 1px solid #eef0f3; border-radius: 12px; max-width: 100%; }
    .rmbz-imp-sample table.widefat { margin: 0; border: 0; }
    .rmbz-imp-sample th { white-space: nowrap; background: #fafbfc !important; }
    .rmbz-imp-sample td { white-space: nowrap; }
    .rmbz-imp-sample::-webkit-scrollbar { height: 9px; }
    .rmbz-imp-sample::-webkit-scrollbar-thumb { background: #cdd2da; border-radius: 999px; }
    .rmbz-imp-sample::-webkit-scrollbar-track { background: transparent; }
    </style>

    <script>
    function toggleRate() {
        const sel = document.getElementById('currency_selector');
        const row = document.getElementById('rate_row');
        row.style.display = (sel.value === 'USD') ? 'none' : 'flex';
    }
    function updateConversionPreview() {
        const rate = parseFloat(document.getElementById('exchange_rate_input').value) || 0;
        const total = <?php echo number_format($total_money, 4, '.', ''); ?>;
        const disp = document.getElementById('rate_display');
        const usd  = document.getElementById('usd_preview');
        if (disp) disp.innerText = rate.toFixed(4);
        if (usd)  usd.innerText  = (total * rate).toLocaleString('pt-PT', {minimumFractionDigits:2, maximumFractionDigits:2});
    }
    </script>
    <?php
}

/* ============================================================================
 * HELPERS — ícones de loja, bandeiras, nomes de países e meses
 * ============================================================================ */

/* ============================================================================
 * AGGREGATE PREVIEW — para Data Reports sem ISRC (ex: TuneCore Data Report)
 * ============================================================================ */
function rmbz_render_aggregate_preview( $target_file, $temp_filename, $header, $header_lower, $profile, $already_imported, $file_hash, $file ) {
    $handle = fopen($target_file, 'r');
    fgetcsv($handle); // skip header

    $idx_date    = array_search('date', $header_lower);
    $idx_streams = array_search('streams', $header_lower);
    $idx_songs   = array_search('songs sold', $header_lower);
    $idx_releases = array_search('releases sold', $header_lower);
    $idx_total   = array_search('total earned', $header_lower);
    if ( $idx_total === false ) $idx_total = array_search('earnings', $header_lower);

    $months = [];
    $total_all = 0.0;
    $streams_all = 0;
    $songs_all = 0;

    while ( ($row = fgetcsv($handle)) !== FALSE ) {
        if ( ! is_array($row) || empty($row[$idx_date] ?? '') ) continue;
        $ts = strtotime($row[$idx_date]);
        if ( ! $ts ) continue;
        $val = (float) str_replace([',','$'], ['.',''], (string)($row[$idx_total] ?? '0'));
        if ( $val <= 0 ) continue;

        $streams = $idx_streams !== false ? (int) ($row[$idx_streams] ?? 0) : 0;
        $songs   = $idx_songs !== false ? (int) ($row[$idx_songs] ?? 0) : 0;
        $releases = $idx_releases !== false ? (int) ($row[$idx_releases] ?? 0) : 0;

        $months[] = [
            'month_key'   => date('Y-m-01', $ts),
            'month_label' => rmbz_fmt_month_year_pt($ts),
            'total'       => $val,
            'streams'     => $streams,
            'songs_sold'  => $songs,
            'releases'    => $releases,
        ];
        $total_all += $val;
        $streams_all += $streams;
        $songs_all += $songs;
    }
    fclose($handle);

    usort($months, function($a, $b){ return strcmp($b['month_key'], $a['month_key']); });
    ?>

    <div class="wrap rmbz-import-v2">

        <div class="rmbz-iv-head">
            <div>
                <div class="rmbz-iv-kicker">Distribuição Digital · Importar</div>
                <h1>Pré-análise — <?php echo esc_html($profile['name']); ?></h1>
            </div>
            <div class="rmbz-iv-pills">
                <span class="rmbz-iv-pill neutral">📄 <?php echo esc_html(basename($file['name'])); ?></span>
                <span class="rmbz-iv-pill info" style="background: <?php echo esc_attr($profile['badge_color']); ?>; color:var(--rmbz-text-on-color, #fff); border-color: <?php echo esc_attr($profile['badge_color']); ?>;">
                    <?php echo esc_html($profile['badge_initial']); ?> <?php echo esc_html($profile['short']); ?>
                </span>
                <span class="rmbz-iv-pill warning">⚠ Sem ISRC · agregado mensal</span>
                <?php if ( $already_imported ): ?>
                    <span class="rmbz-iv-pill warning">⚠ Já importado antes</span>
                <?php endif; ?>
            </div>
        </div>

        <div class="notice notice-warning" style="margin:0 0 20px 0; padding: 14px 18px; border-left-width: 4px;">
            <h3 style="margin: 0 0 6px 0; color: #856404; font-size: 14px;">⚠ Relatório agregado — sem informação por faixa</h3>
            <p style="margin: 0; font-size: 13px; color: var(--rmbz-text-muted, #666);">
                Este tipo de relatório do <strong><?php echo esc_html($profile['distributor']); ?></strong> só tem totais mensais.
                Sem ISRC por linha, <strong>não é possível distribuir automaticamente pelos artistas</strong>.
                Cada mês será criado como uma entrada no <strong>Black Box</strong> para distribuição manual.
            </p>
            <p style="margin: 8px 0 0 0; font-size: 12px; color: var(--rmbz-text-muted, #666);">
                💡 <strong>Solução ideal:</strong> pedir ao <?php echo esc_html($profile['distributor']); ?> o relatório por faixa (Track Report) que inclui ISRC e detalhes de artista.
            </p>
        </div>

        <div class="rmbz-iv-kpis">
            <div class="rmbz-iv-kpi green">
                <div class="lbl">Receita Total</div>
                <div class="val">$<?php echo number_format($total_all, 2); ?></div>
                <div class="sub">USD · <?php echo count($months); ?> meses</div>
            </div>
            <div class="rmbz-iv-kpi blue">
                <div class="lbl">Streams totais</div>
                <div class="val"><?php echo rmbz_fmt_compact($streams_all); ?></div>
                <div class="sub">agregado em todos os meses</div>
            </div>
            <div class="rmbz-iv-kpi purple">
                <div class="lbl">Músicas vendidas</div>
                <div class="val"><?php echo number_format($songs_all); ?></div>
                <div class="sub">compras individuais</div>
            </div>
            <div class="rmbz-iv-kpi red">
                <div class="lbl">Entradas Black Box</div>
                <div class="val"><?php echo count($months); ?></div>
                <div class="sub">1 por mês · carecem distribuição</div>
            </div>
        </div>

        <div class="rmbz-iv-card">
            <div class="rmbz-iv-card-head">
                <strong>Detalhe por mês (vai para o Black Box)</strong>
                <span><?php echo count($months); ?> registo(s)</span>
            </div>
            <table class="rmbz-iv-table">
                <thead>
                    <tr>
                        <th>Período</th>
                        <th style="text-align:right;">Streams</th>
                        <th style="text-align:right;">Músicas</th>
                        <th style="text-align:right;">Receita</th>
                        <th style="text-align:center;">Após importar</th>
                    </tr>
                </thead>
                <tbody>
                <?php foreach ( $months as $m ): ?>
                    <tr>
                        <td><strong><?php echo esc_html($m['month_label']); ?></strong></td>
                        <td style="text-align:right;"><?php echo $m['streams'] > 0 ? number_format($m['streams']) : '—'; ?></td>
                        <td style="text-align:right;"><?php echo $m['songs_sold'] > 0 ? number_format($m['songs_sold']) : '—'; ?></td>
                        <td style="text-align:right;"><strong>$<?php echo number_format($m['total'], 2); ?></strong></td>
                        <td style="text-align:center;">
                            <span class="status-pill unlinked">→ Black Box</span>
                        </td>
                    </tr>
                <?php endforeach; ?>
                </tbody>
            </table>
        </div>

        <?php if ( $already_imported ): ?>
            <div class="notice notice-warning" style="margin:16px 0; padding:12px 16px;">
                <strong>⚠ Ficheiro já importado antes</strong>
                <p style="margin:4px 0 0 0;">Hash: <code><?php echo substr($file_hash, 0, 12); ?></code>. Re-importar cria entradas duplicadas.</p>
            </div>
        <?php endif; ?>

        <form method="post" action="<?php echo admin_url('admin-post.php'); ?>" class="rmbz-iv-form">
            <input type="hidden" name="action" value="rmbz_processar_importacao_final">
            <input type="hidden" name="temp_file" value="<?php echo esc_attr($temp_filename); ?>">
            <input type="hidden" name="profile_id" value="<?php echo esc_attr($profile['id']); ?>">
            <input type="hidden" name="source_name" value="<?php echo esc_attr($profile['distributor']); ?>">
            <input type="hidden" name="reporting_period" value="<?php echo $months ? date('Y-m', strtotime($months[0]['month_key'])) : date('Y-m'); ?>">
            <input type="hidden" name="original_currency" value="<?php echo esc_attr($profile['currency']); ?>">
            <input type="hidden" name="exchange_rate" value="<?php echo esc_attr( rmbz_default_exchange_rate($profile['currency']) ); ?>">
            <?php wp_nonce_field('rmbz_import_final_nonce'); ?>

            <div class="rmbz-iv-actions">
                <a href="?page=rmbz-admin-distribution&tab=import" class="button button-large">← Cancelar</a>
                <button type="submit" class="button button-primary button-hero rmbz-iv-btn-confirm"
                        onclick="return confirm('Confirma importar <?php echo count($months); ?> meses para o Black Box? Total: $<?php echo number_format($total_all, 2); ?> USD. Depois de importar, vá ao separador Não Reclamados para distribuir manualmente.');">
                    ✓ Confirmar e enviar $<?php echo number_format($total_all, 2); ?> para Black Box
                </button>
            </div>
        </form>

    </div>
    <?php
}


function rmbz_store_icon_info( $partner_name ) {
    $n = strtolower( trim($partner_name) );
    $map = [
        'spotify'          => ['color' => '#1DB954', 'initial' => 'S'],
        'apple'            => ['color' => '#FC3C44', 'initial' => 'A'],
        'apple music'      => ['color' => '#FC3C44', 'initial' => 'A'],
        'itunes'           => ['color' => '#FC3C44', 'initial' => 'iT'],
        'youtube'          => ['color' => '#FF0000', 'initial' => 'Y'],
        'youtube music'    => ['color' => '#FF0000', 'initial' => 'YT'],
        'youtube content id' => ['color' => '#CC0000', 'initial' => 'YC'],
        'amazon'           => ['color' => '#00A8E1', 'initial' => 'a'],
        'amazon music'     => ['color' => '#00A8E1', 'initial' => 'a'],
        'tidal'            => ['color' => '#000000', 'initial' => 'T'],
        'deezer'           => ['color' => '#A238FF', 'initial' => 'D'],
        'boomplay'         => ['color' => '#00B46A', 'initial' => 'B'],
        'audiomack'        => ['color' => '#FFA500', 'initial' => 'Am'],
        'soundcloud'       => ['color' => '#FF5500', 'initial' => 'SC'],
        'pandora'          => ['color' => '#005483', 'initial' => 'P'],
        'napster'          => ['color' => '#2D2F31', 'initial' => 'N'],
        'anghami'          => ['color' => '#8A00FF', 'initial' => 'An'],
        'qobuz'            => ['color' => '#1A6DFF', 'initial' => 'Q'],
        'jiosaavn'         => ['color' => '#2BC8C8', 'initial' => 'J'],
        'gaana'            => ['color' => '#FF6B35', 'initial' => 'G'],
        'facebook'         => ['color' => '#1877F2', 'initial' => 'F'],
        'instagram'        => ['color' => '#E4405F', 'initial' => 'IG'],
        'tiktok'           => ['color' => '#FF0050', 'initial' => 'TT'],
        'kkbox'            => ['color' => '#009FE3', 'initial' => 'KK'],
        'claro musica'     => ['color' => '#E60000', 'initial' => 'CM'],
        'joox'             => ['color' => '#00D4C8', 'initial' => 'JX'],
    ];
    if ( isset($map[$n]) ) return $map[$n];
    foreach ( $map as $k => $v ) {
        if ( strpos($n, $k) !== false ) return $v;
    }
    $first = mb_substr( $partner_name, 0, 1 );
    $hash = crc32( strtolower($partner_name) );
    $colors = ['#e74c3c','#3498db','#9b59b6','#f39c12','#1abc9c','#34495e','#16a085','#d35400','#c0392b','#8e44ad'];
    return [
        'color'   => $colors[ abs($hash) % count($colors) ],
        'initial' => strtoupper($first ?: '?'),
    ];
}

function rmbz_country_flag_emoji( $country_code ) {
    $cc = strtoupper( trim($country_code) );
    if ( strlen($cc) !== 2 ) return '🏳️';
    $letter1 = ord($cc[0]) - ord('A') + 0x1F1E6;
    $letter2 = ord($cc[1]) - ord('A') + 0x1F1E6;
    if ( $letter1 < 0x1F1E6 || $letter1 > 0x1F1FF || $letter2 < 0x1F1E6 || $letter2 > 0x1F1FF ) return '🏳️';
    return mb_chr( $letter1, 'UTF-8' ) . mb_chr( $letter2, 'UTF-8' );
}

function rmbz_country_name_pt( $cc ) {
    $map = [
        'MZ' => 'Moçambique', 'PT' => 'Portugal', 'BR' => 'Brasil', 'AO' => 'Angola',
        'CV' => 'Cabo Verde', 'GW' => 'Guiné-Bissau', 'ST' => 'São Tomé',
        'US' => 'EUA', 'GB' => 'Reino Unido', 'ES' => 'Espanha', 'FR' => 'França',
        'DE' => 'Alemanha', 'IT' => 'Itália', 'NL' => 'Países Baixos', 'BE' => 'Bélgica',
        'CA' => 'Canadá', 'MX' => 'México', 'AR' => 'Argentina', 'CL' => 'Chile',
        'CO' => 'Colômbia', 'PE' => 'Peru', 'UY' => 'Uruguai', 'VE' => 'Venezuela',
        'ZA' => 'África do Sul', 'NG' => 'Nigéria', 'KE' => 'Quénia', 'GH' => 'Gana',
        'SN' => 'Senegal', 'CI' => 'Costa do Marfim', 'CD' => 'RD Congo', 'UG' => 'Uganda',
        'TZ' => 'Tanzânia', 'ET' => 'Etiópia', 'EG' => 'Egipto', 'MA' => 'Marrocos',
        'PH' => 'Filipinas', 'JP' => 'Japão', 'KR' => 'Coreia do Sul', 'CN' => 'China',
        'IN' => 'Índia', 'ID' => 'Indonésia', 'TH' => 'Tailândia', 'VN' => 'Vietname',
        'AU' => 'Austrália', 'NZ' => 'Nova Zelândia',
        'RU' => 'Rússia', 'TR' => 'Turquia', 'SA' => 'Arábia Saudita', 'AE' => 'Emirados',
        'SE' => 'Suécia', 'NO' => 'Noruega', 'DK' => 'Dinamarca', 'FI' => 'Finlândia',
        'PL' => 'Polónia', 'RO' => 'Roménia', 'CH' => 'Suíça', 'AT' => 'Áustria',
        'IE' => 'Irlanda', 'GR' => 'Grécia', 'CZ' => 'República Checa',
    ];
    return $map[ strtoupper($cc) ] ?? $cc;
}

function rmbz_month_name_pt( $month_num ) {
    $m = (int) $month_num;
    $names = ['', 'janeiro', 'fevereiro', 'março', 'abril', 'maio', 'junho',
              'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'];
    return $names[ $m ] ?? '';
}

function rmbz_currency_symbol( $cur ) {
    $map = ['USD'=>'$', 'EUR'=>'€', 'GBP'=>'£', 'BRL'=>'R$', 'ZAR'=>'R', 'MZN'=>'MT',
            'AOA'=>'Kz', 'CHF'=>'CHF ', 'JPY'=>'¥', 'CAD'=>'C$', 'AUD'=>'A$'];
    return $map[ strtoupper($cur) ] ?? '$';
}

function rmbz_fmt_compact( $n ) {
    $n = (int) $n;
    if ( $n >= 1000000 ) return number_format( $n / 1000000, 1 ) . 'M';
    if ( $n >= 1000 )    return number_format( $n / 1000, 1 ) . 'K';
    return number_format( $n );
}

/**
 * Taxa de câmbio sugerida por defeito (para USD).
 * Valores aproximados — o admin pode ajustar no form.
 */
function rmbz_default_exchange_rate( $currency ) {
    $rates = [
        'USD' => 1.0000,
        'EUR' => 1.0800,
        'GBP' => 1.2700,
        'BRL' => 0.2000,
        'ZAR' => 0.0550,
        'MZN' => 0.0157,
        'AOA' => 0.0011,
        'CHF' => 1.1400,
        'JPY' => 0.0067,
        'CAD' => 0.7400,
        'AUD' => 0.6600,
    ];
    return $rates[ strtoupper($currency) ] ?? 1.0000;
}


/* ============================================================================
 * [DS 1.5.94] CLASSIFICAÇÃO DE FONTES DE MONETIZAÇÃO
 * ============================================================================
 * Lojas como YouTube, Facebook e TikTok têm várias fontes de receita
 * (streaming normal vs monetização de UGC vs ads). O CSV vem com nomes
 * tipo "YouTube", "YouTube Content ID", "YouTube Music", "Facebook & Instagram",
 * etc. Esta função normaliza-os em chaves canónicas para o admin ver
 * de onde vem o dinheiro com clareza.
 * ──────────────────────────────────────────────────────────────────────── */

/**
 * Recebe nome de loja como vem no CSV e devolve chave canónica.
 * Mantém o nome original se não bater com nenhum padrão conhecido.
 */
function rmbz_classify_service_source( $store_name ) {
    $s = mb_strtolower( trim( (string) $store_name ) );
    if ( $s === '' ) return '(Sem fonte)';

    // YouTube — 3 fontes possíveis
    if ( strpos($s, 'youtube') !== false ) {
        if ( strpos($s, 'content id') !== false || strpos($s, 'contentid') !== false ) {
            return 'YouTube Content ID';
        }
        if ( strpos($s, 'music') !== false ) return 'YouTube Music';
        if ( strpos($s, 'ad') !== false || strpos($s, 'shorts') !== false ) return 'YouTube Ads/Shorts';
        return 'YouTube';
    }

    // Facebook / Instagram (Meta) — geralmente vem junto
    if ( strpos($s, 'facebook') !== false || strpos($s, 'instagram') !== false || strpos($s, 'meta') !== false || strpos($s, 'fb/ig') !== false ) {
        return 'Facebook / Instagram';
    }

    // TikTok monetização (separado de TikTok streaming normal)
    if ( strpos($s, 'tiktok') !== false ) {
        if ( strpos($s, 'monet') !== false || strpos($s, 'sef') !== false || strpos($s, 'commercial') !== false ) {
            return 'TikTok Monetization';
        }
        return 'TikTok';
    }

    // Outros DSPs comuns — devolve nome canónico
    if ( strpos($s, 'spotify') !== false ) return 'Spotify';
    if ( strpos($s, 'apple') !== false )   return 'Apple Music';
    if ( strpos($s, 'amazon') !== false )  return 'Amazon Music';
    if ( strpos($s, 'deezer') !== false )  return 'Deezer';
    if ( strpos($s, 'tidal') !== false )   return 'Tidal';
    if ( strpos($s, 'pandora') !== false ) return 'Pandora';
    if ( strpos($s, 'soundcloud') !== false ) return 'SoundCloud';
    if ( strpos($s, 'napster') !== false ) return 'Napster';
    if ( strpos($s, 'audiomack') !== false ) return 'Audiomack';
    if ( strpos($s, 'boomplay') !== false ) return 'Boomplay';

    // Caiu em nada — devolve original (capitalizado bonito)
    return ucwords( trim( (string) $store_name ) );
}

/**
 * Indica se uma fonte é "especial" (UGC/monetização) e merece destaque visual.
 * Estas são fontes onde o admin pode querer atenção extra (ex: Content ID
 * pode ter claims falsos, Meta tem regras diferentes, etc).
 */
function rmbz_is_special_service( $service_key ) {
    return in_array( $service_key, [
        'YouTube Content ID',
        'YouTube Ads/Shorts',
        'Facebook / Instagram',
        'TikTok Monetization',
    ], true );
}

