<?php
// includes/admin/royalties/royalties-ledger.php
// Extracto de transacções com filtros e ajustes manuais

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


function rmbz_render_royalties_ledger() {
    global $wpdb;
    $t_ledger = $wpdb->prefix . 'rmbz_distro_ledger';

    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_ledger'") !== $t_ledger ) {
        echo '<div class="notice notice-warning"><p>Tabela de ledger não existe.</p></div>';
        return;
    }

    if ( isset($_GET['adj_done']) ) {
        echo '<div class="notice notice-success is-dismissible"><p>✓ Ajuste manual registado.</p></div>';
    }
    if ( isset($_GET['adj_error']) ) {
        echo '<div class="notice notice-error"><p>Erro: ' . esc_html(urldecode($_GET['adj_error'])) . '</p></div>';
    }

    $f_artist = isset($_GET['l_artist']) ? sanitize_text_field($_GET['l_artist']) : '';
    $f_type   = isset($_GET['l_type']) ? sanitize_text_field($_GET['l_type']) : '';
    $f_period = isset($_GET['l_period']) ? sanitize_text_field($_GET['l_period']) : '';
    $f_status = isset($_GET['l_status']) ? sanitize_text_field($_GET['l_status']) : 'active';

    $cols = $wpdb->get_col("SHOW COLUMNS FROM $t_ledger");
    $has_reverted = in_array('reverted_at', $cols, true);

    $where = ['1=1'];
    $params = [];
    if ( $f_artist ) {
        $where[] = 'artist_telemovel LIKE %s';
        $params[] = '%' . $wpdb->esc_like($f_artist) . '%';
    }
    if ( $f_type ) {
        $where[] = 'type = %s';
        $params[] = $f_type;
    }
    if ( $f_period ) {
        $where[] = 'reporting_period = %s';
        $params[] = $f_period;
    }
    if ( $has_reverted ) {
        if ( $f_status === 'active' )       $where[] = "reverted_at IS NULL";
        elseif ( $f_status === 'reverted' ) $where[] = "reverted_at IS NOT NULL";
    }
    $where_sql = implode(' AND ', $where);

    $count_sql = "SELECT COUNT(*) FROM $t_ledger WHERE $where_sql";
    $total_count = $params ? (int) $wpdb->get_var( $wpdb->prepare($count_sql, $params) ) : (int) $wpdb->get_var($count_sql);

    $sum_sql = "SELECT COALESCE(SUM(amount),0) FROM $t_ledger WHERE $where_sql";
    $total_sum = $params ? (float) $wpdb->get_var( $wpdb->prepare($sum_sql, $params) ) : (float) $wpdb->get_var($sum_sql);

    // [1.5.176] Paginação — 100 por página
    $per_page = 100;
    $total_pages = max( 1, (int) ceil( $total_count / $per_page ) );
    $current_page = isset($_GET['l_page']) ? max( 1, (int) $_GET['l_page'] ) : 1;
    if ( $current_page > $total_pages ) $current_page = $total_pages;
    $offset = ( $current_page - 1 ) * $per_page;

    $sql = "SELECT * FROM $t_ledger WHERE $where_sql ORDER BY created_at DESC LIMIT %d OFFSET %d";
    $sql_params = array_merge( $params, [ $per_page, $offset ] );
    $rows = $wpdb->get_results( $wpdb->prepare($sql, $sql_params) );

    $types = $wpdb->get_col("SELECT DISTINCT type FROM $t_ledger ORDER BY type");
    $periods = $wpdb->get_col("SELECT DISTINCT reporting_period FROM $t_ledger WHERE reporting_period IS NOT NULL ORDER BY reporting_period DESC LIMIT 24");
    ?>

    <div class="rol-summary">
        <div class="rol-stat">
            <span class="lbl">Resultado da pesquisa</span>
            <strong><?php echo number_format($total_count); ?> transacção(ões) · $<?php echo number_format($total_sum, 2); ?> USD</strong>
        </div>
        <button type="button" class="button button-primary" onclick="document.getElementById('rol-adjust-form').style.display='block';">
            ➕ Ajuste manual (+/-)
        </button>
    </div>

    <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" id="rol-adjust-form" style="display:none; background:#fff; border:1px solid #e5e5e5; border-radius:8px; padding:16px; margin-bottom:16px;">
        <h3 style="margin:0 0 12px 0;">➕ Ajuste manual</h3>
        <input type="hidden" name="action" value="rmbz_ledger_manual_adjust">
        <?php wp_nonce_field('rmbz_ledger_adjust_nonce'); ?>
        <div style="display:grid; grid-template-columns: 1fr 1fr; gap:12px; margin-bottom:12px;">
            <div>
                <label style="display:block; font-size:11px; font-weight:600; color:#666; margin-bottom:4px;">Telemóvel do artista</label>
                <input type="text" name="artist_phone" required placeholder="+258..." style="width:100%; padding:6px;">
            </div>
            <div>
                <label style="display:block; font-size:11px; font-weight:600; color:#666; margin-bottom:4px;">Valor USD (negativo para retirar)</label>
                <input type="number" name="amount" step="0.0001" required placeholder="ex: 10.00 ou -10.00" style="width:100%; padding:6px;">
            </div>
        </div>
        <div style="margin-bottom:12px;">
            <label style="display:block; font-size:11px; font-weight:600; color:#666; margin-bottom:4px;">Tipo</label>
            <select name="adj_type" required style="width:100%; padding:6px;">
                <option value="manual_credit">Crédito manual (+)</option>
                <option value="manual_debit">Débito manual (-)</option>
                <option value="correction">Rectificação</option>
                <option value="bonus">Bónus</option>
                <option value="refund">Reembolso</option>
                <option value="penalty">Penalidade</option>
            </select>
        </div>
        <div style="margin-bottom:12px;">
            <label style="display:block; font-size:11px; font-weight:600; color:#666; margin-bottom:4px;">Justificação (obrigatória)</label>
            <textarea name="reason" required rows="2" style="width:100%; padding:6px;" placeholder="Explica o motivo deste ajuste para auditoria..."></textarea>
        </div>
        <button type="submit" class="button button-primary" onclick="return confirm('Confirmar ajuste? Esta operação fica registada permanentemente no ledger.');">
            ✓ Aplicar ajuste
        </button>
        <button type="button" class="button" onclick="document.getElementById('rol-adjust-form').style.display='none';">Cancelar</button>
    </form>

    <form method="get" class="rol-filters">
        <input type="hidden" name="page" value="rmbz-admin-distribution">
        <input type="hidden" name="tab" value="royalties">
        <input type="hidden" name="rsub" value="ledger">
        <div class="fg">
            <label>Artista (telemóvel)</label>
            <input type="text" name="l_artist" value="<?php echo esc_attr($f_artist); ?>" placeholder="+258...">
        </div>
        <div class="fg">
            <label>Tipo</label>
            <select name="l_type">
                <option value="">Todos</option>
                <?php foreach ( $types as $t ): ?>
                    <option value="<?php echo esc_attr($t); ?>" <?php selected($f_type, $t); ?>><?php echo esc_html($t); ?></option>
                <?php endforeach; ?>
            </select>
        </div>
        <div class="fg">
            <label>Período</label>
            <select name="l_period">
                <option value="">Todos</option>
                <?php foreach ( $periods as $p ): ?>
                    <option value="<?php echo esc_attr($p); ?>" <?php selected($f_period, $p); ?>><?php echo esc_html($p); ?></option>
                <?php endforeach; ?>
            </select>
        </div>
        <?php if ( $has_reverted ): ?>
        <div class="fg">
            <label>Status</label>
            <select name="l_status">
                <option value="all" <?php selected($f_status, 'all'); ?>>Todos</option>
                <option value="active" <?php selected($f_status, 'active'); ?>>Activos</option>
                <option value="reverted" <?php selected($f_status, 'reverted'); ?>>Anulados</option>
            </select>
        </div>
        <?php endif; ?>
        <div class="fa">
            <button type="submit" class="button button-primary">🔍 Filtrar</button>
            <a href="?page=rmbz-admin-distribution&tab=royalties&rsub=ledger" class="button">Limpar</a>
        </div>
    </form>

    <table class="rol-table" id="rol-ledger-table">
        <thead>
            <tr>
                <th>Data</th>
                <th>Artista</th>
                <th>Tipo</th>
                <th>Período</th>
                <th style="text-align:right;">Valor</th>
                <th>Descrição</th>
                <th>Status</th>
            </tr>
        </thead>
        <tbody id="rol-ledger-tbody">
            <?php if ( empty($rows) ): ?>
                <tr><td colspan="7" style="text-align:center; padding:30px; color:#888;">Nenhuma transacção encontrada.</td></tr>
            <?php else: foreach ( $rows as $r ): 
                $is_reverted = $has_reverted && ! empty($r->reverted_at);
                $is_negative = (float) $r->amount < 0;
            ?>
                <tr class="<?php echo $is_reverted ? 'reverted' : ''; ?>">
                    <td><?php echo esc_html(date('d/m/Y H:i', strtotime($r->created_at))); ?></td>
                    <td><code><?php echo esc_html($r->artist_telemovel); ?></code></td>
                    <td><span class="type-pill type-<?php echo esc_attr($r->type); ?>"><?php echo esc_html($r->type); ?></span></td>
                    <td><?php echo esc_html($r->reporting_period ?: '—'); ?></td>
                    <td style="text-align:right;" class="<?php echo $is_negative ? 'neg' : 'pos'; ?>">
                        <strong><?php echo $is_negative ? '-' : '+'; ?>$<?php echo number_format(abs((float)$r->amount), 4); ?></strong>
                    </td>
                    <td class="desc"><?php echo esc_html(rmbz_truncate_str($r->description ?? '', 80)); ?></td>
                    <td>
                        <?php if ( $is_reverted ): ?>
                            <span class="status-pill reverted">⚠ Anulado</span>
                        <?php else: ?>
                            <span class="status-pill active">✓</span>
                        <?php endif; ?>
                    </td>
                </tr>
            <?php endforeach; endif; ?>
        </tbody>
    </table>

    <?php /* [1.5.176] PAGINAÇÃO — sem reload, AJAX troca tbody */ ?>
    <?php if ( $total_pages > 1 ): ?>
        <div class="rol-pagination" id="rol-pagination"
             data-total-pages="<?php echo (int) $total_pages; ?>"
             data-current-page="<?php echo (int) $current_page; ?>"
             data-total-count="<?php echo (int) $total_count; ?>"
             data-per-page="<?php echo (int) $per_page; ?>"
             data-nonce="<?php echo esc_attr( wp_create_nonce('rmbz_ledger_page') ); ?>"
             data-filters='<?php echo esc_attr( wp_json_encode([
                'l_artist' => $f_artist,
                'l_type'   => $f_type,
                'l_period' => $f_period,
                'l_status' => $f_status,
             ]) ); ?>'>
            <button type="button" class="rol-pg-btn rol-pg-prev" data-page="prev"
                    <?php echo $current_page <= 1 ? 'disabled' : ''; ?>>← Anterior</button>
            <span class="rol-pg-numbers" id="rol-pg-numbers"><!-- preenchido pelo JS --></span>
            <button type="button" class="rol-pg-btn rol-pg-next" data-page="next"
                    <?php echo $current_page >= $total_pages ? 'disabled' : ''; ?>>Próxima →</button>
            <span class="rol-pg-info" id="rol-pg-info">
                Página <strong><?php echo (int) $current_page; ?></strong> de <strong><?php echo (int) $total_pages; ?></strong>
                · <?php echo number_format($total_count); ?> transacções
            </span>
        </div>
    <?php endif; ?>

    <style>
    .rol-summary { display:flex; justify-content:space-between; align-items:center; background:#fff; border:1px solid #e5e5e5; border-radius:8px; padding:12px 16px; margin-bottom:12px; }
    .rol-stat .lbl { font-size:10px; color:#888; text-transform:uppercase; letter-spacing:0.3px; display:block; }
    .rol-stat strong { font-size:14px; color:#222; }
    .rol-filters { background:#fff; border:1px solid #e5e5e5; border-radius:8px; padding:10px 14px; margin-bottom:12px; display:flex; gap:10px; align-items:flex-end; flex-wrap:wrap; }
    .rol-filters .fg label { display:block; font-size:10px; color:#666; text-transform:uppercase; font-weight:600; margin-bottom:4px; }
    .rol-filters .fg input, .rol-filters .fg select { padding:5px 8px; border:1px solid #ddd; border-radius:4px; font-size:12px; min-width:140px; }
    .rol-filters .fa { margin-left:auto; display:flex; gap:6px; }
    .rol-table { width:100%; border-collapse:collapse; background:#fff; border:1px solid #e5e5e5; border-radius:8px; overflow:hidden; font-size:12px; }
    .rol-table th { background:#fafafa; padding:10px 8px; text-align:left; font-size:10px; text-transform:uppercase; color:#666; font-weight:600; border-bottom:1px solid #e5e5e5; }
    .rol-table td { padding:10px 8px; border-bottom:1px solid #f0f0f0; vertical-align:middle; }
    .rol-table tr:last-child td { border-bottom:none; }
    .rol-table tr.reverted { opacity:0.5; background:#fafafa; }
    .rol-table .neg strong { color:#c0392b; }
    .rol-table .pos strong { color:#27ae60; }
    .rol-table .desc { color:#666; font-size:11px; max-width:250px; }
    .rol-table code { background:#f5f5f5; padding:2px 6px; border-radius:3px; font-size:10px; }
    .type-pill { padding:2px 8px; border-radius:10px; font-size:10px; font-weight:600; background:#eef; color:#446; text-transform:none; }
    .type-pill.type-royalty_payout, .type-pill.type-royalty_split { background:#d4edda; color:#155724; }
    .type-pill.type-manual_claim { background:#fff3cd; color:#856404; }
    .type-pill.type-manual_credit, .type-pill.type-bonus { background:#d1ecf1; color:#0c5460; }
    .type-pill.type-manual_debit, .type-pill.type-penalty { background:#f8d7da; color:#721c24; }
    .status-pill { padding:2px 8px; border-radius:10px; font-size:10px; font-weight:600; }
    .status-pill.active { background:#d4edda; color:#155724; }
    .status-pill.reverted { background:#f8d7da; color:#721c24; }

    /* [1.5.176] Paginação */
    .rol-pagination {
        display: flex;
        align-items: center;
        gap: 8px;
        margin-top: 16px;
        padding: 12px 16px;
        background: #fff;
        border: 1px solid #e5e5e5;
        border-radius: 8px;
        flex-wrap: wrap;
    }
    .rol-pg-btn {
        padding: 6px 12px;
        border: 1px solid #ddd;
        background: #fafafa;
        color: #333;
        border-radius: 4px;
        font-size: 12px;
        cursor: pointer;
        transition: all 0.15s ease;
    }
    .rol-pg-btn:hover:not(:disabled) {
        background: #f0b90b;
        border-color: #f0b90b;
        color: #000;
    }
    .rol-pg-btn:disabled {
        opacity: 0.4;
        cursor: not-allowed;
    }
    .rol-pg-numbers {
        display: inline-flex;
        gap: 4px;
        flex-wrap: wrap;
    }
    .rol-pg-num {
        padding: 6px 11px;
        border: 1px solid #ddd;
        background: #fff;
        color: #333;
        border-radius: 4px;
        font-size: 12px;
        cursor: pointer;
        min-width: 32px;
        text-align: center;
        transition: all 0.15s ease;
    }
    .rol-pg-num:hover {
        background: #f0b90b;
        border-color: #f0b90b;
        color: #000;
    }
    .rol-pg-num.active {
        background: #f0b90b;
        border-color: #d4a009;
        color: #000;
        font-weight: 700;
    }
    .rol-pg-ellipsis {
        padding: 6px 4px;
        color: #888;
        font-size: 12px;
    }
    .rol-pg-info {
        margin-left: auto;
        font-size: 11px;
        color: #666;
    }
    .rol-table.is-loading {
        opacity: 0.5;
        pointer-events: none;
        transition: opacity 0.15s ease;
    }
    </style>

    <?php /* [1.5.176] JS paginação ledger — sem reload */ ?>
    <script>
    (function() {
        var pagination = document.getElementById('rol-pagination');
        if (!pagination) return;

        var totalPages   = parseInt(pagination.getAttribute('data-total-pages'), 10) || 1;
        var currentPage  = parseInt(pagination.getAttribute('data-current-page'), 10) || 1;
        var totalCount   = parseInt(pagination.getAttribute('data-total-count'), 10) || 0;
        var perPage      = parseInt(pagination.getAttribute('data-per-page'), 10) || 100;
        var nonce        = pagination.getAttribute('data-nonce');
        var filtersAttr  = pagination.getAttribute('data-filters') || '{}';
        var filters      = {};
        try { filters = JSON.parse(filtersAttr); } catch(e) {}

        var ajaxUrl = '<?php echo esc_js( admin_url('admin-ajax.php') ); ?>';
        var tbody   = document.getElementById('rol-ledger-tbody');
        var table   = document.getElementById('rol-ledger-table');
        var numbers = document.getElementById('rol-pg-numbers');
        var info    = document.getElementById('rol-pg-info');

        // Renderizar números: 1 ... 4 5 [6] 7 8 ... 12
        function renderNumbers() {
            numbers.innerHTML = '';
            var pages = computePagesToShow(currentPage, totalPages);
            pages.forEach(function(p) {
                if (p === '...') {
                    var span = document.createElement('span');
                    span.className = 'rol-pg-ellipsis';
                    span.textContent = '…';
                    numbers.appendChild(span);
                } else {
                    var btn = document.createElement('button');
                    btn.type = 'button';
                    btn.className = 'rol-pg-num' + (p === currentPage ? ' active' : '');
                    btn.textContent = String(p);
                    btn.setAttribute('data-page', String(p));
                    numbers.appendChild(btn);
                }
            });

            // Update prev/next
            var prevBtn = pagination.querySelector('.rol-pg-prev');
            var nextBtn = pagination.querySelector('.rol-pg-next');
            if (prevBtn) prevBtn.disabled = (currentPage <= 1);
            if (nextBtn) nextBtn.disabled = (currentPage >= totalPages);

            // Update info
            if (info) {
                info.innerHTML = 'Página <strong>' + currentPage + '</strong> de <strong>' + totalPages + '</strong> · ' + totalCount.toLocaleString('pt-PT') + ' transacções';
            }
        }

        // Decidir quais páginas mostrar (max ~9 visíveis)
        function computePagesToShow(current, total) {
            if (total <= 9) {
                var arr = [];
                for (var i = 1; i <= total; i++) arr.push(i);
                return arr;
            }
            var pages = [1];
            var start = Math.max(2, current - 2);
            var end = Math.min(total - 1, current + 2);
            if (start > 2) pages.push('...');
            for (var i = start; i <= end; i++) pages.push(i);
            if (end < total - 1) pages.push('...');
            pages.push(total);
            return pages;
        }

        // Buscar página via AJAX
        function loadPage(page) {
            page = parseInt(page, 10);
            if (isNaN(page) || page < 1 || page > totalPages || page === currentPage) return;

            table.classList.add('is-loading');

            var fd = new FormData();
            fd.append('action', 'rmbz_ledger_page');
            fd.append('_nonce', nonce);
            fd.append('page', String(page));
            fd.append('l_artist', filters.l_artist || '');
            fd.append('l_type',   filters.l_type   || '');
            fd.append('l_period', filters.l_period || '');
            fd.append('l_status', filters.l_status || 'active');

            fetch(ajaxUrl, { method: 'POST', body: fd, credentials: 'same-origin' })
                .then(function(r) { return r.json(); })
                .then(function(data) {
                    table.classList.remove('is-loading');
                    if (!data || !data.success) {
                        console.error('[Ledger] Erro ao carregar página', data);
                        return;
                    }
                    tbody.innerHTML = data.data.html || '';
                    currentPage = page;
                    renderNumbers();
                    // Scroll suave para topo da tabela
                    table.scrollIntoView({ behavior: 'smooth', block: 'start' });
                })
                .catch(function(err) {
                    table.classList.remove('is-loading');
                    console.error('[Ledger] Falhou', err);
                });
        }

        pagination.addEventListener('click', function(e) {
            var btn = e.target.closest('.rol-pg-btn, .rol-pg-num');
            if (!btn || btn.disabled) return;
            var p = btn.getAttribute('data-page');
            if (p === 'prev') loadPage(currentPage - 1);
            else if (p === 'next') loadPage(currentPage + 1);
            else loadPage(p);
        });

        renderNumbers();
    })();
    </script>
    <?php
}


function rmbz_truncate_str( $s, $max = 80 ) {
    $s = (string) $s;
    if ( mb_strlen($s) <= $max ) return $s;
    return mb_substr($s, 0, $max - 1) . '…';
}


/* ============================================================================
 * HANDLER — ajuste manual
 * ============================================================================ */
function rmbz_handle_ledger_manual_adjust() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');
    check_admin_referer('rmbz_ledger_adjust_nonce');

    global $wpdb;
    $phone  = preg_replace('/[^0-9+]/', '', (string) ($_POST['artist_phone'] ?? ''));
    $amount = (float) ($_POST['amount'] ?? 0);
    $type   = sanitize_key($_POST['adj_type'] ?? 'manual_credit');
    $reason = sanitize_textarea_field($_POST['reason'] ?? '');

    $base = admin_url('admin.php?page=rmbz-admin-distribution&tab=royalties&rsub=ledger');

    if ( empty($phone) || empty($reason) || $amount == 0 ) {
        wp_safe_redirect( add_query_arg('adj_error', urlencode('Telemóvel, valor e justificação são obrigatórios.'), $base) );
        exit;
    }

    $artist = $wpdb->get_row( $wpdb->prepare(
        "SELECT id, user_nome FROM {$wpdb->prefix}rmbz_wallets WHERE user_telemovel = %s LIMIT 1", $phone
    ) );
    if ( ! $artist ) {
        wp_safe_redirect( add_query_arg('adj_error', urlencode('Artista não encontrado: ' . $phone), $base) );
        exit;
    }

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

    $wpdb->query('START TRANSACTION');
    try {
        $desc = sprintf('Ajuste manual por %s: %s', $admin_login, $reason);

        $wpdb->insert( $wpdb->prefix . 'rmbz_distro_ledger', [
            'artist_telemovel'  => $phone,
            'amount'            => $amount,
            'currency'          => 'USD',
            'original_amount'   => $amount,
            'original_currency' => 'USD',
            'exchange_rate'     => 1.0,
            'source_name'       => 'Manual Adjustment',
            'reporting_period'  => date('Y-m'),
            'type'              => $type,
            'description'       => $desc,
            'reference_id'      => 'ADJ_' . date('YmdHis') . '_' . wp_generate_password(4, false),
            'created_at'        => $now,
        ] );

        $wpdb->query( $wpdb->prepare(
            "INSERT INTO {$wpdb->prefix}rmbz_distro_stats (artist_telemovel, total_streams, total_earnings, last_updated)
             VALUES (%s, 0, %f, %s)
             ON DUPLICATE KEY UPDATE
                total_earnings = GREATEST(0, total_earnings + VALUES(total_earnings)),
                last_updated   = VALUES(last_updated)",
            $phone, $amount, $now
        ) );

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

    wp_safe_redirect( add_query_arg('adj_done', '1', $base) );
    exit;
}
add_action('admin_post_rmbz_ledger_manual_adjust', 'rmbz_handle_ledger_manual_adjust');


/* ============================================================================
 * [1.5.176] HANDLER AJAX — paginação ledger sem reload
 *
 * Recebe: page (1-indexed) + filtros + nonce
 * Devolve: HTML do tbody com rows da página solicitada
 *
 * Usa exactamente a mesma lógica de query que rmbz_render_royalties_ledger
 * (mantida em sync — se um filtro mudar lá, mudar aqui).
 * ============================================================================ */
function rmbz_ledger_page_ajax_handler() {
    if ( ! current_user_can('manage_options') ) {
        wp_send_json_error( [ 'msg' => 'no_permission' ], 403 );
    }
    if ( ! isset($_POST['_nonce']) || ! wp_verify_nonce( $_POST['_nonce'], 'rmbz_ledger_page' ) ) {
        wp_send_json_error( [ 'msg' => 'nonce_invalid' ], 403 );
    }

    global $wpdb;
    $t_ledger = $wpdb->prefix . 'rmbz_distro_ledger';

    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_ledger'") !== $t_ledger ) {
        wp_send_json_error( [ 'msg' => 'no_table' ], 500 );
    }

    $page     = max( 1, (int) ( $_POST['page'] ?? 1 ) );
    $f_artist = sanitize_text_field( $_POST['l_artist'] ?? '' );
    $f_type   = sanitize_text_field( $_POST['l_type'] ?? '' );
    $f_period = sanitize_text_field( $_POST['l_period'] ?? '' );
    $f_status = sanitize_text_field( $_POST['l_status'] ?? 'active' );

    $cols = $wpdb->get_col("SHOW COLUMNS FROM $t_ledger");
    $has_reverted = in_array('reverted_at', $cols, true);

    $where = ['1=1'];
    $params = [];
    if ( $f_artist ) {
        $where[] = 'artist_telemovel LIKE %s';
        $params[] = '%' . $wpdb->esc_like($f_artist) . '%';
    }
    if ( $f_type ) {
        $where[] = 'type = %s';
        $params[] = $f_type;
    }
    if ( $f_period ) {
        $where[] = 'reporting_period = %s';
        $params[] = $f_period;
    }
    if ( $has_reverted ) {
        if ( $f_status === 'active' )       $where[] = "reverted_at IS NULL";
        elseif ( $f_status === 'reverted' ) $where[] = "reverted_at IS NOT NULL";
    }
    $where_sql = implode(' AND ', $where);

    $per_page = 100;
    $offset = ( $page - 1 ) * $per_page;

    $sql = "SELECT * FROM $t_ledger WHERE $where_sql ORDER BY created_at DESC LIMIT %d OFFSET %d";
    $sql_params = array_merge( $params, [ $per_page, $offset ] );
    $rows = $wpdb->get_results( $wpdb->prepare($sql, $sql_params) );

    // Render tbody HTML
    ob_start();
    if ( empty($rows) ) {
        echo '<tr><td colspan="7" style="text-align:center; padding:30px; color:#888;">Nenhuma transacção nesta página.</td></tr>';
    } else {
        foreach ( $rows as $r ) {
            $is_reverted = $has_reverted && ! empty($r->reverted_at);
            $is_negative = (float) $r->amount < 0;
            ?>
            <tr class="<?php echo $is_reverted ? 'reverted' : ''; ?>">
                <td><?php echo esc_html(date('d/m/Y H:i', strtotime($r->created_at))); ?></td>
                <td><code><?php echo esc_html($r->artist_telemovel); ?></code></td>
                <td><span class="type-pill type-<?php echo esc_attr($r->type); ?>"><?php echo esc_html($r->type); ?></span></td>
                <td><?php echo esc_html($r->reporting_period ?: '—'); ?></td>
                <td style="text-align:right;" class="<?php echo $is_negative ? 'neg' : 'pos'; ?>">
                    <strong><?php echo $is_negative ? '-' : '+'; ?>$<?php echo number_format(abs((float)$r->amount), 4); ?></strong>
                </td>
                <td class="desc"><?php echo esc_html(rmbz_truncate_str($r->description ?? '', 80)); ?></td>
                <td>
                    <?php if ( $is_reverted ): ?>
                        <span class="status-pill reverted">⚠ Anulado</span>
                    <?php else: ?>
                        <span class="status-pill active">✓</span>
                    <?php endif; ?>
                </td>
            </tr>
            <?php
        }
    }
    $html = ob_get_clean();

    wp_send_json_success( [ 'html' => $html, 'page' => $page, 'count' => count($rows) ] );
}
add_action('wp_ajax_rmbz_ledger_page', 'rmbz_ledger_page_ajax_handler');
