<?php

/**
 * Scheduled Actions functionality for Wuclean plugin
 *
 * @package Wuclean
 */
if ( !defined( 'ABSPATH' ) ) {
    exit;
}
/**
 * Scheduled Actions page with Settings tab
 */
function pt_wuclean_render_scheduled_actions_page() {
    // Verify nonce - required for security (CSRF protection).
    if ( isset( $_GET['tab'] ) ) {
        if ( isset( $_GET['_wpnonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'wuclean-scheduled-tab' ) ) {
            $current_tab = sanitize_text_field( wp_unslash( $_GET['tab'] ) );
        } else {
            // Nonce verification failed - default to settings tab for security.
            $current_tab = 'settings';
        }
    } else {
        $current_tab = 'settings';
    }
    // Validate tab value.
    $valid_tabs = array('settings');
    if ( !in_array( $current_tab, $valid_tabs, true ) ) {
        $current_tab = 'settings';
    }
    echo '<div class="wrap">';
    echo '<h1>⏰ ' . esc_html__( 'Scheduled Actions', 'wuclean-database-cleaner-for-woocommerce' ) . '</h1>';
    // Tab navigation.
    echo '<nav class="nav-tab-wrapper">';
    echo '<a href="' . esc_url( add_query_arg( array(
        'page'     => 'wuclean-scheduled-actions',
        'tab'      => 'settings',
        '_wpnonce' => wp_create_nonce( 'wuclean-scheduled-tab' ),
    ), admin_url( 'admin.php' ) ) ) . '" class="nav-tab' . (( 'settings' === $current_tab ? ' nav-tab-active' : '' )) . '">' . esc_html__( 'Settings', 'wuclean-database-cleaner-for-woocommerce' ) . '</a>';
    echo '</nav>';
    // Standard inner wrapper for all tabs (max width + side padding).
    echo '<div class="pt-wuclean-page-inner" style="max-width: 1600px; box-sizing: border-box;">';
    if ( 'settings' === $current_tab ) {
        pt_wuclean_render_scheduled_actions_settings_tab();
    }
    echo '</div>';
    // Close inner wrapper.
    echo '</div>';
}

/**
 * Scheduled Actions Settings Tab
 */
function pt_wuclean_render_scheduled_actions_settings_tab() {
    if ( !current_user_can( pt_wuclean_get_required_capability() ) ) {
        wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'wuclean-database-cleaner-for-woocommerce' ) );
    }
    // Handle form submission.
    if ( isset( $_POST['pt_wuclean_scheduled_actions_settings_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['pt_wuclean_scheduled_actions_settings_nonce'] ) ), 'pt_wuclean_save_scheduled_actions_settings' ) ) {
        $settings = get_option( 'pt_wuclean_settings', array() );
        // Delete settings - only save days if checkbox is checked.
        $settings['delete_completed_actions_days'] = ( isset( $_POST['enable_delete_completed_actions'] ) ? absint( wp_unslash( $_POST['delete_completed_actions_days'] ?? 7 ) ) : 0 );
        $settings['delete_failed_actions_days'] = ( isset( $_POST['enable_delete_failed_actions'] ) ? absint( wp_unslash( $_POST['delete_failed_actions_days'] ?? 7 ) ) : 0 );
        // Action Scheduler logs retention (days) - only save if checkbox enabled.
        $settings['delete_as_logs_days'] = ( isset( $_POST['enable_delete_as_logs'] ) ? absint( wp_unslash( $_POST['delete_as_logs_days'] ?? 0 ) ) : 0 );
        update_option( 'pt_wuclean_settings', $settings, false );
        echo '<div class="notice notice-success"><p>' . esc_html__( 'Scheduled Actions cleanup settings saved successfully!', 'wuclean-database-cleaner-for-woocommerce' ) . '</p></div>';
    }
    $settings = get_option( 'pt_wuclean_settings', array() );
    $delete_completed_actions_days = $settings['delete_completed_actions_days'] ?? 0;
    $delete_failed_actions_days = $settings['delete_failed_actions_days'] ?? 0;
    $delete_as_logs_days = $settings['delete_as_logs_days'] ?? 0;
    echo '<div style="margin-top:2em; max-width: 1600px;">';
    echo '<h2>⚙️ ' . esc_html__( 'Scheduled Actions Cleanup Settings', 'wuclean-database-cleaner-for-woocommerce' ) . '</h2>';
    // Info box.
    echo '<div style="max-width: 1600px; background: #e7f3ff; border: 1px solid #2196f3; border-radius: 4px; padding: 15px; margin: 20px 0;">';
    echo '<p style="margin: 0 0 10px 0;"><strong>ℹ️ ' . esc_html__( 'About Scheduled Actions Cleanup:', 'wuclean-database-cleaner-for-woocommerce' ) . '</strong> ' . esc_html__( 'Scheduled Actions are usually cleaned after 30 days by Woo. However, busy stores can accumulate thousands of records in 30 days. This cleanup routine allows quicker deletion of selected scheduled actions at different ages.', 'wuclean-database-cleaner-for-woocommerce' );
    if ( pt_wuclean_fs()->is_not_paying() ) {
        echo ' ' . esc_html__( 'Automate this with Wuclean Pro👑', 'wuclean-database-cleaner-for-woocommerce' );
    }
    echo '</p>';
    echo '</div>';
    echo '<form method="post" class="wuclean">';
    wp_nonce_field( 'pt_wuclean_save_scheduled_actions_settings', 'pt_wuclean_scheduled_actions_settings_nonce' );
    // Settings card.
    echo '<div style="background: #fff; border: 1px solid #ccd0d4; border-radius: 4px; padding: 20px; margin: 20px 0; max-width: 1600px;">';
    echo '<h3 style="margin-top: 0;">📋 ' . esc_html__( 'Shared Scan Settings (Manual + Scheduled)', 'wuclean-database-cleaner-for-woocommerce' ) . '</h3>';
    echo '<table class="form-table"><tbody>';
    // Delete Completed Actions.
    echo '<tr><th scope="row" style="width: 300px;">' . esc_html__( 'Delete completed actions', 'wuclean-database-cleaner-for-woocommerce' ) . ' <span class="pt-wuclean-tooltip">?<span class="pt-wuclean-tooltip-text">' . esc_html__( 'Delete successfully completed actions after the specified number of days.', 'wuclean-database-cleaner-for-woocommerce' ) . '</span></span></th><td>';
    echo '<input type="checkbox" name="enable_delete_completed_actions" value="1"' . checked( $delete_completed_actions_days > 0, true, false ) . '> ';
    echo '<input type="number" name="delete_completed_actions_days" min="1" max="30" value="' . esc_attr( ( $delete_completed_actions_days > 0 ? $delete_completed_actions_days : 7 ) ) . '" style="width: 70px;"> ' . esc_html__( 'days old', 'wuclean-database-cleaner-for-woocommerce' );
    echo '</td></tr>';
    // Delete Failed Actions.
    echo '<tr><th scope="row" style="width: 300px;">' . esc_html__( 'Delete failed actions', 'wuclean-database-cleaner-for-woocommerce' ) . ' <span class="pt-wuclean-tooltip">?<span class="pt-wuclean-tooltip-text">' . esc_html__( 'Delete failed actions after the specified number of days.', 'wuclean-database-cleaner-for-woocommerce' ) . '</span></span></th><td>';
    echo '<input type="checkbox" name="enable_delete_failed_actions" value="1"' . checked( $delete_failed_actions_days > 0, true, false ) . '> ';
    echo '<input type="number" name="delete_failed_actions_days" min="1" max="30" value="' . esc_attr( ( $delete_failed_actions_days > 0 ? $delete_failed_actions_days : 7 ) ) . '" style="width: 70px;"> ' . esc_html__( 'days old', 'wuclean-database-cleaner-for-woocommerce' );
    echo '</td></tr>';
    // Action Scheduler Logs Retention.
    echo '<tr><th scope="row" style="width: 300px;">' . esc_html__( 'Delete action scheduler logs', 'wuclean-database-cleaner-for-woocommerce' ) . ' <span class="pt-wuclean-tooltip">?<span class="pt-wuclean-tooltip-text">' . esc_html__( 'Delete Action Scheduler database log entries older than the specified number of days. This is separate from WooCommerce Logs retention.', 'wuclean-database-cleaner-for-woocommerce' ) . '</span></span></th><td>';
    echo '<input type="checkbox" name="enable_delete_as_logs" value="1"' . checked( $delete_as_logs_days > 0, true, false ) . '> ';
    echo '<input type="number" name="delete_as_logs_days" min="1" max="365" value="' . esc_attr( ( $delete_as_logs_days > 0 ? $delete_as_logs_days : 30 ) ) . '" style="width: 70px;"> ' . esc_html__( 'days old', 'wuclean-database-cleaner-for-woocommerce' );
    echo '</td></tr>';
    echo '</tbody></table>';
    echo '<p style="margin-bottom: 0;"><input type="submit" class="button button-primary" value="' . esc_attr__( 'Save Settings', 'wuclean-database-cleaner-for-woocommerce' ) . '"></p>';
    echo '</div>';
    // Close settings card.
    echo '</form>';
    // Manual Cleanup Section.
    echo '<div style="background: #fff; border: 1px solid #ccd0d4; border-radius: 4px; padding: 20px; margin: 20px 0; max-width: 1600px;">';
    echo '<h3 style="margin-top: 0;">🔍 ' . esc_html__( 'Manual Scheduled Action Cleanup', 'wuclean-database-cleaner-for-woocommerce' ) . '</h3>';
    echo '<p>' . esc_html__( 'Run the scheduled action cleanup immediately based on your settings above. This will delete completed and failed actions according to the criteria you\'ve configured.', 'wuclean-database-cleaner-for-woocommerce' ) . '</p>';
    echo '<p style="font-size: 13px; color: #666;"><em>' . esc_html__( 'Note: No email notification will be sent.', 'wuclean-database-cleaner-for-woocommerce' ) . '</em></p>';
    echo '<button type="button" id="pt-run-scheduled-actions-cleanup" class="button button-primary" style="background: #2196f3; border-color: #2196f3;">▶️ ' . esc_html__( 'Run Cleanup Now', 'wuclean-database-cleaner-for-woocommerce' ) . '</button>';
    echo '<div id="pt-scheduled-actions-result" style="display:none; margin-top:15px;"></div>';
    echo '</div>';
    // Close manual cleanup card.
    // Free version: progressive disclosure for automation benefits (Settings tab only).
    $pro_benefits = array(__( 'Schedule automatic cleanup of Scheduled Actions daily', 'wuclean-database-cleaner-for-woocommerce' ), __( 'Receive email notifications of cleanup actions, counts and file sizes', 'wuclean-database-cleaner-for-woocommerce' ));
    pt_wuclean_render_pro_automation_callout( $pro_benefits, 'scheduled-actions-settings' );
    echo '</div>';
}

/**
 * Acquire a short-lived lock to prevent overlapping scheduled actions cleanups.
 *
 * @return bool True if lock acquired, false if already locked.
 */
function pt_wuclean_scheduled_actions_cleanup_lock_acquire() {
    $lock_key = 'pt_wuclean_scheduled_actions_cleanup_lock';
    $locked = get_transient( $lock_key );
    if ( !empty( $locked ) ) {
        return false;
    }
    // 15 minutes is long enough for typical cleanup runs, and short enough to self-heal.
    set_transient( $lock_key, time(), 15 * MINUTE_IN_SECONDS );
    return true;
}

/**
 * Release the scheduled actions cleanup lock.
 *
 * @return void
 */
function pt_wuclean_scheduled_actions_cleanup_lock_release() {
    delete_transient( 'pt_wuclean_scheduled_actions_cleanup_lock' );
}

/**
 * Get scheduled actions counts
 */
function pt_wuclean_get_scheduled_actions_counts() {
    global $wpdb;
    $counts = array(
        'pending'   => 0,
        'failed'    => 0,
        'completed' => 0,
        'total'     => 0,
    );
    // Get counts for each status.
    $status_counts = $wpdb->get_results( "SELECT status, COUNT(*) as count \n         FROM {$wpdb->actionscheduler_actions} \n         GROUP BY status" );
    foreach ( $status_counts as $row ) {
        // Map Action Scheduler statuses to our expected keys.
        switch ( $row->status ) {
            case 'pending':
                $counts['pending'] = intval( $row->count );
                break;
            case 'complete':
                $counts['completed'] = intval( $row->count );
                break;
            case 'failed':
                $counts['failed'] = intval( $row->count );
                break;
            case 'in-progress':
            case 'canceled':
                // Include these in total but not in specific categories.
                break;
        }
    }
    $counts['total'] = $counts['pending'] + $counts['failed'] + $counts['completed'];
    return $counts;
}

/**
 * Apply scheduled actions and Action Scheduler log retention from plugin settings.
 *
 * @param array $settings `pt_wuclean_settings` option array (expects delete_* keys).
 * @return array{
 *     before_counts: array<string, int>,
 *     after_counts: array<string, int>,
 *     deleted_completed: int,
 *     deleted_failed: int,
 *     deleted_logs: int
 * }
 */
function pt_wuclean_apply_scheduled_actions_retention_from_settings(  array $settings  ) {
    global $wpdb;
    $before_counts = pt_wuclean_get_scheduled_actions_counts();
    $deleted_completed = 0;
    $deleted_failed = 0;
    $deleted_logs = 0;
    $delete_completed_days = (int) ($settings['delete_completed_actions_days'] ?? 0);
    $delete_failed_days = (int) ($settings['delete_failed_actions_days'] ?? 0);
    $actions_table_escaped = esc_sql( $wpdb->actionscheduler_actions );
    if ( $delete_completed_days > 0 ) {
        $completed_cutoff = gmdate( 'Y-m-d H:i:s', strtotime( '-' . $delete_completed_days . ' days' ) );
        $deleted_completed = (int) $wpdb->query( $wpdb->prepare( 
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name escaped.
            "DELETE FROM {$actions_table_escaped} WHERE status = 'complete' AND scheduled_date_local < %s",
            $completed_cutoff
         ) );
    }
    if ( $delete_failed_days > 0 ) {
        $failed_cutoff = gmdate( 'Y-m-d H:i:s', strtotime( '-' . $delete_failed_days . ' days' ) );
        $deleted_failed = (int) $wpdb->query( $wpdb->prepare( 
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name escaped.
            "DELETE FROM {$actions_table_escaped} WHERE status = 'failed' AND scheduled_date_local < %s",
            $failed_cutoff
         ) );
    }
    $after_counts = pt_wuclean_get_scheduled_actions_counts();
    $delete_as_logs_days = (int) ($settings['delete_as_logs_days'] ?? 0);
    if ( $delete_as_logs_days > 0 ) {
        $logs_table_escaped = esc_sql( $wpdb->prefix . 'actionscheduler_logs' );
        $actions_table_for_join = esc_sql( $wpdb->actionscheduler_actions );
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $deleted_logs = (int) $wpdb->query( $wpdb->prepare( 
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name escaped.
            "DELETE FROM {$logs_table_escaped} WHERE log_date_gmt < (UTC_TIMESTAMP() - INTERVAL %d DAY)",
            $delete_as_logs_days
         ) );
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Action Scheduler cleanup.
        $deleted_logs += (int) $wpdb->query( 
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table names escaped.
            "DELETE l FROM {$logs_table_escaped} l LEFT JOIN {$actions_table_for_join} a ON a.action_id = l.action_id WHERE a.action_id IS NULL"
         );
        if ( $deleted_logs > 0 ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $logs_table_escaped from esc_sql
            $wpdb->query( "OPTIMIZE TABLE {$logs_table_escaped}" );
        }
    }
    return array(
        'before_counts'     => $before_counts,
        'after_counts'      => $after_counts,
        'deleted_completed' => $deleted_completed,
        'deleted_failed'    => $deleted_failed,
        'deleted_logs'      => $deleted_logs,
    );
}

/**
 * Get Action Scheduler DB (logs table) size and count.
 * Separate helper to present data under the Action Scheduler section.
 *
 * @return array<string, float|int>|string Array with count and size_mb, or empty string if the table is missing.
 */
function pt_wuclean_get_action_scheduler_db_info() {
    global $wpdb;
    $logs_table = $wpdb->prefix . 'actionscheduler_logs';
    $logs_table_escaped = esc_sql( $logs_table );
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $logs_table_escaped from esc_sql
    $table_exists = $wpdb->get_var( "SHOW TABLES LIKE '{$logs_table_escaped}'" ) === $logs_table;
    if ( !$table_exists ) {
        return '';
    }
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $logs_table_escaped from esc_sql
    $logs_count = intval( $wpdb->get_var( "SELECT COUNT(*) FROM {$logs_table_escaped}" ) );
    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- $logs_table_escaped from esc_sql
    $logs_size = (float) $wpdb->get_var( "SELECT ROUND(((data_length + index_length) / 1024 / 1024), 2) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = '{$logs_table_escaped}'" );
    return array(
        'count'   => $logs_count,
        'size_mb' => $logs_size,
    );
}

/**
 * Get WooCommerce Logs (filesystem) folder info: count and size.
 *
 * @param bool $html If true, return HTML; otherwise return JSON-encoded array.
 * @return string HTML, or JSON with count and size_bytes, or empty string.
 */
function pt_wuclean_get_wc_logs_folder_info(  $html = false  ) {
    // Determine log directory.
    if ( function_exists( 'wc_get_log_dir' ) ) {
        $dir = wc_get_log_dir();
    } else {
        $uploads = wp_get_upload_dir();
        $dir = trailingslashit( $uploads['basedir'] ) . 'wc-logs/';
    }
    // Normalize path.
    $dir = trailingslashit( $dir );
    $count = 0;
    $size_bytes = 0;
    if ( is_dir( $dir ) && is_readable( $dir ) ) {
        // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, Squiz.PHP.DiscouragedFunctions.Discouraged -- scandir can fail on invalid dir; we check is_dir/is_readable and handle false.
        $files = @scandir( $dir );
        if ( $files && is_array( $files ) ) {
            foreach ( $files as $file ) {
                if ( '.' === $file || '..' === $file ) {
                    continue;
                }
                $path = $dir . $file;
                if ( is_file( $path ) ) {
                    ++$count;
                    // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged, Squiz.PHP.DiscouragedFunctions.Discouraged -- filesize can fail; we check false and skip.
                    $filesize = @filesize( $path );
                    if ( false !== $filesize ) {
                        $size_bytes += $filesize;
                    }
                }
            }
        }
    }
    $size_human = size_format( $size_bytes, 2 );
    if ( $html ) {
        $wc_status_url = admin_url( 'admin.php?page=wc-status' );
        $out = '<strong><a href="' . esc_url( $wc_status_url ) . '">' . esc_html__( 'WooCommerce → Status', 'wuclean-database-cleaner-for-woocommerce' ) . '</a></strong> (' . esc_html__( 'Logs tab', 'wuclean-database-cleaner-for-woocommerce' ) . ')<br>';
        /* translators: %s: formatted number of log files */
        $out .= __( 'Size:', 'wuclean-database-cleaner-for-woocommerce' ) . ' ' . esc_html( $size_human ) . ' (' . sprintf( __( '%s files', 'wuclean-database-cleaner-for-woocommerce' ), number_format_i18n( $count ) ) . ')<br>';
        /* translators: %s: WooCommerce Status screen URL */
        $out .= '<em>' . sprintf( __( 'Log retention: open <a href="%s">WooCommerce → Status</a>, Logs tab, then Settings.', 'wuclean-database-cleaner-for-woocommerce' ), esc_url( $wc_status_url ) ) . '</em>';
        return $out;
    }
    return wp_json_encode( array(
        'count'      => $count,
        'size_bytes' => $size_bytes,
    ) );
}

/**
 * AJAX handler for manual scheduled actions cleanup
 */
function pt_wuclean_ajax_run_scheduled_actions_cleanup() {
    // Check nonce.
    if ( !isset( $_POST['nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'pt_wuclean_scheduled_actions_cleanup' ) ) {
        wp_send_json_error( array(
            'message' => __( 'Invalid nonce', 'wuclean-database-cleaner-for-woocommerce' ),
        ) );
        return;
    }
    // Check permissions.
    if ( !current_user_can( pt_wuclean_get_required_capability() ) ) {
        wp_send_json_error( array(
            'message' => __( 'Insufficient permissions', 'wuclean-database-cleaner-for-woocommerce' ),
        ) );
        return;
    }
    if ( !pt_wuclean_scheduled_actions_cleanup_lock_acquire() ) {
        wp_send_json_error( __( 'Another cleanup is already running. Please wait for it to finish.', 'wuclean-database-cleaner-for-woocommerce' ) );
        return;
    }
    $settings = get_option( 'pt_wuclean_settings', array() );
    $result = pt_wuclean_apply_scheduled_actions_retention_from_settings( $settings );
    $deleted_completed = $result['deleted_completed'];
    $deleted_failed = $result['deleted_failed'];
    $deleted_logs = $result['deleted_logs'];
    $after_counts = $result['after_counts'];
    // Build summary message.
    $message = '<div class="notice notice-success" style="padding: 10px; background: #fff; border-left: 4px solid #46b450;">';
    $message .= '<strong>' . __( 'Cleanup completed successfully!', 'wuclean-database-cleaner-for-woocommerce' ) . '</strong><br><br>';
    $deleted_anything = $deleted_completed > 0 || $deleted_failed > 0 || $deleted_logs > 0;
    if ( $deleted_anything ) {
        $message .= __( 'Deleted:', 'wuclean-database-cleaner-for-woocommerce' ) . '<br>';
        if ( $deleted_completed > 0 ) {
            // translators: %d: number of completed actions.
            $message .= '• ' . sprintf( __( '%d completed actions', 'wuclean-database-cleaner-for-woocommerce' ), $deleted_completed ) . '<br>';
        }
        if ( $deleted_failed > 0 ) {
            // translators: %d: number of failed actions.
            $message .= '• ' . sprintf( __( '%d failed actions', 'wuclean-database-cleaner-for-woocommerce' ), $deleted_failed ) . '<br>';
        }
        if ( $deleted_logs > 0 ) {
            // translators: %d: number of deleted Action Scheduler logs.
            $message .= '• ' . sprintf( __( '%d action scheduler logs', 'wuclean-database-cleaner-for-woocommerce' ), $deleted_logs ) . '<br>';
        }
        $message .= '<br>';
    } else {
        $message .= __( 'No actions or logs were deleted.', 'wuclean-database-cleaner-for-woocommerce' ) . '<br><br>';
    }
    // Action Scheduler section (same link pattern as cleanup email).
    $wc_status_url = admin_url( 'admin.php?page=wc-status' );
    $message .= '<br><strong><a href="' . esc_url( $wc_status_url ) . '">' . esc_html__( 'WooCommerce → Status', 'wuclean-database-cleaner-for-woocommerce' ) . '</a></strong> (' . esc_html__( 'Scheduled Actions tab', 'wuclean-database-cleaner-for-woocommerce' ) . ')<br>';
    /* translators: %d: number of pending scheduled actions */
    $message .= '• ' . sprintf( __( 'Pending: %d', 'wuclean-database-cleaner-for-woocommerce' ), $after_counts['pending'] ) . '<br>';
    /* translators: %d: number of completed scheduled actions */
    $message .= '• ' . sprintf( __( 'Completed: %d', 'wuclean-database-cleaner-for-woocommerce' ), $after_counts['completed'] ) . '<br>';
    /* translators: %d: number of failed scheduled actions */
    $message .= '• ' . sprintf( __( 'Failed: %d', 'wuclean-database-cleaner-for-woocommerce' ), $after_counts['failed'] ) . '<br>';
    $db_stats = pt_wuclean_get_action_scheduler_db_info();
    if ( is_array( $db_stats ) ) {
        /* translators: %s: formatted number of scheduler logs */
        $message .= '• ' . sprintf( __( 'Logs: %s', 'wuclean-database-cleaner-for-woocommerce' ), number_format_i18n( intval( $db_stats['count'] ) ) ) . '<br>';
        /* translators: %s: table size in megabytes */
        $message .= '• ' . sprintf( __( 'Size: %s MB', 'wuclean-database-cleaner-for-woocommerce' ), esc_html( number_format_i18n( $db_stats['size_mb'], 2 ) ) ) . '<br>';
    }
    // WC Logs section.
    $wc_logs_html = pt_wuclean_get_wc_logs_folder_info( true );
    if ( !empty( $wc_logs_html ) ) {
        $message .= '<br>' . $wc_logs_html;
    }
    $message .= '</div>';
    pt_wuclean_scheduled_actions_cleanup_lock_release();
    wp_send_json_success( array(
        'message' => wp_kses_post( $message ),
    ) );
}

// Register AJAX action.
add_action( 'wp_ajax_pt_wuclean_run_scheduled_actions_cleanup', 'pt_wuclean_ajax_run_scheduled_actions_cleanup' );
/**
 * Enqueue scripts for scheduled actions page.
 *
 * @param string $hook The current admin page hook.
 */
function pt_wuclean_enqueue_scheduled_actions_scripts(  $hook  ) {
    // Support both historical and current menu hook names so the inline script
    // is loaded regardless of whether the parent slug is "wuclean" (older free
    // versions) or "wuclean-database-cleaner-for-woocommerce" (current builds).
    if ( 'wuclean-database-cleaner-for-woocommerce_page_wuclean-scheduled-actions' !== $hook && 'wuclean_page_wuclean-scheduled-actions' !== $hook ) {
        return;
    }
    wp_enqueue_script(
        'pt-wuclean-common',
        plugin_dir_url( __FILE__ ) . 'assets/js/common.js',
        array('jquery'),
        '1.0.0',
        true
    );
    wp_add_inline_script( 'pt-wuclean-common', "\n        jQuery(document).ready(function(\$) {\n            \$('#pt-run-scheduled-actions-cleanup').on('click', function() {\n                var button = \$(this);\n                var resultDiv = \$('#pt-scheduled-actions-result');\n                var btnRunning = '" . esc_js( __( 'Running...', 'wuclean-database-cleaner-for-woocommerce' ) ) . "';\n                var btnReady = '" . esc_js( __( 'Run Cleanup Now', 'wuclean-database-cleaner-for-woocommerce' ) ) . "';\n                var errGeneric = '" . esc_js( __( 'An error occurred. Please try again.', 'wuclean-database-cleaner-for-woocommerce' ) ) . "';\n\n                button.prop('disabled', true).text(btnRunning);\n                resultDiv.hide();\n\n                \$.ajax({\n                    url: ajaxurl,\n                    type: 'POST',\n                    data: {\n                        action: 'pt_wuclean_run_scheduled_actions_cleanup',\n                        nonce: '" . wp_create_nonce( 'pt_wuclean_scheduled_actions_cleanup' ) . "'\n                    },\n                    success: function(response) {\n                        if (response && response.success && response.data && response.data.message) {\n                            if (typeof ptWucleanSetKsesTrustedNoticeHtml === 'function') {\n                                ptWucleanSetKsesTrustedNoticeHtml(resultDiv, response.data.message);\n                            } else {\n                                resultDiv.empty().html(response.data.message).show();\n                            }\n                        } else if (response && !response.success) {\n                            var err = (typeof ptWucleanCoerceAjaxMessage === 'function')\n                                ? ptWucleanCoerceAjaxMessage(response.data, '')\n                                : '';\n                            if (err) {\n                                resultDiv.empty().append(\$('<div>', { class: 'notice notice-error' }).append(\$('<p>').text(err)));\n                                resultDiv.show();\n                            } else {\n                                resultDiv.empty().hide();\n                            }\n                        } else {\n                            resultDiv.empty().hide();\n                        }\n                        button.prop('disabled', false).text(btnReady);\n                    },\n                    error: function() {\n                        resultDiv.empty().append(\$('<div>', { class: 'notice notice-error' }).append(\$('<p>').text(errGeneric)));\n                        resultDiv.show();\n                        button.prop('disabled', false).text(btnReady);\n                    }\n                });\n            });\n        });\n    " );
}

add_action( 'admin_enqueue_scripts', 'pt_wuclean_enqueue_scheduled_actions_scripts' );