<?php
defined('ABSPATH') || exit;

/**
 * Update specific plugins or themes
 */
function wpsec_update_items_endpoint($request) {
    // Get parameters
    $items = $request->get_param('items');
    $type = $request->get_param('type'); // 'plugin' or 'theme'
    
    if (!$items || !$type || !is_array($items)) {
        return new WP_Error('invalid_request', 'Invalid request parameters', ['status' => 400]);
    }
    
    // Make sure the webhooks file is included
    if (!function_exists('wpsec_send_update_item_progress_webhook')) {
        require_once(WPSEC_PLUGIN_DIR . 'includes/webhooks.php');
    }
    
    // Set up data for background processing
    $items_to_update = [];
    foreach ($items as $item) {
        $slug = sanitize_text_field(is_array($item) ? $item['slug'] : $item);
        
        // Send initial progress webhook
        wpsec_send_update_item_progress_webhook($slug, 'in-progress');
        
        // Store for processing
        $items_to_update[] = [
            'slug' => $slug,
            'type' => $type
        ];
    }
    
    // Store the items to update in a transient for background processing
    set_transient('wpsec_items_updating', $items_to_update, 3600);
    
    // Set up background processing - run on shutdown after sending response
    add_action('shutdown', function() {
        // Prevent PHP from stopping the script when the client disconnects
        ignore_user_abort(true);
        
        // Remove time limit so the process can complete
        set_time_limit(0);
        
        // Send headers to close the connection and flush the output buffer
        if (!headers_sent()) {
            header('Connection: close');
        }
        
        // Flush the output buffer
        if (ob_get_level()) {
            ob_end_flush();
            flush();
        }
        
        // Get the items to update
        $items_to_update = get_transient('wpsec_items_updating');
        delete_transient('wpsec_items_updating');
        
        if (!empty($items_to_update) && is_array($items_to_update)) {
            foreach ($items_to_update as $item) {
                wpsec_process_individual_update($item['slug'], $item['type']);
            }
        }
    });
    
    // Return immediately with success response
    return rest_ensure_response([
        'success' => true,
        'message' => 'Update process initiated for ' . count($items) . ' items',
        'items' => array_map(function($item) {
            return sanitize_text_field(is_array($item) ? $item['slug'] : $item);
        }, $items)
    ]);
}

/**
 * Process an individual plugin or theme update in the background
 * 
 * @param string $slug The slug of the item to update
 * @param string $type Either 'plugin' or 'theme'
 */
function wpsec_process_individual_update($slug, $type) {
    wpsec_debug_log('🔄 Starting background update for ' . $type . ' ' . $slug, 'info');
    
    // Include required WordPress core files
    require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
    require_once(ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php');
    require_once(ABSPATH . 'wp-admin/includes/class-theme-upgrader.php');
    require_once(ABSPATH . 'wp-admin/includes/update.php');
    require_once(ABSPATH . 'wp-admin/includes/file.php');
    require_once(WPSEC_PLUGIN_DIR . 'includes/class-wpsec-upgrader-skin.php');
    
    if (!function_exists('activate_plugin')) {
        require_once(ABSPATH . 'wp-admin/includes/plugin.php');
    }
    
    // Make sure webhook functions are available
    if (!function_exists('wpsec_send_update_item_complete_webhook')) {
        require_once(WPSEC_PLUGIN_DIR . 'includes/webhooks.php');
    }
    
    // Force refresh of update data
    wp_update_plugins();
    wp_update_themes();

    // Get all installed plugins/themes for reference
    if ($type === 'plugin') {
        $installed_items = wpsec_get_installed_plugins();
    } else {
        $installed_items = wpsec_get_installed_themes();
    }
    
    // Create lookup table for installed items
    $installed_lookup = [];
    foreach ($installed_items as $item) {
        $installed_lookup[$item['slug']] = $item;
    }

    // Temporarily grant necessary capabilities
    $old_user = wp_get_current_user();
    $temp_admin = new WP_User(0);
    $temp_admin->allcaps = array(
        'update_plugins' => true,
        'update_themes' => true,
        'install_plugins' => true,
        'install_themes' => true,
        'activate_plugins' => true,
        'edit_plugins' => true,
        'edit_themes' => true,
        'delete_plugins' => true,
        'delete_themes' => true,
        'manage_options' => true,
        'administrator' => true
    );
    $GLOBALS['current_user'] = $temp_admin;
    
    // Create upgrader instances with our custom skin
    $skin = new WPSEC_Upgrader_Skin();
    $plugin_upgrader = new Plugin_Upgrader($skin);
    $theme_upgrader = new Theme_Upgrader($skin);
    
    $success = false;
    $error_message = '';
    
    if ($type === 'plugin') {
        if (!isset($installed_lookup[$slug])) {
            $error_message = 'Plugin not found';
        } else {
            $plugin_file = $installed_lookup[$slug]['path'];
            $was_active = is_plugin_active($plugin_file);
            
            try {
                // Make sure we have filesystem credentials
                WP_Filesystem();
                
                // Clear previous messages
                $skin->messages = array();
                
                // Send progress update
                wpsec_send_update_item_progress_webhook($slug, 'updating');
                
                // Use Plugin_Upgrader with our custom skin
                $update = $plugin_upgrader->upgrade($plugin_file);
                $success = $update !== false && !is_wp_error($update);
                
                if ($success) {
                    // Reactivate if it was active before
                    if ($was_active) {
                        $activate_result = activate_plugin($plugin_file);
                        if (is_wp_error($activate_result)) {
                            wpsec_debug_log('⚠️ Failed to reactivate plugin ' . $plugin_file . ': ' . $activate_result->get_error_message(), 'error');
                        }
                    }
                    
                    // Get new version after update
                    if (!function_exists('get_plugin_data')) {
                        require_once(ABSPATH . 'wp-admin/includes/plugin.php');
                    }
                    $new_plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin_file);
                    wpsec_debug_log('✅ Plugin ' . $slug . ' updated successfully to version ' . $new_plugin_data['Version'], 'info');
                } else {
                    $error_message = is_wp_error($update) ? $update->get_error_message() : 'Update failed';
                    wpsec_debug_log('❌ Failed to update plugin ' . $slug . ': ' . $error_message, 'error');
                }
            } catch (Exception $e) {
                $error_message = $e->getMessage();
                wpsec_debug_log('❌ Exception updating plugin ' . $slug . ': ' . $error_message, 'error');
            }
        }
    } else if ($type === 'theme') {
        if (!isset($installed_lookup[$slug])) {
            $error_message = 'Theme not found';
        } else {
            try {
                // Make sure we have filesystem credentials
                WP_Filesystem();
                
                // Clear previous messages
                $skin->messages = array();
                
                // Send progress update
                wpsec_send_update_item_progress_webhook($slug, 'updating');
                
                // Use Theme_Upgrader with our custom skin
                $update = $theme_upgrader->upgrade($slug);
                $success = $update !== false && !is_wp_error($update);
                
                if ($success) {
                    // Get new version after update
                    $theme = wp_get_theme($slug);
                    wpsec_debug_log('✅ Theme ' . $slug . ' updated successfully to version ' . $theme->get('Version'), 'info');
                } else {
                    $error_message = is_wp_error($update) ? $update->get_error_message() : 'Update failed';
                    wpsec_debug_log('❌ Failed to update theme ' . $slug . ': ' . $error_message, 'error');
                }
            } catch (Exception $e) {
                $error_message = $e->getMessage();
                wpsec_debug_log('❌ Exception updating theme ' . $slug . ': ' . $error_message, 'error');
            }
        }
    }
    
    // Restore original user
    $GLOBALS['current_user'] = $old_user;
    
    // Purge vulnerabilities cache after updates
    wpsec_purge_vulnerability_cache();
    
    // Send appropriate completion webhook based on result
    if ($success) {
        wpsec_send_update_item_complete_webhook($slug);
    } else {
        wpsec_send_update_item_failed_webhook($slug, $error_message);
    }
    
    wpsec_debug_log('🏁 Completed background update process for ' . $type . ' ' . $slug, 'info');
}

/**
 * Update all available updates for plugins and themes
 * 
 * @param WP_REST_Request $request The request object
 * @return WP_REST_Response The response object
 */
function wpsec_update_all_endpoint($request) {
    // Include required WordPress core files for initial setup
    require_once(ABSPATH . 'wp-admin/includes/update.php');
    
    // Check if update_id is provided in the request
    $body = $request->get_json_params();
    $update_id = isset($body['update_id']) ? sanitize_text_field($body['update_id']) : '';
    
    // If no update_id provided, generate one
    if (empty($update_id)) {
        $update_id = 'upd_' . time() . '_' . substr(md5(uniqid(wp_rand(), true)), 0, 8);
    }
    
    // Force refresh of update data
    wp_update_plugins();
    wp_update_themes();
    
    // Get the available updates
    $plugins = get_site_transient('update_plugins');
    $themes = get_site_transient('update_themes');
    
    $updating_items = [];
    
    // Prepare the list of plugins to be updated
    if (!empty($plugins->response)) {
        foreach ($plugins->response as $plugin_file => $plugin_data) {
            $updating_items[] = [
                'slug' => dirname($plugin_file),
                'status' => 'in-progress',
                'error' => null,
                'type' => 'plugin',
                'file' => $plugin_file
            ];
        }
    }
    
    // Prepare the list of themes to be updated
    if (!empty($themes->response)) {
        foreach ($themes->response as $theme_slug => $theme_data) {
            $updating_items[] = [
                'slug' => $theme_slug,
                'status' => 'in-progress',
                'error' => null,
                'type' => 'theme'
            ];
        }
    }
    
    // If we have items to update, send the initial progress webhook
    if (!empty($updating_items)) {
        // Include the webhook functions
        if (!function_exists('wpsec_send_update_progress_webhook')) {
            require_once(WPSEC_PLUGIN_DIR . 'includes/webhooks.php');
        }
        
        // Send initial progress webhook
        wpsec_send_update_progress_webhook($update_id, $updating_items);
        
        // Store update data for background processing
        set_transient('wpsec_bulk_update_' . $update_id, [
            'update_id' => $update_id,
            'items' => $updating_items
        ], 3600);
        
        // Set up background processing - run on shutdown after sending response
        add_action('shutdown', function() use ($update_id) {
            // Prevent PHP from stopping the script when the client disconnects
            ignore_user_abort(true);
            
            // Remove time limit so the process can complete
            set_time_limit(0);
            
            // Send headers to close the connection and flush the output buffer
            if (!headers_sent()) {
                header('Connection: close');
            }
            
            // Flush the output buffer
            if (ob_get_level()) {
                ob_end_flush();
                flush();
            }
            
            // Get the update data
            $update_data = get_transient('wpsec_bulk_update_' . $update_id);
            delete_transient('wpsec_bulk_update_' . $update_id);
            
            if (!empty($update_data) && is_array($update_data)) {
                wpsec_process_bulk_update($update_data['update_id'], $update_data['items']);
            }
        });
        
        wpsec_debug_log('🚀 Set up bulk update process with update_id: ' . $update_id, 'info');
    }
    
    // Prepare the immediate response
    $response = [
        'success' => true,
        'message' => 'Update process has been initiated for ' . count($updating_items) . ' items.',
        'update_id' => $update_id,
        'items' => $updating_items
    ];
    
    return rest_ensure_response($response);
}

/**
 * Process bulk updates in the background
 * 
 * @param string $update_id The update ID
 * @param array $updating_items The items to update
 */
function wpsec_process_bulk_update($update_id, $updating_items) {
    // Include required WordPress core files
    require_once(ABSPATH . 'wp-admin/includes/class-wp-upgrader.php');
    require_once(ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php');
    require_once(ABSPATH . 'wp-admin/includes/class-theme-upgrader.php');
    require_once(ABSPATH . 'wp-admin/includes/update.php');
    require_once(ABSPATH . 'wp-admin/includes/file.php');
    require_once(WPSEC_PLUGIN_DIR . 'includes/class-wpsec-upgrader-skin.php');
    
    if (!function_exists('activate_plugin')) {
        require_once(ABSPATH . 'wp-admin/includes/plugin.php');
    }
    
    // Include webhook functions
    if (!function_exists('wpsec_send_update_progress_webhook')) {
        require_once(WPSEC_PLUGIN_DIR . 'includes/webhooks.php');
    }
    
    wpsec_debug_log('🚀 Starting bulk update background process with update_id: ' . $update_id, 'info');
    
    // Temporarily grant necessary capabilities
    $old_user = wp_get_current_user();
    $temp_admin = new WP_User(0);
    $temp_admin->allcaps = array(
        'update_plugins' => true,
        'update_themes' => true,
        'install_plugins' => true,
        'install_themes' => true,
        'activate_plugins' => true,
        'edit_plugins' => true,
        'edit_themes' => true,
        'delete_plugins' => true,
        'delete_themes' => true,
        'manage_options' => true,
        'administrator' => true
    );
    $GLOBALS['current_user'] = $temp_admin;
    
    // Create upgrader instances with our custom skin
    $skin = new WPSEC_Upgrader_Skin();
    $plugin_upgrader = new Plugin_Upgrader($skin);
    $theme_upgrader = new Theme_Upgrader($skin);
    
    $all_items = [];
    
    // Process each item
    foreach ($updating_items as $key => $item) {
        // Update the status to 'updating'
        $updating_items[$key]['status'] = 'updating';
        
        // Send progress webhook
        wpsec_send_update_progress_webhook($update_id, $updating_items);
        
        try {
            // Make sure we have filesystem credentials
            WP_Filesystem();
            
            if ($item['type'] === 'plugin') {
                $plugin_file = $item['file'];
                $was_active = is_plugin_active($plugin_file);
                
                // Clear previous messages
                $skin->messages = array();
                
                // Perform the update
                $update = $plugin_upgrader->upgrade($plugin_file);
                
                if ($update !== false && !is_wp_error($update)) {
                    // Update was successful
                    $updating_items[$key]['status'] = 'completed';
                    
                    // Reactivate if it was active before
                    if ($was_active) {
                        $activate_result = activate_plugin($plugin_file);
                    }
                } else {
                    // Update failed
                    $updating_items[$key]['status'] = 'failed';
                    $updating_items[$key]['error'] = is_wp_error($update) ? $update->get_error_message() : 'Update failed';
                }
            } elseif ($item['type'] === 'theme') {
                $theme_slug = $item['slug'];
                
                // Clear previous messages
                $skin->messages = array();
                
                // Perform the update
                $update = $theme_upgrader->upgrade($theme_slug);
                
                if ($update !== false && !is_wp_error($update)) {
                    // Update was successful
                    $updating_items[$key]['status'] = 'completed';
                } else {
                    // Update failed
                    $updating_items[$key]['status'] = 'failed';
                    $updating_items[$key]['error'] = is_wp_error($update) ? $update->get_error_message() : 'Update failed';
                }
            }
        } catch (Exception $e) {
            // Exception occurred
            $updating_items[$key]['status'] = 'failed';
            $updating_items[$key]['error'] = $e->getMessage();
            wpsec_debug_log('❌ Exception during bulk update: ' . $e->getMessage(), 'error');
        }
        
        // Add the item to all_items
        $all_items[] = $updating_items[$key];
        
        // Send progress webhook after each item
        wpsec_send_update_progress_webhook($update_id, $updating_items);
    }
    
    // Restore original user
    $GLOBALS['current_user'] = $old_user;
    
    // Purge vulnerabilities cache after updates
    wpsec_purge_vulnerability_cache();
    
    // Remove duplicates from all_items by keeping only the latest status for each slug
    $unique_items = [];
    $processed_slugs = [];
    
    // Process items in reverse to get the latest status first
    foreach (array_reverse($updating_items) as $item) {
        if (!in_array($item['slug'], $processed_slugs)) {
            $unique_items[] = $item;
            $processed_slugs[] = $item['slug'];
        }
    }
    
    // Send the completion webhook
    wpsec_send_update_completed_webhook($update_id, $unique_items);
    
    wpsec_debug_log('🏁 Completed bulk update background process for update_id: ' . $update_id, 'info');
}

/**
 * Helper function to get plugin file from slug
 */
/**
 * Purge all vulnerability cache transients
 */
function wpsec_purge_vulnerability_cache() {
    global $wpdb;
    
    // Delete all transients that start with wpsec_vulnerability_report_
    $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '%_transient_wpsec_vulnerability_report_%' OR option_name LIKE '%_transient_timeout_wpsec_vulnerability_report_%'");
}

/**
 * Get plugin file from slug
 */
function wpsec_get_plugin_file_from_slug($slug) {
    if (!function_exists('get_plugins')) {
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
    }
    
    $plugins = get_plugins();
    
    foreach ($plugins as $plugin_file => $plugin_data) {
        if (strpos($plugin_file, $slug . '/') === 0 || $plugin_file === $slug . '.php') {
            return $plugin_file;
        }
    }
    
    return false;
}
