<?php
namespace WalletUpPro\Core\Cron;

use WalletUpPro\Core\Error\ErrorHandler;
use WalletUpPro\Core\Security\EnhancedSecurityManager;

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

/**
 * Wallet Options Demo Cleanup Service
 * 
 * Enterprise-grade cleanup service that runs every 30 minutes to reset
 * wallet options for demo purposes, allowing multiple users to experience
 * fresh demo sessions without interference.
 * 
 * Features:
 * - Runs every 30 minutes via WordPress cron
 * - Maintains cleanup counter with detailed logging
 * - Resets demo data and user configurations
 * - Preserves admin settings and core configurations
 * - Enterprise-grade error handling and reporting
 * - Security audit trail
 * - Performance monitoring
 * - Demo mode toggle for production safety
 * 
 * @package WalletUpPro\Core\Cron
 * @since 4.1.0
 */
class WalletOptionsCleanup
{
    /** @var ErrorHandler Error handler instance */
    private $errorHandler;
    
    /** @var EnhancedSecurityManager Security manager instance */
    private $securityManager;
    
    /** @var \wpdb WordPress database instance */
    private $db;
    
    /** @var array Cleanup statistics */
    private $stats = [
        'transients_cleared' => 0,
        'expired_data_removed' => 0,
        'cache_entries_cleared' => 0,
        'temp_files_cleaned' => 0,
        'temp_data_cleared' => 0,
        'settings_reset' => 0,
        'tables_cleared' => 0,
        'analytics_cleared' => 0,
        'execution_time' => 0,
        'memory_before' => 0,
        'memory_after' => 0,
        'errors' => []
    ];
    
    /** @var string Cron hook name */
    private const CRON_HOOK = 'wallet_up_options_cleanup';
    
    /** @var string Counter option name */
    private const COUNTER_OPTION = 'wallet_up_demo_cleanup_counter';
    
    /** @var string Last run option name */
    private const LAST_RUN_OPTION = 'wallet_up_demo_cleanup_last_run';
    
    /** @var string Demo mode option name */
    private const DEMO_MODE_OPTION = 'wallet_up_demo_mode_enabled';
    
    /** @var string Demo cleanup interval option name */
    private const CLEANUP_INTERVAL_OPTION = 'wallet_up_demo_cleanup_interval';
    
    /** @var int Default cleanup interval in minutes */
    private const DEFAULT_CLEANUP_INTERVAL = 30;
    
    /** @var array Demo data to reset at configurable intervals */
    private const DEMO_CLEANUP_TARGETS = [
        'user_data' => [
            'wallet_up_settings', // Reset to demo defaults
            'wallet_up_enabled_methods', // Reset payment methods
            'wallet_up_display_settings', // Reset display settings
        ],
        'demo_transactions' => true, // Clear demo transactions
        'user_sessions' => true, // Clear user sessions
        'analytics_data' => true, // Clear analytics for fresh demos
        'qr_codes_cache' => true, // Clear QR code cache
        'temp_data' => [
            'wallet_up_analytics_*',
            'wallet_up_multi_pay_*',
            'wallet_up_session',
            'wallet_up_rate_limits',
            'walletup_url_creation_logs'
        ],
        'preserve_admin' => [ // Keep these for admin
            'wallet_up_paypal_*', // Keep PayPal settings
            'wallet_up_version', // Keep version info
            'wallet_up_demo_mode_enabled', // Keep demo mode setting
            'woocommerce_wallet_up_settings' // Keep WooCommerce config
        ]
    ];
    
    /**
     * Constructor - Initialize and schedule cleanup
     */
    public function __construct()
    {
        global $wpdb;
        $this->db = $wpdb;
        $this->errorHandler = class_exists('WalletUpPro\Core\Error\ErrorHandler') 
            ? ErrorHandler::getInstance() 
            : null;
        $this->securityManager = class_exists('WalletUpPro\Core\Security\EnhancedSecurityManager') 
            ? EnhancedSecurityManager::getInstance() 
            : null;
        
        $this->registerCronHooks();
        $this->scheduleCleanup();
        
        // Add admin dashboard widget for monitoring
        add_action('wp_dashboard_setup', [$this, 'addDashboardWidget']);
        
        // Add AJAX handlers for demo controls
        add_action('wp_ajax_wallet_up_manual_demo_reset', [$this, 'handleManualReset']);
        add_action('wp_ajax_wallet_up_toggle_demo_mode', [$this, 'handleToggleDemoMode']);
        
        // Add AJAX handler for React component status requests
        add_action('wp_ajax_wallet_up_get_demo_status', [$this, 'handleGetDemoStatus']);
        // Removed: nopriv handler for demo status - admin-only data (F7 fix)
        
        // Add AJAX handler for dismissing demo notice
        add_action('wp_ajax_wallet_up_dismiss_demo_notice', [$this, 'handleDismissNotice']);
        
        // Add AJAX handler for setting cleanup interval
        add_action('wp_ajax_wallet_up_set_cleanup_interval', [$this, 'handleSetCleanupInterval']);
        
        // Add admin notice for demo mode configuration
        add_action('admin_notices', [$this, 'showDemoModeNotice']);
    }
    
    private function registerCronHooks(): void
    {
        add_action(self::CRON_HOOK, [$this, 'executeCleanup']);
        
        // Add custom cron schedule for 30 minutes if it doesn't exist
        add_filter('cron_schedules', [$this, 'addCustomCronSchedule']);
    }
    
    public function addCustomCronSchedule(array $schedules): array
    {
        $interval_minutes = $this->getCleanupInterval();
        $interval_seconds = $interval_minutes * 60;
        $schedule_key = "wallet_up_demo_cleanup_{$interval_minutes}min";
        
        // Add our custom schedule
        $schedules[$schedule_key] = [
            'interval' => $interval_seconds,
            /* translators: %d: Number of minutes between cleanup runs */
            'display' => sprintf(__('Every %d Minutes (Wallet-Up Demo)', 'walletup'), $interval_minutes)
        ];
        
        // Keep legacy 30-minute schedule for compatibility
        if (!isset($schedules['thirty_minutes'])) {
            $schedules['thirty_minutes'] = [
                'interval' => 1800, // 30 minutes in seconds
                'display' => __('Every 30 Minutes', 'walletup')
            ];
        }
        
        return $schedules;
    }
    
    private function getCronScheduleKey(): string
    {
        $interval_minutes = $this->getCleanupInterval();
        return "wallet_up_demo_cleanup_{$interval_minutes}min";
    }
    
    /**
     * Schedule the cleanup if not already scheduled and demo mode is enabled
     */
    private function scheduleCleanup(): void
    {
        // Only schedule if demo mode is enabled
        if (!$this->isDemoModeEnabled()) {
            $this->logInfo('Demo mode disabled - cleanup not scheduled');
            return;
        }
        
        if (!wp_next_scheduled(self::CRON_HOOK)) {
            $schedule_key = $this->getCronScheduleKey();
            $interval_minutes = $this->getCleanupInterval();
            
            $scheduled = wp_schedule_event(time(), $schedule_key, self::CRON_HOOK);
            
            if ($scheduled === false) {
                $this->logError("Failed to schedule wallet options demo cleanup cron job with {$interval_minutes} minute interval");
            } else {
                $this->logInfo("Wallet options demo cleanup scheduled successfully with {$interval_minutes} minute interval");
            }
        }
    }
    
    /**
     * Execute the demo cleanup process
     * 
     * @return array Cleanup statistics
     */
    public function executeCleanup(): array
    {
        $start_time = microtime(true);
        
        // Reset stats for fresh cleanup
        $this->resetStats();
        $this->stats['memory_before'] = memory_get_usage(true);
        
        try {
            // Only run if demo mode is enabled
            if (!$this->isDemoModeEnabled()) {
                $this->logInfo('Demo mode disabled - skipping cleanup');
                return ['skipped' => true, 'reason' => 'Demo mode disabled'];
            }
            
            $this->logInfo('Starting wallet options DEMO cleanup cycle');
            $this->incrementCounter();
            
            // Security audit
            $this->performSecurityAudit();
            
            // Execute demo-specific cleanup operations
            $this->resetDemoSettings();
            $this->clearDemoTransactions();
            $this->cleanupDemoSessions();
            $this->clearAnalyticsData();
            $this->cleanupQRCache();
            $this->cleanupTempData();
            $this->resetDemoDefaults();
            
            // Finalize stats
            $this->stats['execution_time'] = round((microtime(true) - $start_time) * 1000, 2);
            $this->stats['memory_after'] = memory_get_usage(true);
            
            $this->updateLastRunTimestamp();
            $this->logCleanupStats();
            
            $this->logInfo('Demo cleanup completed successfully - ready for new demo users');
            
        } catch (\Exception $e) {
            $this->stats['errors'][] = $e->getMessage();
            $this->logError('Demo cleanup failed: ' . $e->getMessage(), [
                'trace' => $e->getTraceAsString(),
                'stats' => $this->stats
            ]);
        }
        
        return $this->stats;
    }
    
    private function resetStats(): void
    {
        $this->stats = [
            'transients_cleared' => 0,
            'expired_data_removed' => 0,
            'cache_entries_cleared' => 0,
            'temp_files_cleaned' => 0,
            'temp_data_cleared' => 0,
            'settings_reset' => 0,
            'tables_cleared' => 0,
            'analytics_cleared' => 0,
            'execution_time' => 0,
            'memory_before' => 0,
            'memory_after' => 0,
            'errors' => []
        ];
    }
    
    private function isDemoModeEnabled(): bool
    {
        return (bool) get_option(self::DEMO_MODE_OPTION, false);
    }
    
    public function getCleanupInterval(): int
    {
        return (int) get_option(self::CLEANUP_INTERVAL_OPTION, self::DEFAULT_CLEANUP_INTERVAL);
    }
    
    public function setCleanupInterval(int $minutes): bool
    {
        // Validate interval (5 minutes to 24 hours)
        if ($minutes < 5 || $minutes > 1440) {
            $this->logError("Invalid cleanup interval: {$minutes} minutes. Must be between 5 and 1440.");
            return false;
        }
        
        $result = update_option(self::CLEANUP_INTERVAL_OPTION, $minutes);
        
        if ($result) {
            // Reschedule with new interval if demo mode is enabled
            if ($this->isDemoModeEnabled()) {
                $this->unschedule();
                $this->scheduleCleanup();
                $this->logInfo("Demo cleanup rescheduled with {$minutes} minute interval");
            }
        }
        
        return $result;
    }
    
    public function enableDemoMode(): bool
    {
        if (!current_user_can('manage_options')) {
            return false;
        }
        
        $result = update_option(self::DEMO_MODE_OPTION, true);
        if ($result) {
            $this->scheduleCleanup(); // Schedule cleanup when demo mode is enabled
            $this->logInfo('Demo mode enabled - cleanup scheduled');
        }
        return $result;
    }
    
    public function disableDemoMode(): bool
    {
        if (!current_user_can('manage_options')) {
            return false;
        }
        
        $result = update_option(self::DEMO_MODE_OPTION, false);
        if ($result) {
            $this->unschedule(); // Unschedule cleanup when demo mode is disabled
            $this->logInfo('Demo mode disabled - cleanup unscheduled');
        }
        return $result;
    }
    
    private function resetDemoSettings(): void
    {
        $reset_count = 0;
        
        try {
            // Reset main wallet settings to demo defaults
            $demo_defaults = [
                'wallet_up_settings' => $this->getDemoDefaults(),
                'wallet_up_enabled_methods' => ['paypal', 'venmo', 'cashapp'], // Demo payment methods
                'wallet_up_display_settings' => $this->getDemoDisplaySettings()
            ];
            
            // Reset wallet holder settings (the actual payment info users enter)
            $wallet_holders = [
                'cashapp_holder' => '@DemoUser',
                'venmo_holder' => '@DemoVenmo',
                'paypal_holder' => 'demo@walletup.app',
                'fbpay_holder' => 'demo.user',
                'zelle_holder' => 'demo@walletup.app',
                'waluppay_holder' => '@DemoWalletUp',
                'holder_owner' => 'Demo User',
                'holder_email' => 'demo@walletup.app',
                'holder_phone' => '555-DEMO-123'
            ];
            
            // Combine all settings to reset
            $all_settings = array_merge($demo_defaults, $wallet_holders);
            
            foreach ($all_settings as $option => $default_value) {
                if (!empty($option) && $default_value !== null) {
                    $result = update_option($option, $default_value);
                    if ($result) {
                        $reset_count++;
                        $this->logInfo("Reset option: {$option} = {$default_value}");
                    }
                }
            }
            
            $this->stats['settings_reset'] = $reset_count;
            $this->logInfo("Reset {$reset_count} demo settings to defaults (including wallet holders)");
            
        } catch (\Exception $e) {
            $this->stats['settings_reset'] = 0;
            $this->logError("Failed to reset demo settings: " . $e->getMessage());
        }
    }
    
    private function clearDemoTransactions(): void
    {
        $tables_to_clear = [
            $this->db->prefix . 'wallet_up_transactions',
            $this->db->prefix . 'walletup_analytics',
            $this->db->prefix . 'walletup_short_urls'
        ];
        
        $cleared = 0;
        
        try {
            foreach ($tables_to_clear as $table) {
                if (empty($table) || !$this->tableExists($table)) {
                    continue;
                }
                
                // Use DELETE instead of TRUNCATE for better error handling
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Direct query required, caching not applicable.
                $result = $this->db->query("DELETE FROM `{$table}` WHERE 1");
                if ($result !== false) {
                    $cleared++;
                    $this->logInfo("Cleared table: {$table}");
                } else {
                    $this->logError("Failed to clear table: {$table} - " . $this->db->last_error);
                }
            }
            
            $this->stats['tables_cleared'] = $cleared;
            $this->logInfo("Cleared {$cleared} demo transaction tables");
            
        } catch (\Exception $e) {
            $this->stats['tables_cleared'] = 0;
            $this->logError("Failed to clear demo transactions: " . $e->getMessage());
        }
    }
    
    /**
     * Clean up demo sessions
     */
    private function cleanupDemoSessions(): void
    {
        // Clear all user sessions except admin
        $admin_users = get_users(['role' => 'administrator']);
        $admin_ids = array_map(function($user) { return $user->ID; }, $admin_users);
        
        if (!empty($admin_ids)) {
            $admin_placeholders = implode(',', array_fill(0, count($admin_ids), '%d'));
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Direct query required, caching not applicable.
            $this->db->query(
                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Prepared query with safe table name.
                $this->db->prepare(
                    // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name is safely derived from wpdb prefix.
                    "DELETE FROM {$this->db->usermeta} 
                     WHERE meta_key = 'session_tokens' 
                     AND user_id NOT IN ({$admin_placeholders})",
                    ...$admin_ids
                )
            );
        }
        
        // Clear frontend sessions
        $this->cleanupWordPressUserSessions();
        
        $this->logInfo('Cleared demo user sessions (preserved admin sessions)');
    }
    
    private function clearAnalyticsData(): void
    {
        $analytics_keys = [
            'wallet_up_analytics_daily',
            'wallet_up_analytics_weekly', 
            'wallet_up_analytics_monthly',
            'wallet_up_analytics_stats',
            'wallet_up_analytics_summary'
        ];
        
        $cleared = 0;
        foreach ($analytics_keys as $key) {
            if (delete_transient($key)) {
                $cleared++;
            }
        }
        
        $this->stats['analytics_cleared'] = $cleared;
        $this->logInfo("Cleared {$cleared} analytics cache entries");
    }
    
    /**
     * Clean up temporary data
     */
    private function cleanupTempData(): void
    {
        $cleared = 0;
        
        // Add null check for safety
        $patterns = self::DEMO_CLEANUP_TARGETS['temp_data'] ?? [];
        
        foreach ($patterns as $pattern) {
            if (empty($pattern)) continue; // Skip empty patterns
            
            if (strpos($pattern, '*') !== false) {
                $prefix = str_replace('*', '', $pattern);
                $cleared += $this->deleteTransientsByPrefix($prefix);
            } else {
                if (delete_transient($pattern)) {
                    $cleared++;
                }
            }
        }
        
        $this->stats['temp_data_cleared'] = $cleared;
        $this->logInfo("Cleared {$cleared} temporary data entries");
    }
    
    private function resetDemoDefaults(): void
    {
        // Set demo-specific welcome message
        update_option('wallet_up_demo_welcome_message', 
            'Welcome to Wallet-Up Pro Demo! This environment resets every 30 minutes.'
        );
        
        // Reset demo user preferences
        update_option('wallet_up_demo_last_reset', current_time('timestamp'));
        
        $this->logInfo('Applied demo default configurations');
    }
    
    private function getDemoDefaults(): array
    {
        return [
            'demo_mode' => true,
            'payment_methods' => ['paypal', 'venmo', 'cashapp'],
            'display_mode' => 'qr_only',
            'theme' => 'default',
            'auto_generate_qr' => true,
            'demo_message' => 'This is a demo environment - data resets every 30 minutes'
        ];
    }
    
    private function getDemoDisplaySettings(): array
    {
        return [
            'show_qr_code' => true,
            'show_amount_field' => true,
            'show_description' => true,
            'theme' => 'modern',
            'size' => 'medium',
            'demo_banner' => true
        ];
    }
    
    /**
     * Clean up WordPress transients (legacy method for compatibility)
     */
    private function cleanupTransients(): void
    {
        $cleared = 0;
        
        // Use temp_data from DEMO_CLEANUP_TARGETS for compatibility
        $patterns = self::DEMO_CLEANUP_TARGETS['temp_data'] ?? [];
        
        foreach ($patterns as $pattern) {
            if (strpos($pattern, '*') !== false) {
                // Handle wildcard patterns
                $prefix = str_replace('*', '', $pattern);
                $cleared += $this->deleteTransientsByPrefix($prefix);
            } else {
                // Handle exact matches
                if (delete_transient($pattern)) {
                    $cleared++;
                }
            }
        }
        
        $this->stats['transients_cleared'] = $cleared;
        $this->logInfo("Cleared {$cleared} transients");
    }
    
    /**
     * Clean up expired short URLs
     */
    private function cleanupExpiredUrls(): void
    {
        $table_name = $this->db->prefix . 'walletup_short_urls';
        
        if ($this->tableExists($table_name)) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Direct query required, caching not applicable.
            $deleted = $this->db->query(
                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name is safely derived from wpdb prefix.
                "DELETE FROM {$table_name} WHERE expires_at < NOW() AND expires_at IS NOT NULL"
            );
            
            $this->stats['expired_data_removed'] = $deleted ?: 0;
            $this->logInfo("Removed {$this->stats['expired_data_removed']} expired URLs");
        }
    }
    
    /**
     * Clean up temporary session data
     */
    private function cleanupTempSessions(): void
    {
        // Clean PHP sessions older than 30 minutes
        $session_path = session_save_path();
        if (!empty($session_path) && is_dir($session_path)) {
            $files = glob($session_path . '/sess_*');
            $cleaned = 0;
            
            foreach ($files as $file) {
                if (filemtime($file) < (time() - 1800)) { // 30 minutes
                    wp_delete_file($file);
                    if (!file_exists($file)) {
                        $cleaned++;
                    }
                }
            }
            
            $this->stats['temp_files_cleaned'] += $cleaned;
        }
        
        // Clean WordPress user sessions
        $this->cleanupWordPressUserSessions();
    }
    
    /**
     * Clean up analytics cache
     */
    private function cleanupAnalyticsCache(): void
    {
        $cache_cleared = 0;
        
        // Clear analytics transients older than 30 minutes
        $analytics_keys = [
            'wallet_up_analytics_daily',
            'wallet_up_analytics_weekly',
            'wallet_up_analytics_monthly',
            'wallet_up_analytics_stats'
        ];
        
        foreach ($analytics_keys as $key) {
            if (delete_transient($key)) {
                $cache_cleared++;
            }
        }
        
        $this->stats['cache_entries_cleared'] += $cache_cleared;
    }
    
    /**
     * Clean up QR code cache
     */
    private function cleanupQRCache(): void
    {
        // Clean QR code transients
        $qr_patterns = [
            'wallet_up_qr_',
            'walletup_qr_cache_',
            'wallet_up_qr_generation_'
        ];
        
        $cleared = 0;
        foreach ($qr_patterns as $pattern) {
            $cleared += $this->deleteTransientsByPrefix($pattern);
        }
        
        $this->stats['cache_entries_cleared'] += $cleared;
    }
    
    /**
     * Clean up temporary files
     */
    private function cleanupTempFiles(): void
    {
        $temp_dirs = [
            WP_CONTENT_DIR . '/uploads/wallet-up-temp/',
            WP_CONTENT_DIR . '/cache/wallet-up/',
            sys_get_temp_dir() . '/wallet-up-pro/'
        ];
        
        $cleaned = 0;
        foreach ($temp_dirs as $dir) {
            if (is_dir($dir)) {
                $cleaned += $this->cleanupTempDirectory($dir);
            }
        }
        
        $this->stats['temp_files_cleaned'] += $cleaned;
    }
    
    /**
     * Clean up WordPress user sessions older than 30 minutes
     */
    private function cleanupWordPressUserSessions(): void
    {
        $user_sessions_table = $this->db->prefix . 'usermeta';
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Direct query required, caching not applicable.
        $deleted = $this->db->query(
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Prepared query with safe table name.
            $this->db->prepare(
                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name is safely derived from wpdb prefix.
                "DELETE FROM {$user_sessions_table} 
                 WHERE meta_key = 'session_tokens' 
                 AND DATE_ADD(FROM_UNIXTIME(
                     SUBSTRING_INDEX(
                         SUBSTRING_INDEX(meta_value, '\"expiration\";i:', -1), 
                         ';', 1
                     )
                 ), INTERVAL 30 MINUTE) < NOW()"
            )
        );
        
        if ($deleted) {
            $this->stats['expired_data_removed'] += $deleted;
        }
    }
    
    private function deleteTransientsByPrefix(string $prefix): int
    {
        $deleted = 0;
        
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Fresh data required for accurate results.
        $transients = $this->db->get_results(
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Prepared query with safe table name.
            $this->db->prepare(
                // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name is safely derived from wpdb prefix.
                "SELECT option_name FROM {$this->db->options} 
                 WHERE option_name LIKE %s 
                 AND option_name NOT LIKE %s",
                '_transient_' . $prefix . '%',
                '_transient_timeout_%'
            )
        );
        
        foreach ($transients as $transient) {
            $key = str_replace('_transient_', '', $transient->option_name);
            if (delete_transient($key)) {
                $deleted++;
            }
        }
        
        return $deleted;
    }
    
    /**
     * Clean up temporary directory
     * 
     * @param string $dir Directory path
     * @return int Number of files cleaned
     */
    private function cleanupTempDirectory(string $dir): int
    {
        $cleaned = 0;
        $cutoff_time = time() - 1800; // 30 minutes ago
        
        if (!is_dir($dir)) {
            return 0;
        }
        
        $iterator = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($dir, \RecursiveDirectoryIterator::SKIP_DOTS)
        );
        
        foreach ($iterator as $file) {
            if ($file->isFile() && $file->getMTime() < $cutoff_time) {
                wp_delete_file($file->getPathname());
                if (!file_exists($file->getPathname())) {
                    $cleaned++;
                }
            }
        }
        
        return $cleaned;
    }
    
    private function tableExists(string $table_name): bool
    {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Fresh data required for accurate results.
        $result = $this->db->get_var(
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Table name/variable is safely derived.
            $this->db->prepare("SHOW TABLES LIKE %s", $table_name)
        );
        return $result === $table_name;
    }
    
    /**
     * Increment cleanup counter
     */
    private function incrementCounter(): void
    {
        $counter = get_option(self::COUNTER_OPTION, 0);
        update_option(self::COUNTER_OPTION, $counter + 1);
    }
    
    public function getCounter(): int
    {
        return (int) get_option(self::COUNTER_OPTION, 0);
    }
    
    private function updateLastRunTimestamp(): void
    {
        update_option(self::LAST_RUN_OPTION, current_time('timestamp'));
    }
    
    public function getLastRun()
    {
        return get_option(self::LAST_RUN_OPTION, false);
    }
    
    /**
     * Perform security audit
     */
    private function performSecurityAudit(): void
    {
        if ($this->securityManager) {
            $this->securityManager->auditAction('wallet_cleanup_started', [
                'counter' => $this->getCounter(),
                'scheduled_time' => current_time('c'),
                'memory_usage' => $this->stats['memory_before']
            ]);
        }
    }
    
    private function logCleanupStats(): void
    {
        $stats_message = sprintf(
            'Cleanup #%d completed | Transients: %d | Expired: %d | Cache: %d | Temp: %d | Time: %sms | Memory: %s',
            $this->getCounter(),
            $this->stats['transients_cleared'],
            $this->stats['expired_data_removed'],
            $this->stats['cache_entries_cleared'],
            $this->stats['temp_files_cleaned'],
            $this->stats['execution_time'],
            $this->formatBytes($this->stats['memory_after'] - $this->stats['memory_before'])
        );
        
        $this->logInfo($stats_message, $this->stats);
    }
    
    public function addDashboardWidget(): void
    {
        if (current_user_can('manage_options')) {
            wp_add_dashboard_widget(
                'wallet_up_cleanup_status',
                __('Wallet-Up Cleanup Status', 'walletup'),
                [$this, 'displayDashboardWidget']
            );
        }
    }
    
    public function displayDashboardWidget(): void
    {
        $counter = $this->getCounter();
        $last_run = $this->getLastRun();
        $next_run = wp_next_scheduled(self::CRON_HOOK);
        $demo_mode = $this->isDemoModeEnabled();
        
        echo '<div class="wallet-up-cleanup-widget">';
        
        // Demo mode status
        echo '<p><strong>' . esc_html__('Demo Mode:', 'walletup') . '</strong> ';
        if ($demo_mode) {
            echo '<span style="color: green;">✓ ' . esc_html__('ENABLED', 'walletup') . '</span>';
        } else {
            echo '<span style="color: red;">✗ ' . esc_html__('DISABLED', 'walletup') . '</span>';
        }
        echo '</p>';

        if ($demo_mode) {
            echo '<p><strong>' . esc_html__('Demo Resets:', 'walletup') . '</strong> ' . intval($counter) . '</p>';

            if ($last_run) {
                echo '<p><strong>' . esc_html__('Last Reset:', 'walletup') . '</strong> ' .
                     esc_html(human_time_diff($last_run)) . ' ' . esc_html__('ago', 'walletup') . '</p>';
            }

            if ($next_run) {
                echo '<p><strong>' . esc_html__('Next Reset:', 'walletup') . '</strong> ' .
                     esc_html(human_time_diff($next_run)) . ' ' . esc_html__('from now', 'walletup') . '</p>';
            }

            echo '<p><em>' . esc_html__('Demo environment resets every 30 minutes', 'walletup') . '</em></p>';

            // Manual reset button for admins
            if (current_user_can('manage_options')) {
                echo '<p><button type="button" class="button button-secondary" onclick="walletUpManualReset()">' .
                     esc_html__('Reset Now', 'walletup') . '</button></p>';

                // Toggle demo mode buttons
                echo '<p>';
                echo '<button type="button" class="button" onclick="walletUpToggleDemoMode(false)">' .
                     esc_html__('Disable Demo Mode', 'walletup') . '</button>';
                echo '</p>';
            }
        } else {
            echo '<p><em>' . esc_html__('Enable demo mode to start automatic resets', 'walletup') . '</em></p>';

            if (current_user_can('manage_options')) {
                echo '<p><button type="button" class="button button-primary" onclick="walletUpToggleDemoMode(true)">' .
                     esc_html__('Enable Demo Mode', 'walletup') . '</button></p>';
            }
        }
        
        echo '</div>';
        
        // Add JavaScript for button actions
        ?>
        <script>
        function walletUpManualReset() {
            if (confirm('<?php echo esc_js(__('Are you sure you want to reset the demo environment now?', 'walletup')); ?>')) {
                jQuery.post(ajaxurl, {
                    action: 'wallet_up_manual_demo_reset',
                    nonce: '<?php echo esc_attr(wp_create_nonce('wallet_up_demo_nonce')); ?>'
                }, function(response) {
                    if (response.success) {
                        alert('<?php echo esc_js(__('Demo environment reset successfully!', 'walletup')); ?>');
                        location.reload();
                    } else {
                        // Handle structured error response
                        let errorMessage = '<?php echo esc_js(__('Reset failed: ', 'walletup')); ?>';
                        if (response.data && typeof response.data === 'object') {
                            errorMessage += response.data.message || 'Unknown error';
                        } else {
                            errorMessage += response.data || 'Unknown error';
                        }
                        alert(errorMessage);
                    }
                });
            }
        }
        
        function walletUpToggleDemoMode(enable) {
            const action = enable ? 'enable' : 'disable';
            const message = enable ? 
                '<?php echo esc_js(__('Enable demo mode? This will start automatic resets every 30 minutes.', 'walletup')); ?>' :
                '<?php echo esc_js(__('Disable demo mode? Automatic resets will stop.', 'walletup')); ?>';
                
            if (confirm(message)) {
                jQuery.post(ajaxurl, {
                    action: 'wallet_up_toggle_demo_mode',
                    enable: enable ? 1 : 0,
                    nonce: '<?php echo esc_attr(wp_create_nonce('wallet_up_demo_nonce')); ?>'
                }, function(response) {
                    if (response.success) {
                        location.reload();
                    } else {
                        // Handle structured error response
                        let errorMessage = '<?php echo esc_js(__('Action failed: ', 'walletup')); ?>';
                        if (response.data && typeof response.data === 'object') {
                            errorMessage += response.data.message || 'Unknown error';
                        } else {
                            errorMessage += response.data || 'Unknown error';
                        }
                        alert(errorMessage);
                    }
                });
            }
        }
        </script>
        <?php
    }
    
    public function getStatus(): array
    {
        return [
            'counter' => $this->getCounter(),
            'last_run' => $this->getLastRun(),
            'next_run' => wp_next_scheduled(self::CRON_HOOK),
            'is_scheduled' => wp_next_scheduled(self::CRON_HOOK) !== false,
            'last_stats' => $this->stats
        ];
    }
    
    /**
     * Manual cleanup trigger (for testing/admin)
     * 
     * @return array Cleanup results
     */
    public function manualCleanup(): array
    {
        if (!current_user_can('manage_options')) {
            return ['error' => 'Insufficient permissions'];
        }
        
        return $this->executeCleanup();
    }
    
    private function formatBytes(int $bytes): string
    {
        if ($bytes === 0) return '0 B';
        
        $units = ['B', 'KB', 'MB', 'GB'];
        $factor = floor((strlen($bytes) - 1) / 3);
        
        return sprintf("%.2f %s", $bytes / pow(1024, $factor), $units[$factor]);
    }
    
    private function logInfo(string $message, array $context = []): void
    {
        if ($this->errorHandler) {
        } else {
        }
    }
    
    private function logError(string $message, array $context = []): void
    {
        if ($this->errorHandler) {
        } else {
        }
    }
    
    /**
     * Unschedule cleanup (for deactivation)
     */
    public function unschedule(): void
    {
        $timestamp = wp_next_scheduled(self::CRON_HOOK);
        if ($timestamp) {
            wp_unschedule_event($timestamp, self::CRON_HOOK);
        }
    }
    
    public function resetCounter(): bool
    {
        if (!current_user_can('manage_options')) {
            return false;
        }
        
        return update_option(self::COUNTER_OPTION, 0);
    }
    
    public function handleManualReset(): void
    {
        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'wallet_up_demo_nonce') || 
            !current_user_can('manage_options')) {
            wp_send_json_error([
                'message' => 'Unauthorized',
                'code' => 'UNAUTHORIZED'
            ]);
            return;
        }
        
        if (!$this->isDemoModeEnabled()) {
            wp_send_json_error([
                'message' => 'Demo mode is not enabled',
                'code' => 'DEMO_MODE_DISABLED'
            ]);
            return;
        }
        
        try {
            $result = $this->executeCleanup();
            
            // Store stats for future reference
            update_option('wallet_up_demo_last_stats', wp_json_encode($result));
            
            wp_send_json_success([
                'message' => 'Demo environment reset successfully',
                'stats' => $result,
                'timestamp' => current_time('c')
            ]);
        } catch (\Exception $e) {
            wp_send_json_error([
                'message' => 'Reset failed: ' . $e->getMessage(),
                'code' => 'RESET_ERROR',
                'error_details' => [
                    'file' => $e->getFile(),
                    'line' => $e->getLine()
                ]
            ]);
        }
    }
    
    public function handleToggleDemoMode(): void
    {
        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'wallet_up_demo_nonce') || 
            !current_user_can('manage_options')) {
            wp_send_json_error([
                'message' => 'Unauthorized',
                'code' => 'UNAUTHORIZED'
            ]);
            return;
        }
        
        $enable = !empty($_POST['enable']);
        
        try {
            if ($enable) {
                $result = $this->enableDemoMode();
                $message = 'Demo mode enabled successfully';
            } else {
                $result = $this->disableDemoMode();
                $message = 'Demo mode disabled successfully';
            }
            
            if ($result) {
                wp_send_json_success([
                    'message' => $message,
                    'demo_enabled' => $enable
                ]);
            } else {
                wp_send_json_error([
                    'message' => 'Failed to update demo mode',
                    'code' => 'UPDATE_FAILED'
                ]);
            }
        } catch (\Exception $e) {
            wp_send_json_error([
                'message' => 'Action failed: ' . $e->getMessage(),
                'code' => 'EXCEPTION'
            ]);
        }
    }
    
    public function handleGetDemoStatus(): void
    {
        try {
            // Basic security check (less strict for status requests)
            $nonce_check = wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'wallet_up_demo_nonce');
            
            // Get current status
            $counter = $this->getCounter();
            $lastRun = $this->getLastRun();
            $nextRun = wp_next_scheduled(self::CRON_HOOK);
            $isDemoEnabled = $this->isDemoModeEnabled();
            $isScheduled = $nextRun !== false;
            
            // Get timing information
            $clientTime = intval(wp_unslash($_POST['client_time'] ?? time()) * 1000);
            $serverTime = time() * 1000; // Server time in milliseconds
            $includeTiming = !empty($_POST['include_timing']);
            
            $response_data = [
                'is_demo_enabled' => $isDemoEnabled,
                'counter' => $counter,
                'last_run' => $lastRun,
                'next_run' => $nextRun,
                'is_scheduled' => $isScheduled,
                'last_stats' => $this->getLastStats(),
                'server_time' => $serverTime,
                'cleanup_interval' => $this->getCleanupInterval()
            ];
            
            // Add timing details if requested
            if ($includeTiming) {
                $response_data['timing'] = [
                    'client_time' => $clientTime,
                    'server_time' => $serverTime,
                    'time_diff' => $serverTime - $clientTime,
                    'next_run_relative' => $nextRun ? ($nextRun * 1000) - $serverTime : null
                ];
            }
            
            wp_send_json_success($response_data);
            
        } catch (\Exception $e) {
            wp_send_json_error([
                'message' => 'Failed to get demo status: ' . $e->getMessage(),
                'code' => 'STATUS_ERROR'
            ]);
        }
    }
    
    private function getLastStats(): ?array
    {
        $stats = get_option('wallet_up_demo_last_stats', null);
        return $stats ? json_decode($stats, true) : null;
    }
    
    public function showDemoModeNotice(): void
    {
        // Only show on Wallet-Up admin pages and for administrators
        if (!current_user_can('manage_options') || !$this->isWalletUpAdminPage()) {
            return;
        }
        
        $isDemoEnabled = $this->isDemoModeEnabled();
        $dismissedNotice = get_user_meta(get_current_user_id(), 'wallet_up_demo_notice_dismissed', true);
        
        // Show notice if demo mode is disabled and user hasn't dismissed it
        if (!$isDemoEnabled && !$dismissedNotice) {
            ?>
            <div class="notice notice-info is-dismissible" id="wallet-up-demo-notice">
                <h3><?php esc_html_e('Wallet-Up Demo Mode', 'walletup'); ?></h3>
                <p>
                    <?php esc_html_e('Enable demo mode to showcase automatic environment resets every 30 minutes. Perfect for demonstrations and testing.', 'walletup'); ?>
                </p>
                <p>
                    <button type="button" class="button button-primary" onclick="walletUpEnableDemoMode()">
                        <?php esc_html_e('Enable Demo Mode', 'walletup'); ?>
                    </button>
                    <button type="button" class="button button-secondary" onclick="walletUpDismissNotice()">
                        <?php esc_html_e('Dismiss', 'walletup'); ?>
                    </button>
                </p>
            </div>
            
            <script>
            function walletUpEnableDemoMode() {
                if (confirm('<?php echo esc_js(__('Enable demo mode? This will start automatic resets every 30 minutes.', 'walletup')); ?>')) {
                    jQuery.post(ajaxurl, {
                        action: 'wallet_up_toggle_demo_mode',
                        enable: 1,
                        nonce: '<?php echo esc_attr(wp_create_nonce('wallet_up_demo_nonce')); ?>'
                    }, function(response) {
                        if (response.success) {
                            location.reload();
                        } else {
                            alert('<?php echo esc_js(__('Failed to enable demo mode. Please try again.', 'walletup')); ?>');
                        }
                    });
                }
            }
            
            function walletUpDismissNotice() {
                jQuery('#wallet-up-demo-notice').fadeOut();
                jQuery.post(ajaxurl, {
                    action: 'wallet_up_dismiss_demo_notice',
                    nonce: '<?php echo esc_attr(wp_create_nonce('wallet_up_demo_nonce')); ?>'
                });
            }
            </script>
            <?php
        }
    }
    
    private function isWalletUpAdminPage(): bool
    {
        $screen = get_current_screen();
        if (!$screen) {
            return false;
        }
        
        return strpos($screen->id, 'walletup') !== false || 
               strpos($screen->id, 'wallet_up') !== false ||
               // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Admin screen check only; no data processing.
               (isset($_GET['page']) && strpos(sanitize_text_field(wp_unslash($_GET['page'])), 'walletup') !== false);
    }
    
    
    public function handleDismissNotice(): void
    {
        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'wallet_up_demo_nonce') || 
            !current_user_can('manage_options')) {
            wp_send_json_error(['message' => 'Unauthorized']);
            return;
        }
        
        // Set user meta to remember dismissal
        $result = update_user_meta(get_current_user_id(), 'wallet_up_demo_notice_dismissed', true);
        
        if ($result !== false) {
            wp_send_json_success(['message' => 'Notice dismissed']);
        } else {
            wp_send_json_error(['message' => 'Failed to dismiss notice']);
        }
    }
    
    public function handleSetCleanupInterval(): void
    {
        if (!wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'] ?? '')), 'wallet_up_demo_nonce') || 
            !current_user_can('manage_options')) {
            wp_send_json_error([
                'message' => 'Unauthorized',
                'code' => 'UNAUTHORIZED'
            ]);
            return;
        }
        
        $interval = intval(wp_unslash($_POST['interval'] ?? 0));
        
        if ($interval < 5 || $interval > 1440) {
            wp_send_json_error([
                'message' => 'Invalid interval. Must be between 5 and 1440 minutes.',
                'code' => 'INVALID_INTERVAL'
            ]);
            return;
        }
        
        try {
            $result = $this->setCleanupInterval($interval);
            
            if ($result) {
                wp_send_json_success([
                    'message' => "Cleanup interval set to {$interval} minutes",
                    'interval' => $interval,
                    'next_run' => wp_next_scheduled(self::CRON_HOOK)
                ]);
            } else {
                wp_send_json_error([
                    'message' => 'Failed to update cleanup interval',
                    'code' => 'UPDATE_FAILED'
                ]);
            }
        } catch (\Exception $e) {
            wp_send_json_error([
                'message' => 'Error updating interval: ' . $e->getMessage(),
                'code' => 'EXCEPTION'
            ]);
        }
    }
}