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

/**
 * Core Reinstall API Endpoints
 * 
 * Provides API endpoints for reinstalling WordPress core files
 */

/**
 * Handle the core reinstall endpoint request
 * 
 * @param WP_REST_Request $request The request object
 * @return WP_REST_Response|WP_Error The response
 */
function wpsec_core_reinstall_endpoint($request) {
    // Debug logging
    wpsec_log('Core reinstall endpoint called', 'action');
    
    // Validate API key (double check)
    if (!wpsec_validate_api_key()) {
        wpsec_log('API key validation failed for core reinstall', 'error');
        return new WP_Error(
            'rest_forbidden',
            'Sorry, you are not allowed to do that.',
            array('status' => 401)
        );
    }

    // Get parameters
    $version = $request->get_param('version');
    $backup = $request->get_param('backup');
    $skip_content = $request->get_param('skip_content');
    $skip_config = $request->get_param('skip_config');
    $verify_checksums = $request->get_param('verify_checksums');
    $bypass_webhooks = $request->get_param('bypass_webhooks');
    $restore_index_files = $request->get_param('restore_index_files');
    
    // Set defaults
    $version = $version ?: 'current';
    $backup = isset($backup) ? (bool)$backup : true;
    $skip_content = isset($skip_content) ? (bool)$skip_content : true;
    $skip_config = isset($skip_config) ? (bool)$skip_config : true;
    $verify_checksums = isset($verify_checksums) ? (bool)$verify_checksums : true;
    $bypass_webhooks = isset($bypass_webhooks) ? (bool)$bypass_webhooks : false;
    $restore_index_files = isset($restore_index_files) ? (bool)$restore_index_files : false;
    
    // Validate version parameter
    if ($version !== 'current' && !preg_match('/^\d+\.\d+(\.\d+)?$/', $version)) {
        wpsec_log('Invalid version parameter for core reinstall: ' . $version, 'error');
        return new WP_Error(
            'invalid_parameter',
            'Invalid version parameter. Use "current" or a valid WordPress version (e.g., "6.1.1").',
            array('status' => 400)
        );
    }
    
    // Check if this is a GET request (status check) or a POST request (start reinstall)
    $method = $request->get_method();
    
    if ($method === 'GET') {
        // Check status of an existing operation
        $operation_id = $request->get_param('operation_id');
        
        if (empty($operation_id)) {
            wpsec_log('Missing operation_id parameter for core reinstall status check', 'error');
            return new WP_Error(
                'missing_parameter',
                'Missing required parameter: operation_id',
                array('status' => 400)
            );
        }
        
        $status = wpsec_get_core_reinstall_status($operation_id);
        
        if (is_wp_error($status)) {
            wpsec_log('Failed to get core reinstall status: ' . $status->get_error_message(), 'error');
            return $status;
        }
        
        return rest_ensure_response(array(
            'status' => 'success',
            'operation_id' => $operation_id,
            'operation_status' => $status['status'],
            'progress' => $status['progress'],
            'message' => isset($status['status_message']) ? $status['status_message'] : '',
            'started_at' => $status['started_at'],
            'completed_at' => isset($status['completed_at']) ? $status['completed_at'] : null,
            'version' => $status['version'],
            'log' => array_slice($status['log'], -10) // Return only the last 10 log entries for brevity
        ));
    } else {
        // Start a new reinstall operation
        wpsec_log('Starting core reinstall operation for version: ' . $version, 'action');
        
        // Validate that WordPress has the necessary permissions
        if (!wpsec_core_reinstall_check_permissions()) {
            wpsec_log('Insufficient filesystem permissions for core reinstall', 'error');
            return new WP_Error(
                'insufficient_permissions',
                'WordPress does not have sufficient permissions to modify core files. Please check file ownership and permissions.',
                array('status' => 403)
            );
        }
        
        // Prepare options
        $options = array(
            'verify_checksums' => $verify_checksums,
            'backup_first' => $backup,
            'backup_core_only' => $skip_content,
            'skip_files' => $skip_config ? array('wp-config.php') : array(),
            'skip_dirs' => $skip_content ? array('wp-content') : array(),
            'bypass_webhooks' => $bypass_webhooks,
            'restore_index_files' => $restore_index_files
        );
        
        // Ensure core-reinstall.php is loaded
        require_once WPSEC_PLUGIN_DIR . 'includes/core-reinstall.php';
        
        // Start the reinstall process
        ignore_user_abort(true);
        set_time_limit(0);
        
        // Generate a unique operation ID
        $operation_id = uniqid('wpsec_core_reinstall_', true);
        
        // Include the operation_id in the options
        $options['operation_id'] = $operation_id;
        
        // Start the operation in the background if possible
        if (function_exists('fastcgi_finish_request')) {
            // Make sure there's no previous output
            if (ob_get_level()) {
                ob_clean();
            }
            
            // Send response immediately
            $response = array(
                'status' => 'success',
                'message' => 'WordPress core reinstall started',
                'operation_id' => $operation_id,
                'version' => $version,
                'started_at' => current_time('mysql'),
                'check_status_endpoint' => rest_url('wpsec/v1/core-reinstall?operation_id=' . $operation_id)
            );
            
            // Initialize the status data structure now, before we send the response
            $metadata = [
                'id' => $operation_id,
                'started_at' => current_time('mysql'),
                'status' => 'preparing',
                'version' => $version === 'current' ? get_bloginfo('version') : $version,
                'current_version' => get_bloginfo('version'),
                'options' => $options,
                'progress' => 0,
                'log' => ['Core reinstall operation initialized']
            ];
            update_option(WPSEC_CORE_REINSTALL_STATUS_PREFIX . $operation_id, $metadata);
            
            // Use wp_send_json which handles headers and encoding properly
            wp_send_json($response);
            // The above function will exit, but in case it doesn't:
            exit;
            
            @ob_end_flush();
            @flush();
            
            fastcgi_finish_request();
            
            // Now run the reinstall
            wpsec_reinstall_wordpress_core($version, $options);
        } else {
            // No FastCGI - have to run in a separate process
            // Schedule a single event to run immediately
            wp_schedule_single_event(time(), 'wpsec_core_reinstall_cron', array($version, $options, $operation_id));
            
            return rest_ensure_response(array(
                'status' => 'success',
                'message' => 'WordPress core reinstall scheduled',
                'operation_id' => $operation_id,
                'version' => $version,
                'started_at' => current_time('mysql'),
                'check_status_endpoint' => rest_url('wpsec/v1/core-reinstall?operation_id=' . $operation_id)
            ));
        }
    }
}

/**
 * Check if WordPress has the necessary permissions to reinstall core files
 * 
 * @return bool True if has permissions, false otherwise
 */
function wpsec_core_reinstall_check_permissions() {
    // Check write permissions for essential directories
    $essential_dirs = array(
        ABSPATH,
        ABSPATH . 'wp-admin',
        ABSPATH . 'wp-includes'
    );
    
    // Initialize WordPress Filesystem
    global $wp_filesystem;
    if (empty($wp_filesystem)) {
        require_once(ABSPATH . '/wp-admin/includes/file.php');
        WP_Filesystem();
    }
    
    foreach ($essential_dirs as $dir) {
        if (!$wp_filesystem->is_writable($dir)) {
            wpsec_log('Directory not writable: ' . $dir, 'error');
            return false;
        }
    }
    
    // Check if we can create and delete a test file
    $test_file = ABSPATH . 'wp-includes/wpsec-test-' . uniqid() . '.tmp';
    
    if (@file_put_contents($test_file, 'test') === false) {
        wpsec_log('Cannot create test file in wp-includes', 'error');
        return false;
    }
    
    if (!@wp_delete_file($test_file)) {
        wpsec_log('Cannot delete test file in wp-includes', 'error');
        return false;
    }
    
    return true;
}

/**
 * Cron callback to run the core reinstall
 * 
 * @param string $version WordPress version to reinstall
 * @param array $options Options for the reinstall process
 * @param string $operation_id The operation ID
 */
function wpsec_core_reinstall_cron_callback($version, $options, $operation_id) {
    // Ensure core-reinstall.php is loaded
    require_once WPSEC_PLUGIN_DIR . 'includes/core-reinstall.php';
    
    // Run the reinstall
    wpsec_reinstall_wordpress_core($version, $options);
}

// Add cron action
add_action('wpsec_core_reinstall_cron', 'wpsec_core_reinstall_cron_callback', 10, 3);
