<?php
/**
 * includes/admin/predeploy-hardening.php
 *
 * ============================================================================
 * HARDENING PRÉ-PRODUÇÃO — 1.5.148
 * ============================================================================
 *
 * 3 componentes integrados numa só página admin:
 *
 *   1. 💾 Snapshots da base de dados — dump SQL das tabelas rmbz_*
 *      antes de cada deploy crítico, guardado em /uploads/rmbz_predeploy_snapshots/
 *
 *   2. 📊 Health Dashboard — verificações em tempo real do estado do
 *      sistema: BD, disco, cron, PHP, schema, etc.
 *
 *   3. 📜 Deploy Log — tabela rmbz_deploy_log que regista cada activate/
 *      versão instalada, com possibilidade de marcar "última versão
 *      estável" para rollback futuro.
 *
 * MENU: Settings → 1MZ → 🛡 Pré-Deploy
 */

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


// ============================================================================
// SCHEMA — tabela rmbz_deploy_log
// ============================================================================

function rmbz_predeploy_table() {
    global $wpdb;
    return $wpdb->prefix . 'rmbz_deploy_log';
}

function rmbz_predeploy_install_schema() {
    global $wpdb;
    if ( get_option('rmbz_predeploy_schema_v') === '1.0' ) return;

    $table = rmbz_predeploy_table();
    $charset = $wpdb->get_charset_collate();
    $sql = "CREATE TABLE $table (
        id bigint(20) NOT NULL AUTO_INCREMENT,
        version varchar(20) NOT NULL,
        deploy_at datetime DEFAULT CURRENT_TIMESTAMP NOT NULL,
        deployed_by varchar(80) DEFAULT NULL,
        is_stable tinyint(1) DEFAULT 0 NOT NULL,
        snapshot_path varchar(255) DEFAULT NULL,
        notes text DEFAULT NULL,
        PRIMARY KEY  (id),
        KEY idx_version (version),
        KEY idx_stable (is_stable)
    ) ENGINE=InnoDB $charset;";

    require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
    dbDelta( $sql );

    update_option('rmbz_predeploy_schema_v', '1.0');

    // Registar a versão actual como primeiro deploy (silencioso, sem snapshot)
    rmbz_predeploy_record_current_version();
}
add_action('admin_init', 'rmbz_predeploy_install_schema', 8);
add_action('init',        'rmbz_predeploy_install_schema', 9);


/**
 * Regista a versão actual no deploy log se ainda não está lá.
 * Chamado em todos os admin_init (mas barato — só insert se diferente da última).
 */
function rmbz_predeploy_record_current_version() {
    global $wpdb;
    $current_version = rmbz_predeploy_get_plugin_version();
    if ( empty($current_version) ) return;

    $table = rmbz_predeploy_table();
    if ( $wpdb->get_var("SHOW TABLES LIKE '$table'") !== $table ) return;

    $last = $wpdb->get_var( "SELECT version FROM $table ORDER BY id DESC LIMIT 1" );
    if ( $last === $current_version ) return; // Mesma versão, não duplica

    $user = wp_get_current_user();
    $wpdb->insert(
        $table,
        [
            'version'     => $current_version,
            'deploy_at'   => current_time('mysql'),
            'deployed_by' => $user && $user->exists() ? $user->user_login : 'system',
            'is_stable'   => 0,
        ],
        ['%s', '%s', '%s', '%d']
    );
}
add_action('admin_init', 'rmbz_predeploy_record_current_version', 20);


// ============================================================================
// HELPERS
// ============================================================================

function rmbz_predeploy_get_plugin_version() {
    if ( ! function_exists('get_plugin_data') ) {
        require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
    }
    // [1.5.154] Bug fix: antes usava WP_PLUGIN_DIR . '/1mz-for-artists/...'
    // que assumia o nome da pasta. Falhava silenciosamente se a pasta tivesse
    // outro nome (ex: descarregar do GitHub cria pasta com sufixo "-main").
    // Quando isto falhava, a versão devolvia '' e o deploy_log NUNCA registava
    // nada — bug detectado pelo smoke test que warneou "Tabela vazia".
    // Agora resolve dinamicamente: includes/admin/predeploy-hardening.php
    // → ../../1mz-for-artists.php (sobe 3 níveis).
    $main_file = dirname( __FILE__, 3 ) . '/1mz-for-artists.php';
    if ( ! file_exists($main_file) ) return '';
    $data = get_plugin_data( $main_file, false, false );
    return $data['Version'] ?? '';
}

function rmbz_predeploy_snapshots_dir() {
    $upload = wp_upload_dir();
    $dir = trailingslashit( $upload['basedir'] ) . 'rmbz_predeploy_snapshots';
    if ( ! is_dir($dir) ) {
        wp_mkdir_p( $dir );
        // Proteger com .htaccess (Apache) — só admin acede via PHP
        @file_put_contents( $dir . '/.htaccess', "Deny from all\n" );
        @file_put_contents( $dir . '/index.html', '' );
    }
    return $dir;
}


// ============================================================================
// SNAPSHOT — dump SQL das tabelas rmbz_*
// ============================================================================

/**
 * Cria um snapshot da BD: dump SQL de todas as tabelas rmbz_*.
 * Devolve path do ficheiro criado.
 *
 * @return array { success, path, size, tables_dumped, errors }
 */
function rmbz_predeploy_create_snapshot() {
    global $wpdb;
    @set_time_limit(300); // Snapshots de wallets grandes podem demorar

    $version = rmbz_predeploy_get_plugin_version();
    $ts      = date('Ymd_His');
    $dir     = rmbz_predeploy_snapshots_dir();
    $fname   = sprintf('snapshot_v%s_%s.sql', $version, $ts);
    $path    = trailingslashit($dir) . $fname;

    $tables = $wpdb->get_col( "SHOW TABLES LIKE '{$wpdb->prefix}rmbz_%'" );
    if ( empty($tables) ) {
        return [ 'success' => false, 'path' => '', 'size' => 0, 'tables_dumped' => 0, 'errors' => ['Nenhuma tabela rmbz_* encontrada.'] ];
    }

    $fh = @fopen( $path, 'w' );
    if ( ! $fh ) {
        return [ 'success' => false, 'path' => $path, 'size' => 0, 'tables_dumped' => 0, 'errors' => ['Não consegui abrir ficheiro para escrita.'] ];
    }

    $header = sprintf(
        "-- 1MZ Pre-Deploy Snapshot\n-- Plugin Version: %s\n-- Created at: %s\n-- WP Site: %s\n-- Tables: %d\n\nSET FOREIGN_KEY_CHECKS=0;\nSET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';\n\n",
        $version, current_time('mysql'), get_site_url(), count($tables)
    );
    fwrite($fh, $header);

    $errors = [];
    $count = 0;

    foreach ( $tables as $t ) {
        // CREATE TABLE
        $create = $wpdb->get_row( "SHOW CREATE TABLE `$t`", ARRAY_A );
        if ( ! $create ) {
            $errors[] = "Falha ao obter schema de $t";
            continue;
        }
        fwrite($fh, "\n-- ─── Tabela $t ───\nDROP TABLE IF EXISTS `$t`;\n" . $create['Create Table'] . ";\n\n");

        // Dados — em batches de 500 para não rebentar memória
        $offset = 0;
        $batch  = 500;
        while ( true ) {
            $rows = $wpdb->get_results( "SELECT * FROM `$t` LIMIT $batch OFFSET $offset", ARRAY_A );
            if ( empty($rows) ) break;

            foreach ( $rows as $row ) {
                $vals = array_map( function($v) use ($wpdb) {
                    if ( $v === null ) return 'NULL';
                    return "'" . esc_sql( (string) $v ) . "'";
                }, array_values($row) );
                $cols = '`' . implode('`, `', array_keys($row)) . '`';
                fwrite($fh, "INSERT INTO `$t` ($cols) VALUES (" . implode(', ', $vals) . ");\n");
            }
            $offset += $batch;
            if ( count($rows) < $batch ) break;
        }
        $count++;
    }

    fwrite($fh, "\nSET FOREIGN_KEY_CHECKS=1;\n-- End of snapshot\n");
    fclose($fh);

    $size = (int) @filesize($path);

    // Marcar no deploy_log que esta versão tem snapshot
    $deploy_table = rmbz_predeploy_table();
    $wpdb->query( $wpdb->prepare(
        "UPDATE $deploy_table SET snapshot_path = %s
         WHERE version = %s
         ORDER BY id DESC LIMIT 1",
        $fname, $version
    ) );

    return [
        'success'       => true,
        'path'          => $path,
        'fname'         => $fname,
        'size'          => $size,
        'tables_dumped' => $count,
        'errors'        => $errors,
    ];
}


/**
 * Lista snapshots existentes (lê o filesystem).
 */
function rmbz_predeploy_list_snapshots() {
    $dir = rmbz_predeploy_snapshots_dir();
    $files = glob( trailingslashit($dir) . 'snapshot_*.sql' );
    if ( empty($files) ) return [];

    $out = [];
    foreach ( $files as $f ) {
        $out[] = [
            'name'  => basename($f),
            'path'  => $f,
            'size'  => @filesize($f),
            'mtime' => @filemtime($f),
        ];
    }
    // Ordenar do mais recente para o mais antigo
    usort($out, function($a, $b){ return $b['mtime'] - $a['mtime']; });
    return $out;
}


/**
 * Apaga um snapshot pelo nome (validado contra path traversal).
 */
function rmbz_predeploy_delete_snapshot( $fname ) {
    $fname = basename( $fname ); // strip qualquer ../
    if ( ! preg_match('/^snapshot_v[\d.]+_\d{8}_\d{6}\.sql$/', $fname) ) {
        return [ 'success' => false, 'message' => 'Nome de ficheiro inválido.' ];
    }
    $path = trailingslashit( rmbz_predeploy_snapshots_dir() ) . $fname;
    if ( ! file_exists($path) ) {
        return [ 'success' => false, 'message' => 'Snapshot não encontrado.' ];
    }
    if ( @unlink($path) ) {
        return [ 'success' => true, 'message' => 'Snapshot apagado.' ];
    }
    return [ 'success' => false, 'message' => 'Falha ao apagar.' ];
}


// ============================================================================
// HEALTH CHECKS
// ============================================================================

/**
 * Devolve array de checks com estado: ok | warn | fail.
 * Cada check tem: label, status, value, hint
 */
function rmbz_predeploy_run_health_checks() {
    global $wpdb;
    $checks = [];

    // 1) Versão PHP
    $php = PHP_VERSION;
    $php_ok = version_compare($php, '7.4', '>=');
    $php_status = $php_ok ? 'ok' : 'fail';
    $checks[] = [
        'label'  => 'PHP version',
        'status' => $php_status,
        'value'  => $php,
        'hint'   => $php_ok ? 'OK' : 'Plugin requer PHP 7.4+',
    ];

    // 2) Memory limit
    $mem = (int) wp_convert_hr_to_bytes( ini_get('memory_limit') );
    $mem_mb = round($mem / 1024 / 1024);
    $mem_status = $mem >= 256 * 1024 * 1024 ? 'ok' : ($mem >= 128 * 1024 * 1024 ? 'warn' : 'fail');
    $checks[] = [
        'label'  => 'Memory limit',
        'status' => $mem_status,
        'value'  => $mem_mb . ' MB',
        'hint'   => $mem_status === 'ok' ? 'OK' : ($mem_status === 'warn' ? '256MB+ recomendado para imports grandes' : 'Insuficiente — sobe para 256MB'),
    ];

    // 3) Upload max
    $upload = (int) wp_convert_hr_to_bytes( ini_get('upload_max_filesize') );
    $upload_mb = round($upload / 1024 / 1024);
    $upload_status = $upload >= 32 * 1024 * 1024 ? 'ok' : ($upload >= 8 * 1024 * 1024 ? 'warn' : 'fail');
    $checks[] = [
        'label'  => 'Upload max filesize',
        'status' => $upload_status,
        'value'  => $upload_mb . ' MB',
        'hint'   => $upload_status === 'ok' ? 'OK' : 'CSVs grandes podem falhar — sobe para 32MB+',
    ];

    // 4) Disco disponível em uploads
    $upload_dir = wp_upload_dir();
    $free = @disk_free_space($upload_dir['basedir']);
    if ( $free !== false ) {
        $free_gb = round($free / 1024 / 1024 / 1024, 2);
        $disk_status = $free > 1024 * 1024 * 1024 ? 'ok' : ($free > 200 * 1024 * 1024 ? 'warn' : 'fail');
        $checks[] = [
            'label'  => 'Disco livre (uploads)',
            'status' => $disk_status,
            'value'  => $free_gb . ' GB',
            'hint'   => $disk_status === 'ok' ? 'OK' : ($disk_status === 'warn' ? 'Pouco espaço — limpa snapshots antigos' : 'CRÍTICO — uploads vão falhar'),
        ];
    }

    // 5) Tabelas rmbz_* presentes
    $tables = $wpdb->get_col( "SHOW TABLES LIKE '{$wpdb->prefix}rmbz_%'" );
    $checks[] = [
        'label'  => 'Tabelas rmbz_*',
        'status' => count($tables) >= 10 ? 'ok' : (count($tables) >= 5 ? 'warn' : 'fail'),
        'value'  => count($tables) . ' tabelas',
        'hint'   => count($tables) >= 10 ? 'OK' : 'Faltam tabelas — corre installers',
    ];

    // 6) Tabelas críticas presentes
    $required = [
        'rmbz_wallets', 'rmbz_wallet_transactions', 'rmbz_subscriptions',
        'rmbz_deposit_requests', 'rmbz_withdrawal_requests',
        'rmbz_distro_releases', 'rmbz_distro_ledger',
        'rmbz_email_logs',
    ];
    $missing = [];
    foreach ( $required as $r ) {
        $full = $wpdb->prefix . $r;
        if ( $wpdb->get_var("SHOW TABLES LIKE '$full'") !== $full ) {
            $missing[] = $r;
        }
    }
    $checks[] = [
        'label'  => 'Tabelas críticas',
        'status' => empty($missing) ? 'ok' : 'fail',
        'value'  => empty($missing) ? 'todas presentes' : 'faltam: ' . implode(', ', $missing),
        'hint'   => empty($missing) ? 'OK' : 'Tabelas em falta — install incompleto',
    ];

    // 7) Cron jobs registados
    // [1.5.154] Bug fix: nomes de hooks corrigidos.
    //   - rmbz_first_deposit_cleanup_extended NÃO é cron — é função
    //     hooked ao rmbz_unlock_funds_hook (diário).
    //   - rmbz_imports_archive_purge não existe — o real é
    //     rmbz_archive_daily_purge (em includes/admin/import-archive.php:303).
    $crons = _get_cron_array() ?: [];
    $expected_hooks = [
        'rmbz_unlock_funds_hook',     // diário (cron-jobs.php)
        'rmbz_archive_daily_purge',   // diário (import-archive.php) — purge CSVs antigos
    ];
    $registered = [];
    foreach ( $crons as $ts => $hooks ) {
        foreach ( $hooks as $hook => $args ) {
            $registered[] = $hook;
        }
    }
    $cron_missing = array_diff( $expected_hooks, $registered );
    $checks[] = [
        'label'  => 'Cron jobs essenciais',
        'status' => empty($cron_missing) ? 'ok' : 'warn',
        'value'  => empty($cron_missing) ? 'todos registados' : 'faltam: ' . implode(', ', $cron_missing),
        'hint'   => empty($cron_missing) ? 'OK' : 'Crons em falta — re-activar plugin',
    ];

    // 8) WP_DEBUG
    $debug_on = defined('WP_DEBUG') && WP_DEBUG;
    $debug_log_on = defined('WP_DEBUG_LOG') && WP_DEBUG_LOG;
    $checks[] = [
        'label'  => 'WP_DEBUG_LOG',
        'status' => $debug_log_on ? 'ok' : 'warn',
        'value'  => $debug_log_on ? 'activo' : 'desactivo',
        'hint'   => $debug_log_on ? 'OK — erros são gravados em wp-content/debug.log' : 'Activa em wp-config.php para apanhar erros',
    ];

    // 9) Erros recentes no debug.log (últimas 24h)
    $debug_log = WP_CONTENT_DIR . '/debug.log';
    if ( file_exists($debug_log) && is_readable($debug_log) ) {
        $size = @filesize($debug_log);
        $size_mb = round($size / 1024 / 1024, 1);
        // Conta linhas de erro nas últimas 24h
        $recent_errors = 0;
        if ( $size < 50 * 1024 * 1024 ) { // não processar se for > 50MB
            $cutoff = time() - 86400;
            $lines = @file($debug_log);
            if ( $lines ) {
                foreach ( $lines as $line ) {
                    if ( preg_match('/\[(\d{2})-([A-Za-z]+)-(\d{4}) (\d{2}:\d{2}:\d{2})/', $line, $m) ) {
                        $ts = strtotime($m[1] . ' ' . $m[2] . ' ' . $m[3] . ' ' . $m[4]);
                        if ( $ts && $ts >= $cutoff ) {
                            if ( stripos($line, 'PHP Fatal') !== false || stripos($line, 'PHP Error') !== false || stripos($line, 'PHP Warning') !== false ) {
                                $recent_errors++;
                            }
                        }
                    }
                }
            }
        }
        $err_status = $recent_errors === 0 ? 'ok' : ($recent_errors < 10 ? 'warn' : 'fail');
        $checks[] = [
            'label'  => 'Erros nas últimas 24h',
            'status' => $err_status,
            'value'  => $recent_errors . ' erros · log ' . $size_mb . ' MB',
            'hint'   => $recent_errors === 0 ? 'OK' : 'Verifica wp-content/debug.log',
        ];
    } else {
        $checks[] = [
            'label'  => 'debug.log',
            'status' => 'warn',
            'value'  => 'sem ficheiro',
            'hint'   => 'Activa WP_DEBUG_LOG para começar a registar',
        ];
    }

    // 10) Última actividade — depósito ou levantamento nas últimas 24h
    $t_dep = $wpdb->prefix . 'rmbz_deposit_requests';
    if ( $wpdb->get_var("SHOW TABLES LIKE '$t_dep'") === $t_dep ) {
        $last_dep = $wpdb->get_var(
            "SELECT request_date FROM $t_dep ORDER BY id DESC LIMIT 1"
        );
        $age_hours = $last_dep ? round( (time() - strtotime($last_dep)) / 3600, 1 ) : -1;
        if ( $age_hours < 0 ) {
            $checks[] = [
                'label'  => 'Última actividade financeira',
                'status' => 'warn',
                'value'  => 'nunca',
                'hint'   => 'Sistema sem depósitos ainda',
            ];
        } else {
            $act_status = $age_hours < 168 ? 'ok' : 'warn'; // 1 semana
            $checks[] = [
                'label'  => 'Última actividade financeira',
                'status' => $act_status,
                'value'  => $age_hours < 24
                    ? round($age_hours) . 'h atrás'
                    : round($age_hours / 24, 1) . ' dias atrás',
                'hint'   => $act_status === 'ok' ? 'Sistema activo' : 'Sem actividade recente',
            ];
        }
    }

    return $checks;
}


// ============================================================================
// HANDLERS
// ============================================================================

function rmbz_predeploy_handle_actions() {
    if ( ! isset($_POST['rmbz_predeploy_action']) ) return;
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');
    if ( ! check_admin_referer('rmbz_predeploy_action') ) wp_die('Falha de segurança.');

    $action = sanitize_text_field($_POST['rmbz_predeploy_action']);

    if ( $action === 'create_snapshot' ) {
        $r = rmbz_predeploy_create_snapshot();
        $msg = $r['success']
            ? sprintf('✓ Snapshot criado: %s · %d tabelas · %s', $r['fname'], $r['tables_dumped'], size_format($r['size']))
            : '✗ Falha: ' . implode(' / ', $r['errors']);
        set_transient('rmbz_predeploy_notice', [
            'type' => $r['success'] ? 'success' : 'error',
            'msg'  => $msg,
        ], 30);
    }
    elseif ( $action === 'mark_stable' ) {
        global $wpdb;
        $deploy_id = (int) ($_POST['deploy_id'] ?? 0);
        $wpdb->update( rmbz_predeploy_table(), [ 'is_stable' => 1 ], [ 'id' => $deploy_id ], [ '%d' ], [ '%d' ] );
        set_transient('rmbz_predeploy_notice', [ 'type' => 'success', 'msg' => '✓ Versão marcada como estável.' ], 30);
    }
    elseif ( $action === 'unmark_stable' ) {
        global $wpdb;
        $deploy_id = (int) ($_POST['deploy_id'] ?? 0);
        $wpdb->update( rmbz_predeploy_table(), [ 'is_stable' => 0 ], [ 'id' => $deploy_id ], [ '%d' ], [ '%d' ] );
        set_transient('rmbz_predeploy_notice', [ 'type' => 'success', 'msg' => 'Marca de estável removida.' ], 30);
    }
    elseif ( $action === 'delete_snapshot' ) {
        $fname = sanitize_text_field( $_POST['snapshot'] ?? '' );
        $r = rmbz_predeploy_delete_snapshot( $fname );
        set_transient('rmbz_predeploy_notice', [
            'type' => $r['success'] ? 'success' : 'error',
            'msg'  => $r['message'],
        ], 30);
    }

    wp_safe_redirect( admin_url('admin.php?page=rmbz-settings&tab=predeploy') );
    exit;
}
add_action('admin_post_rmbz_predeploy', 'rmbz_predeploy_handle_actions');


/**
 * Endpoint para download de um snapshot. Validado contra path traversal.
 */
function rmbz_predeploy_handle_download() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');
    if ( ! isset($_GET['snapshot']) ) wp_die('Falta o ficheiro.');
    if ( ! check_admin_referer('rmbz_predeploy_download') ) wp_die('Falha de segurança.');

    $fname = basename( sanitize_text_field( $_GET['snapshot'] ) );
    if ( ! preg_match('/^snapshot_v[\d.]+_\d{8}_\d{6}\.sql$/', $fname) ) wp_die('Nome inválido.');

    $path = trailingslashit( rmbz_predeploy_snapshots_dir() ) . $fname;
    if ( ! file_exists($path) ) wp_die('Snapshot não encontrado.');

    header('Content-Type: application/sql');
    header('Content-Disposition: attachment; filename="' . $fname . '"');
    header('Content-Length: ' . filesize($path));
    header('Cache-Control: no-cache, must-revalidate');
    @readfile($path);
    exit;
}
add_action('admin_post_rmbz_predeploy_download', 'rmbz_predeploy_handle_download');


// ============================================================================
// PÁGINA ADMIN
// ============================================================================

/** Corpo do Pré-Deploy — vive como aba das Configurações. */
function rmbz_predeploy_render_body() {
    if ( ! current_user_can('manage_options') ) wp_die('Sem permissão.');

    // Notice flash
    $notice = get_transient('rmbz_predeploy_notice');
    if ( $notice ) {
        delete_transient('rmbz_predeploy_notice');
        $css = $notice['type'] === 'success' ? 'notice-success' : 'notice-error';
        echo '<div class="notice ' . esc_attr($css) . ' is-dismissible" style="margin:14px 0;"><p>' . esc_html($notice['msg']) . '</p></div>';
    }

    $current_version = rmbz_predeploy_get_plugin_version();
    $checks    = rmbz_predeploy_run_health_checks();
    $snapshots = rmbz_predeploy_list_snapshots();
    global $wpdb;
    $deploys = $wpdb->get_results( "SELECT * FROM " . rmbz_predeploy_table() . " ORDER BY id DESC LIMIT 20" );

    $colors = [
        'ok'   => ['var(--rmbz-success, #10b981)', '✓'],
        'warn' => ['var(--rmbz-warning, #f59e0b)', '⚠'],
        'fail' => ['var(--rmbz-danger-strong, #dc2626)', '✗'],
    ];
    ?>
    <div>
        <h2 style="margin-top:6px;">🛡 Pré-Deploy &amp; Hardening</h2>
        <p style="color:var(--rmbz-text-muted, #666);">
            Versão actual: <strong><?php echo esc_html($current_version); ?></strong>.
            Esta página dá-te o estado do sistema e ferramentas para deploys seguros.
        </p>

        <?php /* ─────────── HEALTH DASHBOARD ─────────── */ ?>
        <div class="card" style="padding:18px; max-width:none; margin-top:20px;">
            <h2 style="margin-top:0;">📊 Health Dashboard</h2>
            <table class="widefat striped" style="font-size:13px;">
                <thead>
                    <tr>
                        <th width="50">Estado</th>
                        <th width="240">Verificação</th>
                        <th width="200">Valor</th>
                        <th>Notas</th>
                    </tr>
                </thead>
                <tbody>
                <?php foreach ( $checks as $c ):
                    list($color, $icon) = $colors[ $c['status'] ] ?? $colors['warn'];
                ?>
                    <tr>
                        <td style="text-align:center; font-size:18px; color:<?php echo esc_attr($color); ?>;">
                            <?php echo esc_html($icon); ?>
                        </td>
                        <td><strong><?php echo esc_html($c['label']); ?></strong></td>
                        <td style="font-family:monospace; font-size:12px;"><?php echo esc_html($c['value']); ?></td>
                        <td style="color:var(--rmbz-text-muted, #666); font-size:12px;"><?php echo esc_html($c['hint']); ?></td>
                    </tr>
                <?php endforeach; ?>
                </tbody>
            </table>

            <?php
            $fails = count(array_filter($checks, function($c){ return $c['status'] === 'fail'; }));
            $warns = count(array_filter($checks, function($c){ return $c['status'] === 'warn'; }));
            $oks   = count(array_filter($checks, function($c){ return $c['status'] === 'ok'; }));
            ?>
            <p style="margin-top:14px; font-size:13px;">
                <strong style="color:var(--rmbz-success, #10b981);"><?php echo $oks; ?> OK</strong> ·
                <strong style="color:var(--rmbz-warning, #f59e0b);"><?php echo $warns; ?> warn</strong> ·
                <strong style="color:var(--rmbz-danger-strong, #dc2626);"><?php echo $fails; ?> fail</strong>
                <?php if ( $fails === 0 ): ?>
                    · <span style="color:var(--rmbz-success, #10b981);">✓ Sistema pronto para deploy</span>
                <?php else: ?>
                    · <span style="color:var(--rmbz-danger-strong, #dc2626);">⚠ Resolve os FAIL antes de deploy</span>
                <?php endif; ?>
            </p>
        </div>

        <?php
        /* [1.5.153] Hook para módulos externos (ex: smoke-tests.php)
           injectarem painéis adicionais após o Health Dashboard. */
        do_action( 'rmbz_predeploy_after_health' );
        ?>

        <?php /* ─────────── SNAPSHOT TOOL ─────────── */ ?>
        <div class="card" style="padding:18px; max-width:none; margin-top:20px;">
            <h2 style="margin-top:0;">💾 Snapshots da Base de Dados</h2>
            <p>
                Cria um dump SQL completo de todas as tabelas <code>rmbz_*</code>
                <strong>antes</strong> de fazeres update do plugin.
                Em caso de problema, podes restaurar este snapshot via phpMyAdmin
                (importar o ficheiro .sql).
            </p>
            <p style="background:var(--rmbz-warning-soft, #fef3c7); border-left:4px solid var(--rmbz-warning, #f59e0b); padding:8px 12px; font-size:12px;">
                <strong>⚠ Atenção:</strong> snapshots ficam em
                <code>/uploads/rmbz_predeploy_snapshots/</code> protegido por .htaccess.
                Para restauro, descarrega o .sql e importa via phpMyAdmin
                — o plugin não faz restauro automático (segurança).
            </p>

            <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="margin:14px 0;">
                <input type="hidden" name="action" value="rmbz_predeploy">
                <input type="hidden" name="rmbz_predeploy_action" value="create_snapshot">
                <?php wp_nonce_field('rmbz_predeploy_action'); ?>
                <button type="submit" class="button button-primary"
                        onclick="return confirm('Criar snapshot agora? Pode demorar alguns segundos a minutos consoante o tamanho da BD.');">
                    📸 Criar Snapshot Agora (v<?php echo esc_html($current_version); ?>)
                </button>
                <span style="margin-left:12px; color:var(--rmbz-text-muted, #666); font-size:12px;">
                    Recomendado: criar antes de cada update do plugin.
                </span>
            </form>

            <?php if ( ! empty($snapshots) ): ?>
                <h3 style="margin-top:20px;">Snapshots existentes (<?php echo count($snapshots); ?>)</h3>
                <table class="widefat striped" style="font-size:13px;">
                    <thead>
                        <tr>
                            <th>Ficheiro</th>
                            <th width="120">Tamanho</th>
                            <th width="180">Criado em</th>
                            <th width="240">Acções</th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php foreach ( $snapshots as $s ): ?>
                        <tr>
                            <td><code style="font-size:11px;"><?php echo esc_html($s['name']); ?></code></td>
                            <td><?php echo esc_html( size_format($s['size']) ); ?></td>
                            <td><?php echo esc_html( date_i18n('d/m/Y H:i', $s['mtime']) ); ?></td>
                            <td>
                                <a href="<?php echo esc_url( wp_nonce_url(
                                    admin_url('admin-post.php?action=rmbz_predeploy_download&snapshot=' . urlencode($s['name'])),
                                    'rmbz_predeploy_download'
                                ) ); ?>" class="button button-small">⬇ Download</a>

                                <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline;"
                                      onsubmit="return confirm('Apagar este snapshot? Não podes recuperar.');">
                                    <input type="hidden" name="action" value="rmbz_predeploy">
                                    <input type="hidden" name="rmbz_predeploy_action" value="delete_snapshot">
                                    <input type="hidden" name="snapshot" value="<?php echo esc_attr($s['name']); ?>">
                                    <?php wp_nonce_field('rmbz_predeploy_action'); ?>
                                    <button type="submit" class="button button-small" style="color:var(--rmbz-danger-strong, #dc2626);">🗑 Apagar</button>
                                </form>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            <?php else: ?>
                <p style="color:var(--rmbz-text-muted, #888); margin-top:14px;">Sem snapshots criados ainda.</p>
            <?php endif; ?>
        </div>

        <?php /* ─────────── DEPLOY LOG ─────────── */ ?>
        <div class="card" style="padding:18px; max-width:none; margin-top:20px;">
            <h2 style="margin-top:0;">📜 Histórico de Deploys</h2>
            <p>
                Cada vez que entras no admin com versão diferente da última gravada,
                fica registo aqui. Marca uma versão como <strong>estável</strong> quando
                tens a certeza que está a funcionar bem — para sabes a que voltar caso
                uma versão futura tenha problemas.
            </p>

            <?php if ( empty($deploys) ): ?>
                <p style="color:var(--rmbz-text-muted, #888);">Sem registos de deploy ainda.</p>
            <?php else: ?>
                <table class="widefat striped" style="font-size:13px;">
                    <thead>
                        <tr>
                            <th width="100">Versão</th>
                            <th width="180">Data</th>
                            <th width="140">Por</th>
                            <th width="120">Snapshot</th>
                            <th width="140">Estável</th>
                            <th width="140">Acção</th>
                        </tr>
                    </thead>
                    <tbody>
                    <?php foreach ( $deploys as $d ): ?>
                        <tr style="<?php echo $d->is_stable ? 'background:var(--rmbz-success-soft, #f0fdf4);' : ''; ?>">
                            <td><strong><?php echo esc_html($d->version); ?></strong>
                                <?php if ( $d->version === $current_version ): ?>
                                    <span style="background:var(--rmbz-info, #3b82f6); color:#fff; padding:1px 6px; border-radius:3px; font-size:10px; margin-left:4px;">ACTUAL</span>
                                <?php endif; ?>
                            </td>
                            <td><?php echo esc_html( date_i18n('d/m/Y H:i', strtotime($d->deploy_at)) ); ?></td>
                            <td style="font-family:monospace; font-size:11px;"><?php echo esc_html($d->deployed_by ?: '—'); ?></td>
                            <td>
                                <?php if ( $d->snapshot_path ): ?>
                                    <span style="color:var(--rmbz-success, #10b981);" title="<?php echo esc_attr($d->snapshot_path); ?>">✓ Sim</span>
                                <?php else: ?>
                                    <span style="color:var(--rmbz-text-muted, #888);">—</span>
                                <?php endif; ?>
                            </td>
                            <td>
                                <?php if ( $d->is_stable ): ?>
                                    <span style="color:var(--rmbz-success, #10b981); font-weight:600;">⭐ Estável</span>
                                <?php else: ?>
                                    <span style="color:var(--rmbz-text-muted, #888);">—</span>
                                <?php endif; ?>
                            </td>
                            <td>
                                <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="display:inline;">
                                    <input type="hidden" name="action" value="rmbz_predeploy">
                                    <input type="hidden" name="rmbz_predeploy_action" value="<?php echo $d->is_stable ? 'unmark_stable' : 'mark_stable'; ?>">
                                    <input type="hidden" name="deploy_id" value="<?php echo (int) $d->id; ?>">
                                    <?php wp_nonce_field('rmbz_predeploy_action'); ?>
                                    <button type="submit" class="button button-small">
                                        <?php echo $d->is_stable ? 'Desmarcar' : '⭐ Marcar estável'; ?>
                                    </button>
                                </form>
                            </td>
                        </tr>
                    <?php endforeach; ?>
                    </tbody>
                </table>
            <?php endif; ?>
        </div>

        <?php /* ─────────── ROLLBACK GUIDE ─────────── */ ?>
        <div class="card" style="padding:18px; max-width:none; margin-top:20px; background:var(--rmbz-warning-soft, #fef3c7);">
            <h2 style="margin-top:0;">↩ Como fazer rollback</h2>
            <ol style="line-height:1.8;">
                <li>Identifica a última versão marcada como <strong>⭐ Estável</strong> no histórico acima.</li>
                <li>Procura o ZIP dessa versão no teu repositório local (todas as versões foram empacotadas).</li>
                <li>Faz <strong>backup do estado actual</strong>: cria snapshot antes (botão acima).</li>
                <li>Em caso de corrupção de dados: descarrega o snapshot da versão estável e importa via phpMyAdmin.</li>
                <li>Substitui o ZIP do plugin pela versão estável.</li>
                <li>Verifica este Health Dashboard depois do rollback.</li>
            </ol>
        </div>
    </div>
    <?php
}


// ============================================================================
// MENU
// ============================================================================

// [1.6.348] Sem menu próprio — "Pré-Deploy" passou a ser ABA em Configurações
// 1MZ For Artists ("🛡 Pré-Deploy"), via rmbz_predeploy_render_body().
