<?php
// includes/admin/royalties/royalties-imports.php
//
// Lista de importações CSV com acção "anular" (reversion híbrida).
// Reversion mecânica:
//   - ledger: marca reverted_at (soft delete) — preserva auditoria
//   - daily_stats: apaga (hard delete — analytics, não crítico)
//   - unclaimed: apaga entradas pendentes desse import (hard delete)
//   - platform_commissions: marca reverted_at
//   - stats: subtrai o total_earnings por artista
//   - import_logs: marca status='reverted'

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


function rmbz_render_royalties_imports() {
    global $wpdb;

    // Feedback de operações
    if ( isset($_GET['reverted']) && $_GET['reverted'] === '1' ) {
        echo '<div class="notice notice-success is-dismissible" style="margin-bottom:16px; border-left-color:var(--rmbz-success, #10b981);"><p><strong>✓ Importação anulada com sucesso.</strong> Todas as transacções foram revertidas e as wallets dos artistas actualizadas.</p></div>';
    }
    if ( isset($_GET['revert_error']) ) {
        echo '<div class="notice notice-error is-dismissible" style="margin-bottom:16px;"><p><strong>Erro:</strong> ' . esc_html(urldecode($_GET['revert_error'])) . '</p></div>';
    }
    if ( isset($_GET['approved']) && $_GET['approved'] === '1' ) {
        $n = isset($_GET['artists']) ? (int) $_GET['artists'] : (isset($_GET['n_artists']) ? (int) $_GET['n_artists'] : 0);
        echo '<div class="notice notice-success is-dismissible" style="margin-bottom:16px; border-left-color:var(--rmbz-success, #10b981);"><p><strong>✓ Importação aprovada!</strong> ' . $n . ' artista(s) passaram a ver o dinheiro nas suas wallets.</p></div>';
    }
    if ( isset($_GET['rejected']) && $_GET['rejected'] === '1' ) {
        echo '<div class="notice notice-success is-dismissible" style="margin-bottom:16px; border-left-color:var(--rmbz-brand, #f0b90b);"><p><strong>✓ Importação rejeitada.</strong> Nenhum dinheiro chegou a ser creditado a artistas.</p></div>';
    }
    if ( isset($_GET['approve_error']) ) {
        echo '<div class="notice notice-error is-dismissible" style="margin-bottom:16px;"><p><strong>Erro:</strong> ' . esc_html(urldecode($_GET['approve_error'])) . '</p></div>';
    }
    if ( isset($_GET['cleanup_done']) && $_GET['cleanup_done'] === '1' ) {
        $debited = isset($_GET['debited']) ? (int) $_GET['debited'] : 0;
        echo '<div class="notice notice-success is-dismissible" style="margin-bottom:16px; border-left-color:var(--rmbz-success, #10b981);"><p><strong>✓ Limpeza forçada concluída.</strong> ' . $debited . ' wallet(s) debitada(s), linhas órfãs do daily_stats e ledger apagadas.</p></div>';
    }
    // [DS 1.5.108] Mensagem de erro ao desfazer anulação
    if ( isset($_GET['unrevert_error']) ) {
        echo '<div class="notice notice-error is-dismissible" style="margin-bottom:16px;"><p><strong>Erro ao desfazer anulação:</strong> ' . esc_html(urldecode($_GET['unrevert_error'])) . '</p></div>';
    }
    // [1.5.200] Mensagens de feedback para apagar
    if ( isset($_GET['deleted']) && $_GET['deleted'] === '1' ) {
        $rows = isset($_GET['rows']) ? (int) $_GET['rows'] : 0;
        echo '<div class="notice notice-success is-dismissible" style="margin-bottom:16px; border-left-color:var(--rmbz-success, #10b981);"><p><strong>✓ Importação apagada de vez.</strong> ' . $rows . ' registo(s) removidos da BD + CSV arquivado apagado. Esta operação é irreversível.</p></div>';
    }
    if ( isset($_GET['delete_error']) ) {
        echo '<div class="notice notice-error is-dismissible" style="margin-bottom:16px;"><p><strong>Erro ao apagar importação:</strong> ' . esc_html(urldecode($_GET['delete_error'])) . '</p></div>';
    }
    if ( isset($_GET['import_status']) && $_GET['import_status'] === 'pending_approval' ) {
        $new_hash = isset($_GET['new_hash']) ? substr(sanitize_text_field($_GET['new_hash']), 0, 12) : '';
        echo '<div class="notice notice-warning is-dismissible" style="margin-bottom:16px; border-left-color:var(--rmbz-brand, #f0b90b);"><p><strong>⏳ Importação pendente de aprovação!</strong> O CSV foi processado (' . (int)($_GET['processed'] ?? 0) . ' linhas) mas os artistas ainda NÃO vêem o dinheiro. Encontre a importação abaixo (' . esc_html($new_hash) . '...) e clique <strong>Aprovar</strong> para libertar.</p></div>';

        // [FIX 1.6.15] Aviso quando o servidor bloqueou re-importação de faixas
        // já processadas. Acontece se admin forçou checkbox via dev tools ou
        // se houve alguma falha no front-end e o cadeado não apareceu.
        $blocked = isset($_GET['blocked_duplicates']) ? (int) $_GET['blocked_duplicates'] : 0;
        if ( $blocked > 0 ) {
            echo '<div class="notice notice-info is-dismissible" style="margin-bottom:16px; border-left-color:#0073aa;"><p>'
                . '🔒 <strong>' . $blocked . ' faixa' . ($blocked === 1 ? '' : 's') . ' bloqueada' . ($blocked === 1 ? '' : 's') . ' por já ' . ($blocked === 1 ? 'ter' : 'terem') . ' sido importada' . ($blocked === 1 ? '' : 's')
                . '.</strong> O sistema protegeu automaticamente contra duplicação de royalties — só as faixas novas foram processadas.'
                . '</p></div>';
        }
    }

    $t_logs = $wpdb->prefix . 'rmbz_distro_import_logs';
    $t_ledger = $wpdb->prefix . 'rmbz_distro_ledger';
    $t_comm = $wpdb->prefix . 'rmbz_distro_platform_commissions';

    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_logs'") !== $t_logs ) {
        echo '<div class="notice notice-warning"><p>Tabela de logs ainda não existe. Faça pelo menos uma importação primeiro.</p></div>';
        return;
    }

    // Detectar se a coluna `approval_status` existe — precisamos disto
    // ANTES de construir o WHERE da query (linha ~60). Em versões antigas
    // do schema esta coluna não existe ainda.
    $cols_logs = $wpdb->get_col("SHOW COLUMNS FROM $t_logs");
    $has_approval = in_array('approval_status', (array) $cols_logs, true);

    // Filtros
    $f_distributor = isset($_GET['rim_dist']) ? sanitize_text_field($_GET['rim_dist']) : '';
    $f_status = isset($_GET['rim_status']) ? sanitize_text_field($_GET['rim_status']) : 'all';

    $where = ['1=1'];
    $params = [];
    if ( $f_distributor ) {
        $where[] = 'source_name = %s';
        $params[] = $f_distributor;
    }
    if ( $has_approval ) {
        if ( $f_status === 'pending' )   $where[] = "approval_status = 'pending_approval'";
        elseif ( $f_status === 'approved' ) $where[] = "approval_status = 'approved' AND (status IS NULL OR status = 'active')";
        elseif ( $f_status === 'rejected' ) $where[] = "approval_status = 'rejected'";
        elseif ( $f_status === 'reverted' ) $where[] = "status = 'reverted' AND approval_status != 'rejected'";
    } else {
        if ( $f_status === 'active' )       $where[] = "(status IS NULL OR status = 'active')";
        elseif ( $f_status === 'reverted' ) $where[] = "status = 'reverted'";
    }
    $where_sql = implode(' AND ', $where);

    $sql = "SELECT * FROM $t_logs WHERE $where_sql ORDER BY imported_at DESC LIMIT 100";
    $imports = $params ? $wpdb->get_results( $wpdb->prepare($sql, $params) ) : $wpdb->get_results($sql);

    // Distribuidoras disponíveis para o filtro
    $distributors = $wpdb->get_col("SELECT DISTINCT source_name FROM $t_logs ORDER BY source_name");

    // KPIs
    // ($cols_logs e $has_approval já foram detectados acima)

    $total_pending = $has_approval
        ? (int) $wpdb->get_var("SELECT COUNT(*) FROM $t_logs WHERE approval_status = 'pending_approval'")
        : 0;
    $total_approved = $has_approval
        ? (int) $wpdb->get_var("SELECT COUNT(*) FROM $t_logs WHERE approval_status = 'approved' AND (status IS NULL OR status = 'active')")
        : (int) $wpdb->get_var("SELECT COUNT(*) FROM $t_logs WHERE status IS NULL OR status = 'active'");
    $total_rejected = $has_approval
        ? (int) $wpdb->get_var("SELECT COUNT(*) FROM $t_logs WHERE approval_status = 'rejected'")
        : 0;
    $total_reverted = (int) $wpdb->get_var("SELECT COUNT(*) FROM $t_logs WHERE status = 'reverted'");

    $total_amount = 0.0;
    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_comm'") === $t_comm ) {
        $total_amount = (float) $wpdb->get_var("SELECT COALESCE(SUM(gross_amount_usd),0) FROM $t_comm WHERE reverted_at IS NULL");
    }
    ?>

    <div class="rim-kpis">
        <?php if ( $total_pending > 0 ): ?>
        <div class="rim-kpi rim-priority">
            <div class="lbl">⏳ Pendentes aprovação</div>
            <div class="val"><?php echo $total_pending; ?></div>
            <div class="sub">aguardam revisão do admin</div>
        </div>
        <?php endif; ?>
        <div class="rim-kpi">
            <div class="lbl">Aprovadas activas</div>
            <div class="val"><?php echo $total_approved; ?></div>
        </div>
        <div class="rim-kpi">
            <div class="lbl">Volume total</div>
            <div class="val">$<?php echo number_format($total_amount, 2); ?></div>
            <div class="sub">USD · acumulado</div>
        </div>
        <div class="rim-kpi">
            <div class="lbl">Rejeitadas/Anuladas</div>
            <div class="val"><?php echo $total_rejected + $total_reverted; ?></div>
            <div class="sub">em auditoria</div>
        </div>
    </div>

    <?php
    // [FEAT 1.6.12] CALENDÁRIO DE IMPORTS — uma linha por distribuidora ×
    // últimos 12 meses. Detecta lacunas (meses não importados) e permite
    // ver, ao relance, onde está dinheiro perdido por não importar.
    //
    // Critérios:
    //   - "Importado" se HÁ pelo menos 1 log para esse (distribuidora, mês)
    //     com status não-rejected E approval_status não-rejected.
    //   - "N/D" se a distribuidora ainda não tinha registos antes desse mês
    //     (o primeiro mês com import marca o início da distribuidora).
    //   - "Lacuna" se ENTRE o primeiro e o último import há um mês sem dados.
    //
    // [PERF] uma única query devolve todos os pares (source_name, period) com
    // amount + count. O resto é processamento em PHP.
    if ( ! empty( $imports ) || ! empty( $distributors ) ):

        // Janela: últimos 12 meses, do mais antigo (esq) ao mais recente (dir)
        $now = current_time('timestamp');
        $months_window = [];
        for ( $i = 11; $i >= 0; $i-- ) {
            $months_window[] = date('Y-m', strtotime("-{$i} months", $now));
        }

        // Query agregada: source_name × reporting_period → count + valor + log_ids
        // Aceita só status activos (não rejected/reverted).
        // [FIX 1.6.13] Buscar valores autoritativos da `platform_commissions`
        // (a mesma fonte que alimenta os cartões da lista e o KPI "Volume total").
        // A `import_logs.total_amount_usd` era usada antes mas pode estar a zero
        // em imports antigos por falta de preenchimento — não é fiável.
        //
        // Como `platform_commissions` não tem `source_name` directo mas tem
        // `distributor_name`, fazemos LEFT JOIN com import_logs para garantir
        // que a etiqueta da linha bate. Quando há vários logs do mesmo
        // (distributor_name, reporting_period), agregamos.
        $cal_where_status = $has_approval
            ? "((l.approval_status = 'approved' AND (l.status IS NULL OR l.status = 'active')) OR l.approval_status = 'pending_approval')"
            : "(l.status IS NULL OR l.status = 'active')";
        $cal_min_period = $months_window[0];

        // Query principal: junta commissions × logs por import_hash.
        // Soma gross_amount_usd (autoritativo).
        $cal_rows = $wpdb->get_results( $wpdb->prepare(
            "SELECT COALESCE(l.source_name, c.distributor_name) AS source_name,
                    c.reporting_period,
                    COUNT(DISTINCT l.id) AS imports_count,
                    COALESCE(SUM(c.gross_amount_usd), 0) AS total_amount,
                    MAX(l.id) AS sample_log_id
               FROM $t_comm c
          LEFT JOIN $t_logs l ON l.file_hash = c.import_hash
              WHERE c.reverted_at IS NULL
                AND c.reporting_period IS NOT NULL
                AND c.reporting_period != ''
                AND c.reporting_period >= %s
                AND ( l.id IS NULL OR $cal_where_status )
              GROUP BY source_name, c.reporting_period",
            $cal_min_period
        ) );

        // Estrutura: $cal_data[ source_name ][ 'YYYY-MM' ] = [ count, amount, log_id ]
        $cal_data = [];
        $cal_first_period_per_source = []; // primeira aparição de cada distribuidora globalmente
        foreach ( $cal_rows as $r ) {
            $src = $r->source_name;
            $per = $r->reporting_period;
            $cal_data[ $src ][ $per ] = [
                'count'  => (int) $r->imports_count,
                'amount' => (float) $r->total_amount,
                'log_id' => (int) $r->sample_log_id,
            ];
            if ( ! isset($cal_first_period_per_source[$src]) || $per < $cal_first_period_per_source[$src] ) {
                $cal_first_period_per_source[$src] = $per;
            }
        }

        // Para distribuidoras sem nenhum import nos últimos 12 meses, vamos
        // buscar o primeiro registo histórico para sabermos a partir de
        // quando contar como "lacuna" (vs N/D).
        $hist_min_rows = $wpdb->get_results(
            "SELECT source_name, MIN(reporting_period) AS first_period
               FROM $t_logs
              WHERE reporting_period IS NOT NULL AND reporting_period != ''
              GROUP BY source_name"
        );
        foreach ( $hist_min_rows as $h ) {
            if ( ! isset( $cal_first_period_per_source[ $h->source_name ] ) ) {
                $cal_first_period_per_source[ $h->source_name ] = $h->first_period;
            } else {
                // Se o primeiro histórico é mais antigo, prevalece
                if ( $h->first_period < $cal_first_period_per_source[ $h->source_name ] ) {
                    $cal_first_period_per_source[ $h->source_name ] = $h->first_period;
                }
            }
        }

        // Lista de distribuidoras a mostrar (todas as conhecidas, ordenadas por nome)
        $cal_distributors = array_keys( $cal_first_period_per_source );
        sort( $cal_distributors );

        // Contar lacunas globais para mostrar no KPI no header do calendário
        // [FIX] O mês actual NÃO conta como lacuna — ainda está a decorrer.
        $current_period = date('Y-m', $now);
        $gap_count = 0;
        $cal_total_amount = 0.0;
        foreach ( $cal_distributors as $src ) {
            $first_seen = $cal_first_period_per_source[$src] ?? null;
            foreach ( $months_window as $period ) {
                if ( ! empty($cal_data[$src][$period]) ) {
                    $cal_total_amount += (float) $cal_data[$src][$period]['amount'];
                }
                // Lacuna: distribuidora já existia + sem import + NÃO é o mês actual
                if ( $first_seen && $period >= $first_seen && empty($cal_data[$src][$period]) && $period !== $current_period ) {
                    $gap_count++;
                }
            }
        }

        // Nome PT-PT dos meses
        $month_short_pt = ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'];
    ?>
    <div class="rim-calendar">
        <div class="rim-cal-head">
            <div>
                <h2>📅 Calendário de Imports</h2>
                <p class="rim-cal-sub">
                    Últimos 12 meses · uma vista para detectar dinheiro em falta por não ter importado
                </p>
            </div>
            <div class="rim-cal-stats">
                <span class="rim-cal-total-badge" title="Total dos imports activos nos últimos 12 meses">
                    💰 $<?php echo number_format($cal_total_amount, 2); ?>
                </span>
                <?php if ( $gap_count > 0 ): ?>
                    <span class="rim-cal-gap-badge">⚠ <?php echo $gap_count; ?> lacuna<?php echo $gap_count === 1 ? '' : 's'; ?></span>
                <?php else: ?>
                    <span class="rim-cal-ok-badge">✓ Sem lacunas</span>
                <?php endif; ?>
            </div>
        </div>

        <div class="rim-cal-wrap">
            <table class="rim-cal-table">
                <thead>
                    <tr>
                        <th class="rim-cal-th-dist">Distribuidora</th>
                        <?php foreach ( $months_window as $period ):
                            [$yr, $mo] = explode('-', $period);
                            $mo_short = $month_short_pt[ ((int)$mo) - 1 ] ?? $mo;
                            $is_current = ( $period === date('Y-m', $now) );
                        ?>
                            <th class="rim-cal-th-month <?php echo $is_current ? 'is-current' : ''; ?>">
                                <span class="rim-cal-mo"><?php echo $mo_short; ?></span>
                                <span class="rim-cal-yr"><?php echo substr($yr, 2); ?></span>
                            </th>
                        <?php endforeach; ?>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach ( $cal_distributors as $src ):
                        $first_seen = $cal_first_period_per_source[$src] ?? null;
                    ?>
                        <tr>
                            <td class="rim-cal-td-dist">
                                <strong><?php echo esc_html( $src ?: '—' ); ?></strong>
                            </td>
                            <?php foreach ( $months_window as $period ):
                                $has = ! empty( $cal_data[$src][$period] );
                                $before_start = ( $first_seen && $period < $first_seen );
                                $is_current = ( $period === $current_period );

                                if ( $has ) {
                                    $cell = $cal_data[$src][$period];
                                    $class = 'rim-cal-cell-ok';
                                    $title = sprintf(
                                        '%s · %d import%s · $%s',
                                        $period,
                                        $cell['count'],
                                        $cell['count'] === 1 ? '' : 's',
                                        number_format($cell['amount'], 2)
                                    );
                                    $sym = '✓';
                                } elseif ( $before_start ) {
                                    $class = 'rim-cal-cell-na';
                                    $title = $period . ' · distribuidora ainda não existia';
                                    $sym = '·';
                                } elseif ( $is_current ) {
                                    // Mês actual sem import: ainda está a decorrer, não é lacuna
                                    $class = 'rim-cal-cell-pending';
                                    $title = $period . ' · mês actual em curso';
                                    $sym = '…';
                                } else {
                                    $class = 'rim-cal-cell-gap';
                                    $title = $period . ' · LACUNA — sem imports';
                                    $sym = '✗';
                                }
                            ?>
                                <td class="rim-cal-cell <?php echo $class; ?> <?php echo $is_current ? 'is-current' : ''; ?>"
                                    title="<?php echo esc_attr($title); ?>">
                                    <span class="rim-cal-sym"><?php echo $sym; ?></span>
                                    <?php if ( $has ):
                                        // Formatação adaptativa:
                                        //   ≥1000 → "1.2k"
                                        //   ≥10   → inteiro "$45"
                                        //   ≥0.01 → 2 casas "$2.49" (mostra cêntimos)
                                        //   <0.01 → mostra count em vez do valor
                                        $amt = (float) $cell['amount'];
                                        if ( $amt >= 1000 ) {
                                            $amt_str = '$' . number_format($amt/1000, 1) . 'k';
                                        } elseif ( $amt >= 10 ) {
                                            $amt_str = '$' . number_format($amt, 0);
                                        } elseif ( $amt >= 0.01 ) {
                                            $amt_str = '$' . number_format($amt, 2);
                                        } else {
                                            $amt_str = $cell['count'] . '×';
                                        }
                                    ?>
                                        <span class="rim-cal-amount"><?php echo $amt_str; ?></span>
                                    <?php endif; ?>
                                </td>
                            <?php endforeach; ?>
                        </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>

        <div class="rim-cal-legend">
            <span><span class="rim-cal-lg-box rim-cal-lg-ok"></span> Importado</span>
            <span><span class="rim-cal-lg-box rim-cal-lg-gap"></span> Lacuna (em falta)</span>
            <span><span class="rim-cal-lg-box rim-cal-lg-pending"></span> Mês actual em curso</span>
            <span><span class="rim-cal-lg-box rim-cal-lg-na"></span> Antes da distribuidora</span>
            <span class="rim-cal-hint">💡 Passa o rato sobre cada célula para detalhes</span>
        </div>
    </div>

    <style>
    .rim-calendar {
        background: #fff;
        border: 1px solid #e6e8eb;
        border-radius: 10px;
        margin: 0 0 20px 0;
        overflow: hidden;
    }
    .rim-cal-head {
        display: flex;
        justify-content: space-between;
        align-items: flex-start;
        padding: 14px 18px;
        background: linear-gradient(180deg, #fafbfc 0%, #f3f4f6 100%);
        border-bottom: 1px solid #e6e8eb;
        gap: 14px;
        flex-wrap: wrap;
    }
    .rim-cal-head h2 { margin: 0; font-size: 16px; color: #1a1a1a; font-weight: 600; }
    .rim-cal-sub { margin: 3px 0 0 0; font-size: 12px; color: #6b7280; }
    .rim-cal-stats { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
    .rim-cal-total-badge {
        background: linear-gradient(135deg, #10b981, #059669);
        color: #fff;
        padding: 4px 11px; border-radius: 11px;
        font-size: 12px; font-weight: 700;
        font-variant-numeric: tabular-nums;
        box-shadow: 0 1px 2px rgba(16, 185, 129, 0.25);
    }
    .rim-cal-gap-badge {
        background: #fee2e2; color: #991b1b;
        padding: 4px 10px; border-radius: 11px;
        font-size: 12px; font-weight: 700;
    }
    .rim-cal-ok-badge {
        background: #d1fae5; color: #065f46;
        padding: 4px 10px; border-radius: 11px;
        font-size: 12px; font-weight: 700;
    }
    .rim-cal-wrap {
        overflow-x: auto;
        padding: 6px 0;
    }
    .rim-cal-table {
        width: 100%;
        border-collapse: separate;
        border-spacing: 3px;
        min-width: 700px;
    }
    .rim-cal-th-dist {
        text-align: left;
        padding: 6px 14px 6px 18px;
        font-size: 10px;
        text-transform: uppercase;
        letter-spacing: 0.05em;
        color: #6b7280;
        font-weight: 700;
        white-space: nowrap;
        min-width: 140px;
    }
    .rim-cal-th-month {
        text-align: center;
        padding: 4px 0;
        font-size: 10px;
        color: #6b7280;
        font-weight: 600;
        line-height: 1.1;
        min-width: 48px;
    }
    .rim-cal-th-month.is-current {
        color: #f0b90b;
        font-weight: 800;
    }
    .rim-cal-mo { display: block; font-size: 11px; }
    .rim-cal-yr { display: block; font-size: 9px; opacity: 0.7; }

    .rim-cal-td-dist {
        padding: 6px 14px 6px 18px;
        font-size: 13px;
        color: #1a1a1a;
        white-space: nowrap;
    }
    .rim-cal-cell {
        text-align: center;
        padding: 6px 4px;
        border-radius: 6px;
        font-size: 11px;
        line-height: 1.1;
        cursor: help;
        transition: transform 0.1s;
    }
    .rim-cal-cell:hover { transform: scale(1.06); }
    .rim-cal-cell.is-current { box-shadow: 0 0 0 2px #f0b90b inset; }

    .rim-cal-cell-ok {
        background: linear-gradient(135deg, #10b981, #059669);
        color: #fff;
    }
    .rim-cal-cell-gap {
        background: #fee2e2;
        color: #991b1b;
        border: 1px dashed #f87171;
    }
    .rim-cal-cell-pending {
        background: #dbeafe;
        color: #1e40af;
        border: 1px dashed #60a5fa;
    }
    .rim-cal-cell-na {
        background: #f3f4f6;
        color: #9ca3af;
    }
    .rim-cal-sym { display: block; font-size: 12px; font-weight: 700; }
    .rim-cal-amount {
        display: block;
        font-size: 9px;
        font-weight: 600;
        opacity: 0.95;
        margin-top: 1px;
        font-variant-numeric: tabular-nums;
    }

    .rim-cal-legend {
        display: flex;
        align-items: center;
        gap: 16px;
        padding: 10px 18px;
        background: #fafbfc;
        border-top: 1px solid #e6e8eb;
        font-size: 11px;
        color: #6b7280;
        flex-wrap: wrap;
    }
    .rim-cal-legend span { display: inline-flex; align-items: center; gap: 5px; }
    .rim-cal-lg-box {
        display: inline-block;
        width: 12px; height: 12px;
        border-radius: 3px;
    }
    .rim-cal-lg-ok { background: linear-gradient(135deg, #10b981, #059669); }
    .rim-cal-lg-gap { background: #fee2e2; border: 1px dashed #f87171; }
    .rim-cal-lg-pending { background: #dbeafe; border: 1px dashed #60a5fa; }
    .rim-cal-lg-na { background: #f3f4f6; }
    .rim-cal-hint { margin-left: auto; font-style: italic; }

    @media (max-width: 900px) {
        .rim-cal-th-dist, .rim-cal-td-dist { min-width: 110px; padding-left: 12px; }
        .rim-cal-th-month, .rim-cal-cell { min-width: 38px; padding: 4px 2px; }
        .rim-cal-amount { display: none; } /* esconde valores em mobile, fica só o ✓ */
    }
    </style>
    <?php endif; ?>

    <form method="get" class="rim-filters">
        <input type="hidden" name="page" value="rmbz-admin-distribution">
        <input type="hidden" name="tab" value="royalties">
        <input type="hidden" name="rsub" value="imports">
        <div class="fg">
            <label>Distribuidora</label>
            <select name="rim_dist">
                <option value="">Todas</option>
                <?php foreach ( $distributors as $d ): ?>
                    <option value="<?php echo esc_attr($d); ?>" <?php selected($f_distributor, $d); ?>><?php echo esc_html($d); ?></option>
                <?php endforeach; ?>
            </select>
        </div>
        <div class="fg">
            <label>Status</label>
            <select name="rim_status">
                <option value="all" <?php selected($f_status, 'all'); ?>>Todos</option>
                <option value="pending" <?php selected($f_status, 'pending'); ?>>⏳ Pendente aprovação</option>
                <option value="approved" <?php selected($f_status, 'approved'); ?>>✓ Aprovadas</option>
                <option value="rejected" <?php selected($f_status, 'rejected'); ?>>✗ Rejeitadas</option>
                <option value="reverted" <?php selected($f_status, 'reverted'); ?>>Anuladas</option>
            </select>
        </div>
        <div class="fa">
            <button type="submit" class="button button-primary">🔍 Filtrar</button>
        </div>
    </form>

    <?php if ( empty($imports) ): ?>
        <div class="rim-empty">
            <div class="icon">📥</div>
            <h2>Sem importações</h2>
            <p>Ainda não fez nenhuma importação de CSV de royalties.</p>
            <a href="?page=rmbz-admin-distribution&tab=import" class="button button-primary">Importar primeiro CSV →</a>
        </div>
    <?php else: ?>
        <div class="rim-list">
            <?php foreach ( $imports as $imp ):
                $approval = $imp->approval_status ?? 'approved';  // default para importações antigas pré-schema
                $is_pending  = ($approval === 'pending_approval');
                $is_approved = ($approval === 'approved');
                $is_rejected = ($approval === 'rejected');
                $is_reverted = ! empty($imp->status) && $imp->status === 'reverted' && ! $is_rejected;

                // Buscar comissão associada
                $comm = null;
                if ( $wpdb->get_var("SHOW TABLES LIKE '$t_comm'") === $t_comm ) {
                    $comm = $wpdb->get_row( $wpdb->prepare("SELECT * FROM $t_comm WHERE import_hash = %s LIMIT 1", $imp->file_hash) );
                }
                // Contagem de linhas do ledger
                $ledger_lines = 0;
                $ledger_total = 0;
                $affected_artists = 0;
                if ( $wpdb->get_var("SHOW TABLES LIKE '$t_ledger'") === $t_ledger ) {
                    $lcols = $wpdb->get_col("SHOW COLUMNS FROM $t_ledger");
                    if ( in_array('import_hash', $lcols, true) ) {
                        $ledger_lines = (int) $wpdb->get_var( $wpdb->prepare(
                            "SELECT COUNT(*) FROM $t_ledger WHERE import_hash = %s",
                            $imp->file_hash
                        ) );
                        $ledger_total = (float) $wpdb->get_var( $wpdb->prepare(
                            "SELECT COALESCE(SUM(amount),0) FROM $t_ledger WHERE import_hash = %s AND reverted_at IS NULL",
                            $imp->file_hash
                        ) );
                        $affected_artists = (int) $wpdb->get_var( $wpdb->prepare(
                            "SELECT COUNT(DISTINCT artist_telemovel) FROM $t_ledger WHERE import_hash = %s",
                            $imp->file_hash
                        ) );
                    }
                }

                // Buscar top 5 artistas por valor para o preview de aprovação
                $top_artists_preview = [];
                if ( $is_pending && $ledger_lines > 0 ) {
                    $top_artists_preview = $wpdb->get_results( $wpdb->prepare(
                        "SELECT l.artist_telemovel, SUM(l.amount) AS total, COUNT(*) AS lines_n, w.user_nome
                         FROM $t_ledger l
                         LEFT JOIN {$wpdb->prefix}rmbz_wallets w ON w.user_telemovel = l.artist_telemovel
                         WHERE l.import_hash = %s
                         GROUP BY l.artist_telemovel
                         ORDER BY total DESC
                         LIMIT 5",
                        $imp->file_hash
                    ) );
                }
            ?>
                <div class="rim-card <?php echo $is_pending ? 'pending' : ''; ?> <?php echo $is_reverted ? 'reverted' : ''; ?> <?php echo $is_rejected ? 'rejected' : ''; ?>">
                    <div class="rim-card-left">
                        <div class="rim-card-head">
                            <strong><?php echo esc_html($imp->source_name); ?></strong>
                            <?php if ( $is_pending ): ?>
                                <span class="status-pill pending">⏳ Pendente aprovação</span>
                            <?php elseif ( $is_rejected ): ?>
                                <span class="status-pill rejected">✗ Rejeitada</span>
                            <?php elseif ( $is_reverted ): ?>
                                <span class="status-pill reverted">⚠ Anulada</span>
                            <?php else: ?>
                                <span class="status-pill active">✓ Aprovada</span>
                            <?php endif; ?>
                            <code class="hash" title="Hash do ficheiro"><?php echo esc_html(substr($imp->file_hash, 0, 12)); ?></code>
                        </div>
                        <div class="rim-card-meta">
                            <span>📅 Período: <strong><?php echo esc_html($imp->reporting_period); ?></strong></span>
                            <span>📥 Importado: <?php echo esc_html( date('d/m/Y H:i', strtotime($imp->imported_at)) ); ?></span>
                            <?php if ( ! empty($imp->file_name) ): ?>
                                <span>📄 <?php echo esc_html($imp->file_name); ?></span>
                            <?php endif; ?>
                        </div>
                        <div class="rim-card-stats">
                            <?php if ( $comm ): ?>
                                <div class="stat">
                                    <span class="lbl">Bruto</span>
                                    <strong>$<?php echo number_format($comm->gross_amount_usd, 2); ?></strong>
                                </div>
                                <div class="stat">
                                    <span class="lbl">Pago a artistas</span>
                                    <strong class="g">$<?php echo number_format($comm->artist_total_usd, 2); ?></strong>
                                </div>
                                <div class="stat">
                                    <span class="lbl">Margem 1MZ</span>
                                    <strong class="b">$<?php echo number_format($comm->onemz_margin_usd, 2); ?></strong>
                                </div>
                            <?php endif; ?>
                            <div class="stat">
                                <span class="lbl">Artistas</span>
                                <strong><?php echo $affected_artists; ?></strong>
                            </div>
                            <div class="stat">
                                <span class="lbl">Linhas ledger</span>
                                <strong><?php echo $ledger_lines; ?></strong>
                            </div>
                        </div>

                        <?php if ( $is_pending && ! empty($top_artists_preview) ): ?>
                            <details class="rim-preview">
                                <summary>👁 Ver top 5 artistas antes de aprovar</summary>
                                <table class="rim-preview-tbl">
                                    <?php foreach ( $top_artists_preview as $a ): ?>
                                        <tr>
                                            <td><strong><?php echo esc_html($a->user_nome ?: '—'); ?></strong> <code><?php echo esc_html($a->artist_telemovel); ?></code></td>
                                            <td style="text-align:right;"><?php echo (int) $a->lines_n; ?> linhas</td>
                                            <td style="text-align:right;"><strong>$<?php echo number_format($a->total, 4); ?></strong></td>
                                        </tr>
                                    <?php endforeach; ?>
                                </table>
                            </details>
                        <?php endif; ?>

                        <?php if ( $is_reverted ): ?>
                            <div class="rim-reverted-banner">
                                ⚠ Anulada em <?php echo esc_html($imp->reverted_at ? date('d/m/Y H:i', strtotime($imp->reverted_at)) : '—'); ?>
                                <?php if ( ! empty($imp->reverted_by) ): ?>
                                    por <?php echo esc_html($imp->reverted_by); ?>
                                <?php endif; ?>
                            </div>
                        <?php endif; ?>
                        <?php if ( $is_rejected ): ?>
                            <div class="rim-rejected-banner">
                                ✗ Rejeitada em <?php echo esc_html($imp->approved_at ? date('d/m/Y H:i', strtotime($imp->approved_at)) : '—'); ?>
                                <?php if ( ! empty($imp->approved_by) ): ?>por <?php echo esc_html($imp->approved_by); ?><?php endif; ?>
                                <?php if ( ! empty($imp->rejection_reason) ): ?>
                                    <div style="margin-top:4px; font-style:italic;">"<?php echo esc_html($imp->rejection_reason); ?>"</div>
                                <?php endif; ?>
                            </div>
                        <?php endif; ?>
                        <?php if ( $is_approved && ! empty($imp->approved_by) ): ?>
                            <div class="rim-approved-info">
                                ✓ Aprovada em <?php echo esc_html(date('d/m/Y H:i', strtotime($imp->approved_at))); ?> por <?php echo esc_html($imp->approved_by); ?>
                            </div>
                        <?php endif; ?>
                    </div>
                    <div class="rim-card-right">
                        <?php if ( $is_pending ): ?>
                            <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="margin-bottom:6px;"
                                  onsubmit="return confirm('✓ APROVAR esta importação?\n\n- <?php echo $affected_artists; ?> artista(s) vão começar a ver o dinheiro nas suas wallets\n- $<?php echo $comm ? number_format($comm->gross_amount_usd, 2) : '?'; ?> USD serão libertados\n\nContinuar?');">
                                <input type="hidden" name="action" value="rmbz_approve_import">
                                <input type="hidden" name="import_hash" value="<?php echo esc_attr($imp->file_hash); ?>">
                                <input type="hidden" name="import_id" value="<?php echo (int) $imp->id; ?>">
                                <?php wp_nonce_field('rmbz_approve_import_' . $imp->file_hash); ?>
                                <button type="submit" class="button button-primary" style="background:var(--rmbz-success, #10b981); border-color:var(--rmbz-success-strong, #059669); width:100%;">
                                    ✓ Aprovar
                                </button>
                            </form>
                            <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"
                                  onsubmit="return rmbzConfirmReject(this);">
                                <input type="hidden" name="action" value="rmbz_reject_import">
                                <input type="hidden" name="import_hash" value="<?php echo esc_attr($imp->file_hash); ?>">
                                <input type="hidden" name="import_id" value="<?php echo (int) $imp->id; ?>">
                                <input type="hidden" name="reason" value="">
                                <?php wp_nonce_field('rmbz_reject_import_' . $imp->file_hash); ?>
                                <button type="submit" class="button" style="width:100%;">
                                    ✗ Rejeitar
                                </button>
                            </form>
                        <?php elseif ( $is_approved && ! $is_reverted ): ?>
                            <?php
                            // [DS 1.5.90] Botões de exportar relatório + ver erros
                            $export_url = wp_nonce_url(
                                admin_url('admin-post.php?action=rmbz_export_import_report&import_id=' . $imp->id),
                                'rmbz_export_import_' . $imp->id
                            );
                            $errors_url = admin_url('admin.php?page=rmbz-import-errors&import_id=' . $imp->id);
                            $has_errors = ! empty($imp->errors_json);
                            ?>
                            <a href="<?php echo esc_url($export_url); ?>" class="button" style="width:100%; margin-bottom:6px;">
                                📥 Exportar relatório CSV
                            </a>
                            <?php if ( $has_errors || (int)($imp->skipped_rows ?? 0) > 0 ): ?>
                                <a href="<?php echo esc_url($errors_url); ?>" class="button" style="width:100%; margin-bottom:6px;">
                                    📋 Ver erros (<?php echo (int)($imp->skipped_rows ?? 0); ?>)
                                </a>
                            <?php endif; ?>

                            <?php
                            // [DS 1.5.115] Botão "Re-importar do mesmo CSV" — só
                            // aparece se o CSV ainda está arquivado (não foi
                            // limpo pela retenção). Permite voltar e apanhar
                            // linhas que tinham sido desmarcadas no preview.
                            $can_reimport = ! empty($imp->archived_path)
                                && empty($imp->archive_purged_at)
                                && function_exists('rmbz_archive_csv_exists')
                                && rmbz_archive_csv_exists($imp->archived_path);
                            ?>
                            <?php if ( $can_reimport ): ?>
                                <a href="<?php echo esc_url( wp_nonce_url(
                                    admin_url('admin-post.php?action=rmbz_additional_import&log_id=' . (int) $imp->id),
                                    'rmbz_additional_import_' . (int) $imp->id
                                ) ); ?>"
                                   class="button"
                                   style="width:100%; margin-bottom:6px; color:var(--rmbz-info-strong, #0073aa); border-color:var(--rmbz-info-strong, #0073aa);"
                                   onclick="return confirm('↻ RE-IMPORTAR DO MESMO CSV\n\nVai abrir o CSV original arquivado para apanhares linhas que tinham sido desmarcadas no preview anterior.\n\nLinhas já importadas vão aparecer com 🔒 e desmarcadas — só podes seleccionar as que ainda não estão no sistema.\n\nContinuar?');">
                                    ↻ Re-importar do mesmo CSV
                                </a>
                            <?php endif; ?>

                            <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"
                                  onsubmit="return confirm('⚠ CONFIRMA ANULAR esta importação já aprovada?\n\nVai reverter:\n- $<?php echo $comm ? number_format($comm->gross_amount_usd, 2) : '?'; ?> USD distribuídos\n- <?php echo $affected_artists; ?> artista(s) afectado(s)\n- <?php echo $ledger_lines; ?> linha(s) de ledger\n\nEsta acção vai debitar os artistas! Continuar?');">
                                <input type="hidden" name="action" value="rmbz_revert_import">
                                <input type="hidden" name="import_hash" value="<?php echo esc_attr($imp->file_hash); ?>">
                                <input type="hidden" name="import_id" value="<?php echo (int) $imp->id; ?>">
                                <?php wp_nonce_field('rmbz_revert_import_' . $imp->file_hash); ?>
                                <button type="submit" class="button button-link-delete">
                                    🗑 Anular importação
                                </button>
                            </form>
                        <?php else: ?>
                            <?php
                            // Se a importação está anulada mas ainda tem órfãos no daily_stats / ledger
                            // (ex: linhas que vieram via match_review com hash literal), oferecer
                            // botão de limpeza forçada.
                            $orphans = ( $is_reverted && function_exists('rmbz_count_orphan_rows_for_import') )
                                ? rmbz_count_orphan_rows_for_import( $imp->file_hash, $imp->reporting_period ?? '' )
                                : 0;
                            ?>
                            <?php if ( $orphans > 0 ): ?>
                                <div style="background:#fff5f5; border:1px solid #fcc; padding:8px; border-radius:4px; margin-bottom:6px;">
                                    <small style="color:var(--rmbz-danger, #cc0000); display:block; margin-bottom:6px;">
                                        ⚠ <strong><?php echo (int) $orphans; ?> linhas órfãs</strong> ainda existem
                                    </small>
                                    <a href="<?php echo esc_url( wp_nonce_url(
                                        admin_url('admin-post.php?action=rmbz_force_cleanup_import&hash=' . urlencode($imp->file_hash)),
                                        'rmbz_force_cleanup_' . $imp->file_hash
                                    ) ); ?>"
                                       class="button button-small"
                                       style="width:100%; color:var(--rmbz-danger, #cc0000); border-color:var(--rmbz-danger, #cc0000);"
                                       onclick="return confirm('🗑 LIMPEZA FORÇADA\n\nVai apagar <?php echo (int) $orphans; ?> linha(s) de stats órfãs e debitar as wallets dos artistas afectados.\n\nUsa isto quando uma anulação anterior não conseguiu apagar tudo (caso de importações com match_review).\n\nContinuar?');">
                                        🗑 Limpar lixo (<?php echo (int) $orphans; ?>)
                                    </a>
                                </div>
                            <?php endif; ?>

                            <?php
                            // [DS 1.5.108] Botão "Desfazer Anulação" se:
                            //   - import está anulado (não rejeitado)
                            //   - CSV arquivado existe
                            //   - ainda não foi desfeito
                            $can_unrevert = $is_reverted
                                && ! empty($imp->archived_path)
                                && empty($imp->unrevert_replaced_by)
                                && function_exists('rmbz_archive_csv_exists')
                                && rmbz_archive_csv_exists($imp->archived_path);
                            ?>
                            <?php if ( $can_unrevert ): ?>
                                <a href="<?php echo esc_url( wp_nonce_url(
                                    admin_url('admin-post.php?action=rmbz_unrevert_import&log_id=' . (int) $imp->id),
                                    'rmbz_unrevert_import_' . (int) $imp->id
                                ) ); ?>"
                                   class="button"
                                   style="width:100%; margin-bottom:6px; color:var(--rmbz-info-strong, #0073aa); border-color:var(--rmbz-info-strong, #0073aa);"
                                   onclick="return confirm('↶ DESFAZER ANULAÇÃO\n\nIsto vai criar uma NOVA importação a partir do CSV original arquivado.\n\nA nova importação fica PENDENTE de aprovação — tens de a aprovar depois para os artistas voltarem a receber o dinheiro.\n\nA importação anulada continua no histórico para auditoria.\n\nContinuar?');">
                                    ↶ Desfazer Anulação
                                </a>
                            <?php elseif ( $is_reverted && ! empty($imp->unrevert_replaced_by) ): ?>
                                <small style="color:var(--rmbz-info-strong, #0073aa); display:block; margin-bottom:6px;">
                                    ↶ Anulação desfeita — ver importação #<?php echo (int) $imp->unrevert_replaced_by; ?>
                                </small>
                            <?php elseif ( $is_reverted && empty($imp->archived_path) ): ?>
                                <small style="color:var(--rmbz-text-faint, #999); display:block; margin-bottom:6px;" title="Import anterior à 1.5.108 — CSV não foi arquivado">
                                    ⓘ Sem CSV arquivado (legacy)
                                </small>
                            <?php elseif ( $is_reverted && ! empty($imp->archive_purged_at) ): ?>
                                <small style="color:var(--rmbz-text-faint, #999); display:block; margin-bottom:6px;"
                                       title="CSV apagado pela retenção em <?php echo esc_attr($imp->archive_purged_at); ?>">
                                    ⓘ CSV arquivado foi limpo (>retenção)
                                </small>
                            <?php endif; ?>

                            <?php if ( $orphans === 0 && ! $can_unrevert ): ?>
                                <small style="color:var(--rmbz-text-faint, #999);">Finalizada — sem acções</small>
                            <?php endif; ?>

                            <?php
                            // [1.5.200] Botão "Apagar de vez" — só aparece em imports anulados.
                            // [1.5.205] Estendido para imports REJEITADOS também — internamente
                            //           rejected também tem status='reverted', e fazem ambos
                            //           parte do estado terminal "lixo final".
                            //
                            // OPERAÇÃO IRREVERSÍVEL — remove fisicamente:
                            //   - Registo do import_log
                            //   - Todas as linhas em ledger / daily_stats / unclaimed
                            //   - Linhas em commissions
                            //   - Linhas em match_review desse import
                            //   - CSV físico arquivado (se ainda existir)
                            //
                            // Confirmação dupla via JS (typing "APAGAR" no prompt).
                            // ?>
                            <?php if ( $is_reverted || $is_rejected ): ?>
                                <details style="margin-top:10px; border:1px dashed #fcc; border-radius:4px; padding:6px;">
                                    <summary style="cursor:pointer; color:var(--rmbz-danger, #cc0000); font-size:11px; font-weight:600;">
                                        ☠ Acção destrutiva
                                    </summary>
                                    <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>"
                                          style="margin-top:6px;"
                                          onsubmit="return rmbzConfirmDelete(this);">
                                        <input type="hidden" name="action" value="rmbz_delete_import_forever">
                                        <input type="hidden" name="import_id" value="<?php echo (int) $imp->id; ?>">
                                        <input type="hidden" name="import_hash" value="<?php echo esc_attr($imp->file_hash); ?>">
                                        <input type="hidden" name="confirm_text" value="">
                                        <?php wp_nonce_field('rmbz_delete_import_forever_' . $imp->file_hash); ?>
                                        <button type="submit" class="button button-link-delete" style="width:100%; font-size:11px;">
                                            🗑️ Apagar de vez do sistema
                                        </button>
                                        <small style="color:var(--rmbz-text-faint, #888); display:block; margin-top:4px; font-size:10px;">
                                            Remove registos da BD + CSV arquivado.<br>
                                            <strong style="color:var(--rmbz-danger, #cc0000);">Sem volta.</strong>
                                        </small>
                                    </form>
                                </details>
                            <?php endif; ?>
                        <?php endif; ?>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
        <?php if ( count($imports) >= 100 ): ?>
            <p class="rim-hint">Mostrando 100 mais recentes. Use filtros para refinar.</p>
        <?php endif; ?>
    <?php endif; ?>

    <style>
    .rim-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 10px; margin-bottom: 16px; }
    .rim-kpi { background: var(--rmbz-bg-card, #fff); border: 1px solid #e5e5e5; border-left: 3px solid #9b59b6; border-radius: 8px; padding: 12px 16px; }
    .rim-kpi.rim-priority { border-left-color: var(--rmbz-brand, #f0b90b); background: #fff9e6; }
    .rim-kpi.rim-priority .val { color: #b8860b; font-size: 26px; }
    .rim-kpi .lbl { font-size: 10px; color: var(--rmbz-text-faint, #888); text-transform: uppercase; letter-spacing: 0.3px; font-weight: 600; }
    .rim-kpi .val { font-size: 22px; font-weight: 500; color: var(--rmbz-text-strong, #222); margin: 4px 0 2px 0; }
    .rim-kpi .sub { font-size: 11px; color: var(--rmbz-text-muted, #666); }

    .rim-filters { background: var(--rmbz-bg-card, #fff); border: 1px solid #e5e5e5; border-radius: 8px; padding: 10px 14px; margin-bottom: 16px; display: flex; gap: 10px; align-items: flex-end; flex-wrap: wrap; }
    .rim-filters .fg label { display: block; font-size: 10px; color: var(--rmbz-text-muted, #666); text-transform: uppercase; font-weight: 600; margin-bottom: 4px; }
    .rim-filters .fg select { padding: 6px 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 13px; min-width: 160px; }
    .rim-filters .fa { margin-left: auto; }

    .rim-empty { text-align: center; padding: 50px 20px; background: var(--rmbz-bg-card, #fff); border: 1px solid #e5e5e5; border-radius: 8px; }
    .rim-empty .icon { font-size: 48px; margin-bottom: 12px; }
    .rim-empty h2 { color: var(--rmbz-text-muted, #666); margin: 0 0 8px 0; font-weight: 500; }
    .rim-empty p { color: var(--rmbz-text-faint, #888); margin: 0 0 16px 0; }

    .rim-list { display: flex; flex-direction: column; gap: 10px; }
    .rim-card { background: var(--rmbz-bg-card, #fff); border: 1px solid #e5e5e5; border-radius: 8px; padding: 14px 16px; display: grid; grid-template-columns: 1fr auto; gap: 16px; align-items: center; }
    .rim-card.reverted { background: #fafafa; opacity: 0.75; border-left: 3px solid var(--rmbz-danger, #ef4444); padding-left: 13px; }
    .rim-card.pending { border-left: 3px solid var(--rmbz-brand, #f0b90b); padding-left: 13px; background: #fffbef; }
    .rim-card.rejected { background: #fafafa; opacity: 0.7; border-left: 3px solid #95a5a6; padding-left: 13px; }
    .status-pill.pending { background: #fff3cd; color: #856404; }
    .status-pill.rejected { background: #e2e3e5; color: #383d41; }
    .rim-rejected-banner { margin-top: 10px; padding: 8px 12px; background: #e2e3e5; color: #383d41; border-radius: 4px; font-size: 12px; }
    .rim-approved-info { margin-top: 8px; font-size: 11px; color: var(--rmbz-text-muted, #666); }
    .rim-preview { margin-top: 10px; padding: 8px 12px; background: #fafafa; border: 1px solid #eee; border-radius: 4px; }
    .rim-preview summary { cursor: pointer; font-size: 12px; color: var(--rmbz-text-secondary, #555); font-weight: 500; }
    .rim-preview summary:hover { color: #111; }
    .rim-preview-tbl { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: 11px; }
    .rim-preview-tbl td { padding: 4px 6px; border-bottom: 1px solid #f0f0f0; }
    .rim-preview-tbl code { background: var(--rmbz-bg-card, #fff); padding: 1px 4px; font-size: 10px; color: var(--rmbz-text-muted, #666); border-radius: 2px; }
    .rim-card-head { display: flex; gap: 10px; align-items: center; margin-bottom: 6px; flex-wrap: wrap; }
    .rim-card-head strong { font-size: 15px; color: var(--rmbz-text-strong, #222); }
    .rim-card-head .hash { background: #f0f0f0; padding: 2px 6px; border-radius: 3px; font-family: monospace; font-size: 10px; color: var(--rmbz-text-muted, #666); }
    .status-pill { padding: 3px 10px; border-radius: 10px; font-size: 10px; font-weight: 600; }
    .status-pill.active { background: #d4edda; color: #155724; }
    .status-pill.reverted { background: #f8d7da; color: var(--rmbz-danger-strong, #721c24); }
    .rim-card-meta { display: flex; gap: 14px; flex-wrap: wrap; font-size: 12px; color: var(--rmbz-text-muted, #666); margin-bottom: 10px; }
    .rim-card-stats { display: flex; gap: 16px; flex-wrap: wrap; padding-top: 10px; border-top: 1px solid #f0f0f0; }
    .rim-card-stats .stat { display: flex; flex-direction: column; }
    .rim-card-stats .stat .lbl { font-size: 10px; color: var(--rmbz-text-faint, #888); text-transform: uppercase; letter-spacing: 0.3px; }
    .rim-card-stats .stat strong { font-size: 14px; color: var(--rmbz-text-strong, #333); font-variant-numeric: tabular-nums; }
    .rim-card-stats .stat strong.g { color: var(--rmbz-success-strong, #059669); }
    .rim-card-stats .stat strong.b { color: var(--rmbz-info-strong, #2563eb); }
    .rim-reverted-banner { margin-top: 10px; padding: 8px 12px; background: #f8d7da; color: var(--rmbz-danger-strong, #721c24); border-radius: 4px; font-size: 12px; }
    .rim-card-right { min-width: 160px; text-align: right; }
    .rim-hint { text-align: center; color: var(--rmbz-text-faint, #888); margin-top: 20px; font-size: 12px; }
    </style>

    <script>
    // Substitui o antigo prompt() + confirm() encadeados, que em alguns
    // browsers (Firefox / Chrome no Mac) bloqueiam a segunda caixa por
    // anti-spam, fazendo o botão "Rejeitar" parecer não responder.
    function rmbzConfirmReject(form) {
        var reason = window.prompt(
            '✗ REJEITAR esta importação\n\n' +
            'Indique o motivo (opcional, pode ficar em branco):'
        );
        // Se clicou Cancel → null → aborta
        if (reason === null) return false;
        // Mete o motivo no campo escondido e submete directamente
        var f = form.querySelector('input[name=reason]');
        if (f) f.value = reason;
        return true;
    }

    // [1.5.200] Confirmação dupla para apagar de vez
    function rmbzConfirmDelete(form) {
        // Aviso primeiro
        var ok = window.confirm(
            '☠ APAGAR DE VEZ DO SISTEMA\n\n' +
            'Esta operação é IRREVERSÍVEL e vai remover:\n' +
            '• Registo da importação\n' +
            '• Todas as linhas de ledger / daily_stats / unclaimed\n' +
            '• Comissões + match_review desta importação\n' +
            '• CSV arquivado (ficheiro físico)\n\n' +
            'Não dá para desfazer. Continuar?'
        );
        if (!ok) return false;

        // Pedir typing "APAGAR" para confirmar
        var typed = window.prompt(
            'Para confirmar, escreve a palavra:\n\n' +
            '    APAGAR\n\n' +
            '(em maiúsculas, sem aspas)'
        );
        if (typed === null) return false;
        if (typed.trim() !== 'APAGAR') {
            alert('Não confirmado — operação cancelada.\n(Tens de escrever exactamente "APAGAR")');
            return false;
        }

        // Mete a confirmação no campo escondido
        var f = form.querySelector('input[name=confirm_text]');
        if (f) f.value = 'APAGAR';
        return true;
    }
    </script>
    <?php
}


/* ============================================================================
 * HANDLER — anular importação (reversion híbrida)
 * ============================================================================ */
function rmbz_handle_revert_import() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');

    $hash = sanitize_text_field($_POST['import_hash'] ?? '');
    if ( empty($hash) ) wp_die('Hash inválido.');

    check_admin_referer('rmbz_revert_import_' . $hash);

    global $wpdb;
    $t_logs      = $wpdb->prefix . 'rmbz_distro_import_logs';
    $t_ledger    = $wpdb->prefix . 'rmbz_distro_ledger';
    $t_daily     = $wpdb->prefix . 'rmbz_distro_daily_stats';
    $t_unclaimed = $wpdb->prefix . 'rmbz_distro_unclaimed';
    $t_comm      = $wpdb->prefix . 'rmbz_distro_platform_commissions';
    $t_stats     = $wpdb->prefix . 'rmbz_distro_stats';

    // Apanhar a linha específica.
    //
    // [DS 1.5.104] Antes, o handler usava ORDER BY id DESC LIMIT 1 com base
    // no file_hash, o que falhava quando o mesmo ficheiro foi importado
    // duas vezes (após limpeza de hash duplicado): clicar "Anular" na
    // mais antiga apanhava a mais recente, que podia já estar revertida.
    // Agora preferimos `import_id` (único). `file_hash` continua a ser
    // verificado como segurança contra adulteração do form.
    $import_id = (int) ($_POST['import_id'] ?? 0);
    if ( $import_id > 0 ) {
        $log = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM $t_logs WHERE id = %d AND file_hash = %s LIMIT 1",
            $import_id, $hash
        ) );
    } else {
        // Fallback retro-compatível: forms antigos sem import_id
        $log = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM $t_logs WHERE file_hash = %s ORDER BY id DESC LIMIT 1",
            $hash
        ) );
    }
    if ( ! $log ) {
        $err = urlencode('Importação não encontrada.');
        wp_safe_redirect(admin_url("admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports&revert_error=$err"));
        exit;
    }
    if ( ! empty($log->status) && $log->status === 'reverted' ) {
        $err = urlencode('Esta importação já foi anulada.');
        wp_safe_redirect(admin_url("admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports&revert_error=$err"));
        exit;
    }

    $current_user = wp_get_current_user();
    $reverted_by = $current_user && $current_user->exists() ? $current_user->user_login : 'admin';
    $now = current_time('mysql');

    $wpdb->query('START TRANSACTION');
    try {
        // 1) Somar ledger por artista (para subtrair do stats) — só não-revertidos
        // Procuramos por DUAS variantes: o hash real desta importação E o
        // literal '(match_review)' que algumas linhas legacy ainda têm.
        // Para o '(match_review)', restringimos por reporting_period para
        // não apanhar dados de OUTRAS importações que também usaram esse
        // marcador. Usamos o reporting_period do log para garantir match.
        $period_log = $log->reporting_period ?? null;
        $artist_totals = [];
        $artist_streams = [];
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_ledger'") === $t_ledger ) {
            $cols = $wpdb->get_col("SHOW COLUMNS FROM $t_ledger");
            if ( in_array('import_hash', $cols, true) ) {
                // [DS 1.5.104] Filter helper discrimina por import_log_id
                // quando há múltiplos imports com mesmo hash.
                list($w, $p) = rmbz_build_import_filter( $log, $t_ledger );
                $rows = $wpdb->get_results( $wpdb->prepare(
                    "SELECT artist_telemovel, SUM(amount) AS total
                     FROM $t_ledger
                     WHERE $w AND reverted_at IS NULL
                     GROUP BY artist_telemovel",
                    $p
                ) );
                foreach ( $rows as $r ) {
                    $artist_totals[$r->artist_telemovel] = (float) $r->total;
                }

                // Match_review legacy do mesmo período (se houver)
                if ( $period_log ) {
                    $rows_mr = $wpdb->get_results( $wpdb->prepare(
                        "SELECT artist_telemovel, SUM(amount) AS total
                         FROM $t_ledger
                         WHERE import_hash = '(match_review)'
                           AND reporting_period = %s
                           AND reverted_at IS NULL
                         GROUP BY artist_telemovel",
                        $period_log
                    ) );
                    foreach ( $rows_mr as $r ) {
                        if ( ! isset($artist_totals[$r->artist_telemovel]) ) {
                            $artist_totals[$r->artist_telemovel] = 0;
                        }
                        $artist_totals[$r->artist_telemovel] += (float) $r->total;
                    }
                }

                // Também buscar streams para subtrair (ambas variantes)
                if ( $wpdb->get_var("SHOW TABLES LIKE '$t_daily'") === $t_daily ) {
                    $dcols = $wpdb->get_col("SHOW COLUMNS FROM $t_daily");
                    if ( in_array('import_hash', $dcols, true) ) {
                        // [DS 1.5.104] Filter helper
                        list($wd, $pd) = rmbz_build_import_filter( $log, $t_daily );
                        $rows2 = $wpdb->get_results( $wpdb->prepare(
                            "SELECT artist_telemovel, SUM(streams) AS s
                             FROM $t_daily WHERE $wd
                             GROUP BY artist_telemovel",
                            $pd
                        ) );
                        foreach ( $rows2 as $r ) {
                            $artist_streams[$r->artist_telemovel] = (int) $r->s;
                        }

                        if ( $period_log ) {
                            $rows2_mr = $wpdb->get_results( $wpdb->prepare(
                                "SELECT artist_telemovel, SUM(streams) AS s
                                 FROM $t_daily
                                 WHERE import_hash = '(match_review)'
                                   AND report_date >= %s
                                   AND report_date < DATE_ADD(%s, INTERVAL 1 MONTH)
                                 GROUP BY artist_telemovel",
                                $period_log . '-01', $period_log . '-01'
                            ) );
                            foreach ( $rows2_mr as $r ) {
                                if ( ! isset($artist_streams[$r->artist_telemovel]) ) {
                                    $artist_streams[$r->artist_telemovel] = 0;
                                }
                                $artist_streams[$r->artist_telemovel] += (int) $r->s;
                            }
                        }
                    }
                }
            }
        }

        // ────────────────────────────────────────────────────────────────────
        // [DS 1.5.107] CASCATA DE REEMBOLSOS DE LEVANTAMENTOS REJEITADOS
        // ────────────────────────────────────────────────────────────────────
        // Quando um utilizador faz pedido de levantamento e este é rejeitado,
        // entra uma linha no ledger tipo 'withdrawal_rejected_revert' com
        // `import_hash = NULL` (porque o reembolso é uma operação independente
        // do import original).
        //
        // Mas se o dinheiro original veio do import que estamos agora a
        // anular, esse reembolso não devia ter existido — o saldo veio
        // de algo que está a ser invalidado. Por isso, em cascata,
        // somamos esses reembolsos ao débito.
        //
        // Heurística defensável: incluímos QUALQUER reembolso posterior à
        // data do import sendo anulado, para os artistas afectados. Isto
        // pode ser conservador (debitar reembolso que veio de outro import),
        // mas é coerente com a regra "se o utilizador foi creditado e
        // depois levantou e foi rejeitado, o ciclo todo é apagado".
        //
        // O admin pode sempre fazer ajuste manual depois se houver caso
        // legítimo.
        // ────────────────────────────────────────────────────────────────────
        $refund_totals = [];   // phone => total_usd a debitar adicional
        $refund_rows_to_revert = []; // ids do ledger a marcar reverted_at
        $log_imported_at = $log->imported_at ?? null;
        if ( ! empty($artist_totals) && $log_imported_at && $wpdb->get_var("SHOW TABLES LIKE '$t_ledger'") === $t_ledger ) {
            $phones = array_keys($artist_totals);
            $placeholders = implode(',', array_fill(0, count($phones), '%s'));
            $params = array_merge( $phones, [ $log_imported_at ] );
            $rows_refund = $wpdb->get_results( $wpdb->prepare(
                "SELECT id, artist_telemovel, amount
                 FROM $t_ledger
                 WHERE artist_telemovel IN ($placeholders)
                   AND type = 'withdrawal_rejected_revert'
                   AND reverted_at IS NULL
                   AND created_at >= %s",
                $params
            ) );
            foreach ( $rows_refund as $rr ) {
                if ( ! isset($refund_totals[$rr->artist_telemovel]) ) {
                    $refund_totals[$rr->artist_telemovel] = 0;
                }
                $refund_totals[$rr->artist_telemovel] += (float) $rr->amount;
                $refund_rows_to_revert[] = (int) $rr->id;
            }

            // Adicionar ao débito a fazer por artista
            foreach ( $refund_totals as $phone => $extra ) {
                if ( ! isset($artist_totals[$phone]) ) $artist_totals[$phone] = 0;
                $artist_totals[$phone] += $extra;
            }

            // Marcar essas linhas como revertidas (evita serem contabilizadas
            // de novo se o import for desanulado, e dá histórico claro).
            if ( ! empty($refund_rows_to_revert) ) {
                $ids_in = implode(',', array_map('intval', $refund_rows_to_revert));
                $wpdb->query( $wpdb->prepare(
                    "UPDATE $t_ledger SET reverted_at = %s
                     WHERE id IN ($ids_in) AND reverted_at IS NULL",
                    $now
                ) );
            }
        }

        // 2) Soft-delete do ledger — marca reverted_at (ambas variantes)
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_ledger'") === $t_ledger ) {
            $cols = $wpdb->get_col("SHOW COLUMNS FROM $t_ledger");
            if ( in_array('import_hash', $cols, true) && in_array('reverted_at', $cols, true) ) {
                // [DS 1.5.104] Usar filter helper para discriminar entre
                // múltiplos imports do mesmo file_hash. Linhas antigas
                // (sem import_log_id) caem no fallback hash+período.
                list($w, $p) = rmbz_build_import_filter( $log, $t_ledger );
                $wpdb->query( $wpdb->prepare(
                    "UPDATE $t_ledger SET reverted_at = %s WHERE $w AND reverted_at IS NULL",
                    array_merge([ $now ], $p)
                ) );
                if ( $period_log ) {
                    $wpdb->query( $wpdb->prepare(
                        "UPDATE $t_ledger SET reverted_at = %s
                         WHERE import_hash = '(match_review)'
                           AND reporting_period = %s
                           AND reverted_at IS NULL",
                        $now, $period_log
                    ) );
                }
            }
        }

        // 3) Hard-delete do daily_stats (ambas variantes)
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_daily'") === $t_daily ) {
            $cols = $wpdb->get_col("SHOW COLUMNS FROM $t_daily");
            if ( in_array('import_hash', $cols, true) ) {
                list($w, $p) = rmbz_build_import_filter( $log, $t_daily );
                $wpdb->query( $wpdb->prepare( "DELETE FROM $t_daily WHERE $w", $p ) );
                if ( $period_log ) {
                    $wpdb->query( $wpdb->prepare(
                        "DELETE FROM $t_daily
                         WHERE import_hash = '(match_review)'
                           AND report_date >= %s
                           AND report_date < DATE_ADD(%s, INTERVAL 1 MONTH)",
                        $period_log . '-01', $period_log . '-01'
                    ) );
                }
            }
        }

        // 4) Hard-delete do unclaimed (apenas status=pending ainda não reclamados)
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_unclaimed'") === $t_unclaimed ) {
            $cols = $wpdb->get_col("SHOW COLUMNS FROM $t_unclaimed");
            if ( in_array('import_hash', $cols, true) ) {
                list($w, $p) = rmbz_build_import_filter( $log, $t_unclaimed );
                $wpdb->query( $wpdb->prepare(
                    "DELETE FROM $t_unclaimed WHERE $w AND status = 'pending'",
                    $p
                ) );
            }
        }

        // 5) APAGAR a comissão (não só marcar revertida) — porque o
        // import_hash tem UNIQUE KEY e qualquer re-importação do mesmo
        // CSV depois de uma anulação rebenta com "Duplicate entry".
        // O histórico fica preservado em rmbz_distro_import_logs.
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_comm'") === $t_comm ) {
            list($w, $p) = rmbz_build_import_filter( $log, $t_comm );
            $wpdb->query( $wpdb->prepare( "DELETE FROM $t_comm WHERE $w", $p ) );
        }

        // 6) Subtrair totais da stats de cada artista afectado
        foreach ( $artist_totals as $phone => $total ) {
            $streams_sub = $artist_streams[$phone] ?? 0;
            $wpdb->query( $wpdb->prepare(
                "UPDATE $t_stats
                 SET total_earnings = GREATEST(0, total_earnings - %f),
                     total_streams  = GREATEST(0, total_streams - %d),
                     last_updated   = %s
                 WHERE artist_telemovel = %s",
                $total, $streams_sub, $now, $phone
            ) );
        }

        // ────────────────────────────────────────────────────────────────────
        // [DS 1.5.110] WALLET MT NÃO É DEBITADA AUTOMATICAMENTE
        // ────────────────────────────────────────────────────────────────────
        // Antes deste fix, revert_import debitava `rmbz_wallets.balance`
        // (em MT) com o valor em USD do ledger — espelho do bug do approve.
        //
        // A regra correcta: royalties só vivem em USD em `rmbz_distro_stats`.
        // Anular um import:
        //   - Reverte ledger (UPDATE reverted_at) — feito no passo 2
        //   - Apaga daily_stats — feito no passo 3
        //   - Apaga unclaimed pendentes — feito no passo 4
        //   - Apaga commission do import — feito no passo 5
        //   - Subtrai distro_stats USD — feito no passo 6
        //
        // Isto é tudo. A wallet MT não é tocada porque não foi creditada
        // automaticamente quando o import foi aprovado (1.5.110+).
        //
        // Para imports aprovados PRE-1.5.110, a wallet MT pode ter dinheiro
        // residual (USD-tratado-como-MT) que não é debitado por aqui. O
        // admin tem ferramenta manual no diagnóstico para corrigir caso
        // a caso, conforme decisão da nova arquitectura.
        // ────────────────────────────────────────────────────────────────────

        // [DS 1.5.103+1.5.105] Limpeza de "Matches a Rever" desta importação
        //
        // a) Apagar PENDENTES — não há dinheiro associado, perdem sentido.
        //    Só os 'pending'; deixamos 'rejected' para histórico.
        //
        // b) [1.5.105] Marcar APROVADOS como 'reverted_with_import' — o
        //    dinheiro DELES já foi revertido nos passos 2-6.5 acima
        //    (porque as linhas de ledger criadas pelo approve têm
        //    import_hash igual ao do import original). Mas a coluna
        //    `status` ficava em 'approved' eternamente, criando visual
        //    confuso onde matches "Aprovados" não correspondiam a
        //    dinheiro real. Mudamos para 'reverted_with_import' para
        //    sinalizar claramente.
        $t_match_review = $wpdb->prefix . 'rmbz_distro_match_review';
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_match_review'") === $t_match_review ) {
            // (a) apagar pendentes
            $wpdb->query( $wpdb->prepare(
                "DELETE FROM $t_match_review
                 WHERE import_hash = %s AND status = 'pending'",
                $hash
            ) );
            // (b) marcar aprovados como revertidos com a importação.
            // review_notes acumula quem reverteu para auditoria.
            $wpdb->query( $wpdb->prepare(
                "UPDATE $t_match_review
                 SET status = 'reverted_with_import',
                     reviewed_at = %s,
                     review_notes = CONCAT_WS(' | ', review_notes,
                         CONCAT('Revertido com anulação do import por ', %s, ' em ', %s))
                 WHERE import_hash = %s AND status = 'approved'",
                $now, $reverted_by, $now, $hash
            ) );
        }

        // 7) Marcar import_log como revertido (usar id para apanhar só o registo correto)
        $wpdb->update( $t_logs,
            [ 'status' => 'reverted', 'reverted_at' => $now, 'reverted_by' => $reverted_by ],
            [ 'id' => (int) $log->id ],
            [ '%s','%s','%s' ],
            [ '%d' ]
        );

        $wpdb->query('COMMIT');

    } catch ( Exception $e ) {
        $wpdb->query('ROLLBACK');
        $err = urlencode('Erro ao anular: ' . $e->getMessage());
        wp_safe_redirect(admin_url("admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports&revert_error=$err"));
        exit;
    }

    wp_safe_redirect(admin_url("admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports&reverted=1"));
    exit;
}
add_action('admin_post_rmbz_revert_import', 'rmbz_handle_revert_import');


/* ============================================================================
 * RE-LIMPEZA — para importações já marcadas "Anulada" mas que ainda têm
 * dados nas tabelas (lixo de revert anterior incompleto, ex: linhas que
 * usaram `(match_review)` como hash em vez do hash real).
 *
 * Endpoint: admin-post.php?action=rmbz_force_cleanup_import&hash=...
 *
 * Aparece automaticamente na linha de cada importação "Anulada" se ainda
 * houver lixo associado.
 * ============================================================================ */
function rmbz_handle_force_cleanup_import() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');

    $hash = sanitize_text_field($_GET['hash'] ?? $_POST['hash'] ?? '');
    if ( empty($hash) ) wp_die('Hash inválido.');

    check_admin_referer('rmbz_force_cleanup_' . $hash);

    global $wpdb;
    $t_logs    = $wpdb->prefix . 'rmbz_distro_import_logs';
    $t_ledger  = $wpdb->prefix . 'rmbz_distro_ledger';
    $t_daily   = $wpdb->prefix . 'rmbz_distro_daily_stats';
    $t_trans   = $wpdb->prefix . 'rmbz_wallet_transactions';
    $t_wallets = $wpdb->prefix . 'rmbz_wallets';
    $t_stats   = $wpdb->prefix . 'rmbz_distro_stats';
    $base = admin_url('admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports');

    $log = $wpdb->get_row( $wpdb->prepare(
        "SELECT * FROM $t_logs WHERE file_hash = %s ORDER BY id DESC LIMIT 1",
        $hash
    ) );
    if ( ! $log ) {
        wp_safe_redirect( add_query_arg('revert_error', urlencode('Importação não encontrada.'), $base) );
        exit;
    }
    if ( empty($log->status) || $log->status !== 'reverted' ) {
        wp_safe_redirect( add_query_arg('revert_error', urlencode('Esta acção só é válida para importações já anuladas.'), $base) );
        exit;
    }

    $period_log = $log->reporting_period ?? null;
    if ( empty($period_log) ) {
        wp_safe_redirect( add_query_arg('revert_error', urlencode('Importação sem período definido — não é possível identificar o lixo.'), $base) );
        exit;
    }

    $now = current_time('mysql');
    $current_user = wp_get_current_user();
    $by = $current_user && $current_user->exists() ? $current_user->user_login : 'admin';

    $wpdb->query('START TRANSACTION');
    try {
        // 1) Apurar valores a debitar das wallets — usando ambas as variantes
        $artist_totals = [];
        $rows1 = $wpdb->get_results( $wpdb->prepare(
            "SELECT artist_telemovel, SUM(amount) AS total FROM $t_ledger
             WHERE import_hash = %s AND reverted_at IS NULL
             GROUP BY artist_telemovel", $hash
        ) );
        foreach ( $rows1 as $r ) {
            $artist_totals[$r->artist_telemovel] = (float) $r->total;
        }
        $rows2 = $wpdb->get_results( $wpdb->prepare(
            "SELECT artist_telemovel, SUM(amount) AS total FROM $t_ledger
             WHERE import_hash = '(match_review)'
               AND reporting_period = %s
               AND reverted_at IS NULL
             GROUP BY artist_telemovel", $period_log
        ) );
        foreach ( $rows2 as $r ) {
            if ( ! isset($artist_totals[$r->artist_telemovel]) ) $artist_totals[$r->artist_telemovel] = 0;
            $artist_totals[$r->artist_telemovel] += (float) $r->total;
        }

        // 2) Soft-delete ledger (ambas variantes)
        $wpdb->query( $wpdb->prepare(
            "UPDATE $t_ledger SET reverted_at = %s WHERE import_hash = %s AND reverted_at IS NULL",
            $now, $hash
        ) );
        $wpdb->query( $wpdb->prepare(
            "UPDATE $t_ledger SET reverted_at = %s
             WHERE import_hash = '(match_review)' AND reporting_period = %s AND reverted_at IS NULL",
            $now, $period_log
        ) );

        // 3) Hard-delete daily_stats (ambas variantes)
        $wpdb->query( $wpdb->prepare(
            "DELETE FROM $t_daily WHERE import_hash = %s", $hash
        ) );
        $wpdb->query( $wpdb->prepare(
            "DELETE FROM $t_daily
             WHERE import_hash = '(match_review)'
               AND report_date >= %s
               AND report_date < DATE_ADD(%s, INTERVAL 1 MONTH)",
            $period_log . '-01', $period_log . '-01'
        ) );

        // 3.5) Apagar platform_commissions órfão (UNIQUE KEY bloqueia re-import)
        $t_comm_local = $wpdb->prefix . 'rmbz_distro_platform_commissions';
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_comm_local'") === $t_comm_local ) {
            $wpdb->query( $wpdb->prepare(
                "DELETE FROM $t_comm_local WHERE import_hash = %s",
                $hash
            ) );
        }

        // 4) Débito real das wallets — defesa anti-duplo-débito por marker
        $revert_marker = '[force_cleanup:' . $hash . ']';
        $debited_count = 0;
        foreach ( $artist_totals as $phone => $total_to_debit ) {
            if ( empty($phone) || $total_to_debit <= 0 ) continue;

            $already = (int) $wpdb->get_var( $wpdb->prepare(
                "SELECT COUNT(*) FROM $t_trans
                 WHERE user_telemovel = %s AND details LIKE %s",
                $phone, '%' . $wpdb->esc_like($revert_marker) . '%'
            ) );
            if ( $already > 0 ) continue;

            $details = sprintf(
                'Limpeza forçada da importação %s — débito %.4f USD %s',
                substr($hash, 0, 8), $total_to_debit, $revert_marker
            );

            // Débito direto, permitindo saldo negativo (correção retroactiva)
            $current_bal = (float) $wpdb->get_var( $wpdb->prepare(
                "SELECT balance FROM $t_wallets WHERE user_telemovel = %s", $phone
            ) );
            $new_bal = $current_bal - $total_to_debit;
            $wpdb->update(
                $t_wallets,
                [ 'balance' => $new_bal, 'last_updated' => $now ],
                [ 'user_telemovel' => $phone ],
                [ '%f', '%s' ], [ '%s' ]
            );
            $wpdb->insert(
                $t_trans,
                [
                    'user_telemovel'   => $phone,
                    'amount'           => -$total_to_debit,
                    'type'             => 'royalty_revert',
                    'details'          => $details,
                    'transaction_date' => $now,
                    'is_unlocked'      => 1,
                ],
                [ '%s', '%f', '%s', '%s', '%s', '%d' ]
            );
            $debited_count++;

            // Recalcular stats do artista
            if ( function_exists('rmbz_recalc_artist_stats') ) {
                rmbz_recalc_artist_stats($phone);
            }
        }

        // 5) Marcar log com nota
        $existing_reason = (string)($log->rejection_reason ?? '');
        $new_reason = trim($existing_reason . "\n[Limpeza forçada por $by em $now]");
        if ( in_array('rejection_reason', (array) $wpdb->get_col("SHOW COLUMNS FROM $t_logs"), true) ) {
            $wpdb->update( $t_logs,
                [ 'rejection_reason' => $new_reason ],
                [ 'file_hash' => $hash ],
                [ '%s' ], [ '%s' ]
            );
        }

        $wpdb->query('COMMIT');
    } catch ( Exception $e ) {
        $wpdb->query('ROLLBACK');
        wp_safe_redirect( add_query_arg('revert_error', urlencode('Erro: ' . $e->getMessage()), $base) );
        exit;
    }

    wp_safe_redirect( add_query_arg([
        'cleanup_done' => '1',
        'debited' => (int) $debited_count,
    ], $base) );
    exit;
}
add_action('admin_post_rmbz_force_cleanup_import', 'rmbz_handle_force_cleanup_import');


/* ============================================================================
 * [1.5.200] HANDLER — APAGAR IMPORTAÇÃO DE VEZ
 *
 * OPERAÇÃO IRREVERSÍVEL. Remove fisicamente todas as linhas relacionadas
 * com um import (que TEM que estar anulado primeiro).
 *
 * Tabelas afectadas (cascade):
 *   - rmbz_distro_import_logs       DELETE WHERE id = X
 *   - rmbz_distro_ledger             DELETE WHERE import_hash = HASH
 *   - rmbz_distro_daily_stats        DELETE WHERE import_hash = HASH
 *   - rmbz_distro_unclaimed          DELETE WHERE import_log_id = X (se coluna existe)
 *   - rmbz_distro_platform_commissions DELETE WHERE import_hash = HASH
 *   - rmbz_track_match_review        DELETE WHERE import_hash = HASH (se coluna existe)
 *
 * Ficheiro físico:
 *   - CSV em /uploads/rmbz_imports_archive/<hash>.csv → unlink
 *
 * Audit trail:
 *   - Antes de apagar, gravar resumo em wp_options (rmbz_deleted_imports_log)
 *     com: ID, hash, período, contagens, quem apagou, quando
 * ============================================================================ */
function rmbz_handle_delete_import_forever() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');

    $hash = sanitize_text_field($_POST['import_hash'] ?? '');
    if ( empty($hash) ) wp_die('Hash inválido.');

    check_admin_referer('rmbz_delete_import_forever_' . $hash);

    // Confirmação dupla — o JS pôs "APAGAR" no campo
    $confirm = sanitize_text_field($_POST['confirm_text'] ?? '');
    if ( $confirm !== 'APAGAR' ) {
        $err = urlencode('Confirmação inválida (precisa do texto "APAGAR")');
        wp_safe_redirect(admin_url("admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports&delete_error=$err"));
        exit;
    }

    $import_id = (int) ($_POST['import_id'] ?? 0);
    if ( $import_id <= 0 ) {
        $err = urlencode('ID de importação inválido');
        wp_safe_redirect(admin_url("admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports&delete_error=$err"));
        exit;
    }

    global $wpdb;
    $t_logs      = $wpdb->prefix . 'rmbz_distro_import_logs';
    $t_ledger    = $wpdb->prefix . 'rmbz_distro_ledger';
    $t_daily     = $wpdb->prefix . 'rmbz_distro_daily_stats';
    $t_unclaimed = $wpdb->prefix . 'rmbz_distro_unclaimed';
    $t_comm      = $wpdb->prefix . 'rmbz_distro_platform_commissions';
    $t_match_rev = $wpdb->prefix . 'rmbz_track_match_review';

    // 1) Buscar o log e validar que está anulado
    $log = $wpdb->get_row( $wpdb->prepare(
        "SELECT * FROM $t_logs WHERE id = %d AND file_hash = %s LIMIT 1",
        $import_id, $hash
    ) );
    if ( ! $log ) {
        $err = urlencode('Importação não encontrada');
        wp_safe_redirect(admin_url("admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports&delete_error=$err"));
        exit;
    }
    // [1.5.205] Aceitar tanto 'reverted' (anulados) como 'rejected'.
    // Internamente, rejected também tem status='reverted' (definido pelo
    // reject handler), mas verificamos explicitamente para mensagem clara.
    $is_reverted_status = ! empty($log->status) && $log->status === 'reverted';
    $is_rejected_approval = ! empty($log->approval_status) && $log->approval_status === 'rejected';

    if ( ! $is_reverted_status && ! $is_rejected_approval ) {
        $err = urlencode('Só é possível apagar importações anuladas ou rejeitadas. Anula/rejeita primeiro.');
        wp_safe_redirect(admin_url("admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports&delete_error=$err"));
        exit;
    }

    $current_user = wp_get_current_user();
    $deleted_by = $current_user && $current_user->exists() ? $current_user->user_login : 'admin';
    $now = current_time('mysql');

    // 2) AUDIT TRAIL — antes de apagar, registar tudo o que vai ser apagado
    // em wp_options para nunca se perder a memória de que existiu.
    $period_log = $log->reporting_period ?? null;

    $stats = [
        'import_id'        => $import_id,
        'file_hash'        => $hash,
        'reporting_period' => $period_log,
        'service'          => $log->service ?? null,
        'created_at'       => $log->created_at ?? null,
        'reverted_at'      => $log->reverted_at ?? null,
        'archived_path'    => $log->archived_path ?? null,
        'deleted_by'       => $deleted_by,
        'deleted_at'       => $now,
        'rows_deleted'     => [],
    ];

    // Contar antes de apagar
    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_ledger'") === $t_ledger ) {
        $stats['rows_deleted']['ledger'] = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM $t_ledger WHERE import_hash = %s", $hash
        ) );
    }
    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_daily'") === $t_daily ) {
        $stats['rows_deleted']['daily_stats'] = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM $t_daily WHERE import_hash = %s", $hash
        ) );
    }
    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_unclaimed'") === $t_unclaimed ) {
        $cols_u = $wpdb->get_col("SHOW COLUMNS FROM $t_unclaimed");
        if ( in_array('import_log_id', $cols_u, true) ) {
            $stats['rows_deleted']['unclaimed'] = (int) $wpdb->get_var( $wpdb->prepare(
                "SELECT COUNT(*) FROM $t_unclaimed WHERE import_log_id = %d", $import_id
            ) );
        }
    }
    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_comm'") === $t_comm ) {
        $stats['rows_deleted']['commissions'] = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM $t_comm WHERE import_hash = %s", $hash
        ) );
    }
    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_match_rev'") === $t_match_rev ) {
        $cols_m = $wpdb->get_col("SHOW COLUMNS FROM $t_match_rev");
        if ( in_array('import_hash', $cols_m, true) ) {
            $stats['rows_deleted']['match_review'] = (int) $wpdb->get_var( $wpdb->prepare(
                "SELECT COUNT(*) FROM $t_match_rev WHERE import_hash = %s", $hash
            ) );
        }
    }

    // Gravar audit trail (lista cumulativa em wp_options)
    $audit_log = get_option('rmbz_deleted_imports_log', []);
    if ( ! is_array($audit_log) ) $audit_log = [];
    $audit_log[] = $stats;
    // Manter apenas os últimos 500 (proteção contra crescimento sem fim)
    if ( count($audit_log) > 500 ) {
        $audit_log = array_slice($audit_log, -500);
    }
    update_option('rmbz_deleted_imports_log', $audit_log, false); // autoload=false

    // 3) Apagar tudo numa transação atómica
    $wpdb->query('START TRANSACTION');
    $total_rows_deleted = 0;
    try {
        // 3.1) Ledger
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_ledger'") === $t_ledger ) {
            $r = $wpdb->query( $wpdb->prepare(
                "DELETE FROM $t_ledger WHERE import_hash = %s", $hash
            ) );
            $total_rows_deleted += (int) $r;
        }

        // 3.2) Daily stats
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_daily'") === $t_daily ) {
            $r = $wpdb->query( $wpdb->prepare(
                "DELETE FROM $t_daily WHERE import_hash = %s", $hash
            ) );
            $total_rows_deleted += (int) $r;
        }

        // 3.3) Unclaimed (apenas se a coluna import_log_id existe)
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_unclaimed'") === $t_unclaimed ) {
            $cols_u = $wpdb->get_col("SHOW COLUMNS FROM $t_unclaimed");
            if ( in_array('import_log_id', $cols_u, true) ) {
                $r = $wpdb->query( $wpdb->prepare(
                    "DELETE FROM $t_unclaimed WHERE import_log_id = %d", $import_id
                ) );
                $total_rows_deleted += (int) $r;
            }
        }

        // 3.4) Platform commissions
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_comm'") === $t_comm ) {
            $r = $wpdb->query( $wpdb->prepare(
                "DELETE FROM $t_comm WHERE import_hash = %s", $hash
            ) );
            $total_rows_deleted += (int) $r;
        }

        // 3.5) Match review
        if ( $wpdb->get_var("SHOW TABLES LIKE '$t_match_rev'") === $t_match_rev ) {
            $cols_m = $wpdb->get_col("SHOW COLUMNS FROM $t_match_rev");
            if ( in_array('import_hash', $cols_m, true) ) {
                $r = $wpdb->query( $wpdb->prepare(
                    "DELETE FROM $t_match_rev WHERE import_hash = %s", $hash
                ) );
                $total_rows_deleted += (int) $r;
            }
        }

        // 3.6) O próprio log
        $r = $wpdb->query( $wpdb->prepare(
            "DELETE FROM $t_logs WHERE id = %d AND file_hash = %s LIMIT 1",
            $import_id, $hash
        ) );
        $total_rows_deleted += (int) $r;

        $wpdb->query('COMMIT');
    } catch ( Exception $e ) {
        $wpdb->query('ROLLBACK');
        $err = urlencode('Erro ao apagar: ' . $e->getMessage());
        wp_safe_redirect(admin_url("admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=imports&delete_error=$err"));
        exit;
    }

    // 4) Apagar CSV arquivado (depois da BD — se falhar não é fatal, mas
    //    avisa-se. Também há protecções de path traversal.)
    if ( ! empty($log->archived_path) ) {
        $archive_path = $log->archived_path;

        // Segurança extra: garantir que está dentro de /uploads/
        $upload_dir = wp_upload_dir();
        $upload_base = realpath( $upload_dir['basedir'] );
        $real_archive = realpath( $archive_path );

        if ( $upload_base && $real_archive && strpos( $real_archive, $upload_base ) === 0 && file_exists( $real_archive ) ) {
            @unlink( $real_archive );
        }
    }

    // 5) Redirect com sucesso
    wp_safe_redirect( add_query_arg([
        'page'    => 'rmbz-admin-distribution',
        'tab'     => 'royalties',
        'rsub'    => 'imports',
        'deleted' => 1,
        'rows'    => $total_rows_deleted,
    ], admin_url('admin.php') ) );
    exit;
}
add_action('admin_post_rmbz_delete_import_forever', 'rmbz_handle_delete_import_forever');


/**
 * Conta linhas órfãs ainda associadas a uma importação (após anular).
 * Usado para mostrar o botão "Limpar lixo" na UI quando aplicável.
 */
function rmbz_count_orphan_rows_for_import( $hash, $period ) {
    global $wpdb;
    $t_ledger = $wpdb->prefix . 'rmbz_distro_ledger';
    $t_daily  = $wpdb->prefix . 'rmbz_distro_daily_stats';

    $count = 0;
    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_daily'") === $t_daily ) {
        $count += (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM $t_daily WHERE import_hash = %s", $hash
        ) );
        if ( $period ) {
            $count += (int) $wpdb->get_var( $wpdb->prepare(
                "SELECT COUNT(*) FROM $t_daily
                 WHERE import_hash = '(match_review)'
                   AND report_date >= %s
                   AND report_date < DATE_ADD(%s, INTERVAL 1 MONTH)",
                $period . '-01', $period . '-01'
            ) );
        }
    }
    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_ledger'") === $t_ledger ) {
        $count += (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM $t_ledger
             WHERE import_hash = %s AND reverted_at IS NULL", $hash
        ) );
        if ( $period ) {
            $count += (int) $wpdb->get_var( $wpdb->prepare(
                "SELECT COUNT(*) FROM $t_ledger
                 WHERE import_hash = '(match_review)'
                   AND reporting_period = %s
                   AND reverted_at IS NULL", $period
            ) );
        }
    }
    return $count;
}
