<?php

// Load debug helpers
if (!function_exists('fleekdash_log_debug')) {
    require_once FLEEKDASH_PLUGIN_DIR . 'includes/Core/debug-helpers.php';
}

class FleekDashCoreUpdate
{
    private const PATH_UPGRADE_PHP = 'wp-admin/includes/upgrade.php';

    /**
     * Constructor
     *
     * Migrated (v2.2): FeaturesRoutes (Phase 4.2)
     * add_action removed - routes now registered via FeaturesRoutes
     */
    public function __construct()
    {
        \add_action('rest_api_init', array($this, 'register_routes'));
    }

    public function register_routes() // NOSONAR php:S100 - WP REST route registration
    {
        // REST route: core update
        register_rest_route('fleekdash/v1', '/core/update', array(
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => array($this, 'handle_update'),
            'permission_callback' => array($this, 'check_permission'),
        ));

        // REST route: core reinstall
        register_rest_route('fleekdash/v1', '/core/reinstall', array(
            'methods' => WP_REST_Server::CREATABLE,
            'callback' => array($this, 'handle_reinstall'),
            'permission_callback' => array($this, 'check_permission'),
        ));
    }

    public function check_permission(WP_REST_Request $_request) // NOSONAR php:S100,S1172 - WP REST callback signature
    {
        if (!current_user_can('update_core')) {
            return new WP_Error(
                'rest_forbidden',
                'Sorry, you are not allowed to update WordPress.',
                array('status' => rest_authorization_required_code()),
            );
        }
        return true;
    }

    private function prepare_environment() // NOSONAR php:S100 - internal
    {
        // Load required WordPress core files
        require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
        require_once ABSPATH . 'wp-admin/includes/class-automatic-upgrader-skin.php';
        require_once ABSPATH . 'wp-admin/includes/update.php';
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/misc.php';

        // Allow up to 10 minutes for large downloads (same budget as plugin/theme directory install)
        if (\function_exists('set_time_limit')) {
            @\set_time_limit(600);
        }
        if (\function_exists('ignore_user_abort')) {
            @\ignore_user_abort(true);
        }

        // Disable output compression so progress/output is not buffered incorrectly
        @ini_set('zlib.output_compression', 0);

        // Discard any buffered output before upgrader runs
        if (ob_get_level()) {
            ob_end_clean();
        }

        // Flush common caches so core version checks see fresh data
        wp_cache_flush();
        if (function_exists('w3tc_flush_all')) {
            w3tc_flush_all();
        }
        if (function_exists('wp_cache_clear_cache')) {
            wp_cache_clear_cache();
        }
        if (function_exists('rocket_clean_domain')) {
            rocket_clean_domain();
        }
    }

    public function handle_reinstall(WP_REST_Request $_request) // NOSONAR php:S100,S1172,S3776,S138 - WP REST callback
    {
        try {
            // Log start
            fleekdash_log_debug('Starting WordPress reinstallation...');

            $this->prepare_environment();

            // Initialize WP_Filesystem API
            global $wp_filesystem;
            if (!function_exists('WP_Filesystem')) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }

            $creds = request_filesystem_credentials('', '', false, ABSPATH, null);
            if (!WP_Filesystem($creds)) {
                throw new \FleekDash\API\CoreUpdateException('Could not initialize WordPress filesystem. Please check file permissions.');
            }

            // Core upgrader + automatic skin for REST-driven install
            $skin = new Automatic_Upgrader_Skin();
            $upgrader = new Core_Upgrader($skin);

            // Current site version and locale for package URL
            $current_version = get_bloginfo('version');
            $locale = get_locale();
            fleekdash_log_debug("Current WordPress version: {$current_version}, Locale: {$locale}");

            // Build official WordPress zip URL for this version/locale
            $url = sprintf(
                'https://downloads.wordpress.org/release/wordpress-%s.zip',
                $current_version,
            );

            if ($locale !== 'en_US') {
                $url = sprintf(
                    'https://downloads.wordpress.org/release/wordpress-%s-%s.zip',
                    $current_version,
                    $locale,
                );
            }

            fleekdash_log_debug("Download URL: {$url}");

            // HEAD request: ensure the package URL responds before downloading
            $test_download = wp_remote_head($url);
            if (is_wp_error($test_download)) {
                throw new \FleekDash\API\CoreUpdateException('Could not access WordPress package: ' . $test_download->get_error_message());
            }
            if (wp_remote_retrieve_response_code($test_download) !== 200) {
                throw new \FleekDash\API\CoreUpdateException('WordPress package not found at: ' . $url);
            }

            fleekdash_log_debug('Package is accessible, starting download...');

            // Working directory for download + unzip
            $temp_dir = get_temp_dir() . 'wordpress_reinstall_' . time();
            if (!$wp_filesystem->mkdir($temp_dir)) {
                throw new \FleekDash\API\CoreUpdateException('Could not create temporary directory.');
            }

            // Download package to a temp file
            $download_file = download_url($url);
            if (is_wp_error($download_file)) {
                $wp_filesystem->delete($temp_dir, true);
                throw new \FleekDash\API\CoreUpdateException('Failed to download WordPress package: ' . $download_file->get_error_message());
            }

            fleekdash_log_debug('Package downloaded successfully to: ' . $download_file);

            // Progress payload for overlay/UI
            $progress_messages = array(
                array(
                    'type' => 'info',
                    'message' => 'Package downloaded successfully',
                    'timestamp' => time()
                )
            );

            // Unzip into the working directory
            $unzip_result = unzip_file($download_file, $temp_dir);
            if (is_wp_error($unzip_result)) {
                $wp_filesystem->delete($temp_dir, true);
                @unlink($download_file);
                throw new \FleekDash\API\CoreUpdateException('Failed to extract WordPress package: ' . $unzip_result->get_error_message());
            }

            // Delete downloaded zip after successful unzip
            @unlink($download_file);

            fleekdash_log_debug('Package extracted successfully');
            $progress_messages[] = array(
                'type' => 'info',
                'message' => 'Package extracted successfully',
                'timestamp' => time()
            );

            // Options passed to Core_Upgrader::install_package
            $install_options = array(
                'source' => $temp_dir . '/wordpress',
                'destination' => ABSPATH,
                'clear_destination' => false,
                'clear_working' => true,
                'hook_extra' => array(
                    'type' => 'core',
                    'action' => 'update',
                    'incompatible_archive' => false,
                    'folder_exists' => true
                )
            );

            fleekdash_log_debug('Starting core replacement with modified options...');
            $progress_messages[] = array(
                'type' => 'info',
                'message' => 'Starting core replacement...',
                'timestamp' => time()
            );

            // Run reinstall with explicit error handling
            $result = null;
            try {
                // Validate extracted tree looks like WordPress core
                if (!is_dir($install_options['source']) || !file_exists($install_options['source'] . '/wp-includes/version.php')) {
                    throw new \FleekDash\API\CoreUpdateException('Invalid WordPress package structure');
                }

                // WordPress maintenance mode during file replacement
                $upgrader->maintenance_mode(true);

                // Ensure ABSPATH exists for the upgrader
                $destination = $install_options['destination'];
                if (!$wp_filesystem->exists($destination) && !$wp_filesystem->mkdir($destination, FS_CHMOD_DIR)) {
                    throw new \FleekDash\API\CoreUpdateException('Could not create destination directory.');
                }

                // Core_Upgrader entry point
                $upgrader->init();
                $upgrader->fs_connect(array(WP_CONTENT_DIR, $destination));

                // install_package copies core files into ABSPATH
                $result = $upgrader->install_package(array(
                    'source' => $install_options['source'],
                    'destination' => $destination,
                    'clear_destination' => true,
                    'clear_working' => true,
                    'hook_extra' => array(
                        'type' => 'core',
                        'action' => 'update',
                        'skip_process_verified' => true,
                        'abort_if_destination_exists' => false,
                        'overwrite' => true
                    )
                ));

                if (is_wp_error($result)) {
                    throw new \FleekDash\API\CoreUpdateException($result->get_error_message());
                }

                // Restore wp-config/.htaccess from backups if the upgrader moved them
                $config_backup = $destination . 'wp-config.php.bak';
                $htaccess_backup = $destination . '.htaccess.bak';

                if ($wp_filesystem->exists($config_backup)) {
                    $wp_filesystem->move($config_backup, $destination . 'wp-config.php', true);
                }
                if ($wp_filesystem->exists($htaccess_backup)) {
                    $wp_filesystem->move($htaccess_backup, $destination . '.htaccess', true);
                }

            } catch (Exception $install_error) {
                fleekdash_log_error('Installation error caught: ' . $install_error->getMessage());
                $result = new WP_Error('install_error', $install_error->getMessage());
            } finally {
                // Always clear maintenance mode
                $upgrader->maintenance_mode(false);
            }

            // Remove working directory
            $wp_filesystem->delete($temp_dir, true);

            // Stop if install_package returned an error
            if (is_wp_error($result)) {
                fleekdash_log_error('Reinstallation error: ' . $result->get_error_message());
                throw new \FleekDash\API\CoreUpdateException($result->get_error_message());
            }

            // Collect any messages from the upgrader skin
            $upgrade_messages = $skin->get_upgrade_messages();
            if (!empty($upgrade_messages)) {
                fleekdash_log_debug('Upgrade messages: ' . implode(' ', $upgrade_messages));
            }

            if ($result === false) {
                $error_messages = array();

                // Skin-level errors (if any)
                if (method_exists($skin, 'get_errors') && is_array($skin->get_errors())) {
                    foreach ($skin->get_errors() as $error) {
                        $error_messages[] = $error->get_error_message();
                    }
                }

                // Generic message when the skin did not report details
                if (empty($error_messages)) {
                    $error_messages[] = 'Installation failed for an unknown reason.';
                }

                fleekdash_log_error('Installation errors: ' . implode(' ', $error_messages));
                throw new \FleekDash\API\CoreUpdateException(implode(' ', $error_messages));
            }

            fleekdash_log_debug('Core files replaced successfully');
            $progress_messages[] = array(
                'type' => 'success',
                'message' => 'Core files replaced successfully',
                'timestamp' => time()
            );

            // Run db upgrade routines after files are in place
            if (file_exists(ABSPATH . self::PATH_UPGRADE_PHP)) {
                fleekdash_log_debug('Running database upgrade...');
                $progress_messages[] = array(
                    'type' => 'info',
                    'message' => 'Running database upgrade...',
                    'timestamp' => time()
                );

                require_once ABSPATH . self::PATH_UPGRADE_PHP;
                wp_upgrade();

                fleekdash_log_debug('Database upgrade completed');
                $progress_messages[] = array(
                    'type' => 'success',
                    'message' => 'Database upgrade completed',
                    'timestamp' => time()
                );
            }

            fleekdash_log_debug('WordPress reinstallation completed successfully');
            $progress_messages[] = array(
                'type' => 'success',
                'message' => 'WordPress reinstallation completed successfully',
                'timestamp' => time()
            );

            return \rest_ensure_response(array(
                'success' => true,
                'message' => 'WordPress core reinstalled successfully',
                'progress' => $progress_messages,
                'details' => array(
                    'version' => $current_version,
                    'locale' => $locale,
                    'package' => $url,
                ),
            ));

        } catch (Exception $e) {
            fleekdash_log_error('Reinstallation failed: ' . $e->getMessage());
            fleekdash_log_error('Error details: ' . $e->getTraceAsString());

            // Append error to progress payload for the client overlay
            if (isset($progress_messages)) {
                $progress_messages[] = array(
                    'type' => 'error',
                    'message' => 'Error: ' . $e->getMessage(),
                    'timestamp' => time()
                );
            }

            return new WP_Error(
                'reinstall_error',
                $e->getMessage(),
                array(
                    'status' => 500,
                    'progress' => isset($progress_messages) ? $progress_messages : array(),
                    'details' => array(
                        'file' => $e->getFile(),
                        'line' => $e->getLine(),
                        'trace' => $e->getTraceAsString()
                    )
                ),
            );
        }
    }

    public function handle_update(WP_REST_Request $_request) // NOSONAR php:S100,S1172,S3776,S1142 - WP REST callback
    {
        try {
            $this->prepare_environment();

            // Refresh core/plugin/theme update transients
            wp_version_check(array(), true);
            wp_update_plugins();
            wp_update_themes();

            // Read pending core updates from WordPress
            $core_updates = get_core_updates();

            $update = (empty($core_updates) || !is_array($core_updates))
                ? null
                : $core_updates[0];
            if (!$update || $update->response === 'latest') {
                return \rest_ensure_response(array(
                    'success' => true,
                    'message' => 'WordPress is already up to date.',
                    'already_up_to_date' => true,
                ));
            }

            $old_version = \get_bloginfo('version');
            $new_version = isset($update->current) ? (string) $update->current : $old_version;

            // Core upgrader + automatic skin for REST-driven install
            $skin = new Automatic_Upgrader_Skin();
            $upgrader = new Core_Upgrader($skin);

            // Run core upgrade (downloads and replaces files)
            $result = $upgrader->upgrade($update);

            // Stop if upgrade returned WP_Error
            if (is_wp_error($result)) {
                throw new \FleekDash\API\CoreUpdateException($result->get_error_message());
            }

            // Collect any messages from the upgrader skin
            $upgrade_messages = $skin->get_upgrade_messages();
            if (!empty($upgrade_messages)) {
                fleekdash_log_debug('Upgrade messages: ' . implode(' ', $upgrade_messages));
            }

            if ($result === false) {
                $error_messages = array();

                // Skin-level errors (if any)
                if (method_exists($skin, 'get_errors') && is_array($skin->get_errors())) {
                    foreach ($skin->get_errors() as $error) {
                        $error_messages[] = $error->get_error_message();
                    }
                }

                // Generic message when the skin did not report details
                if (empty($error_messages)) {
                    $error_messages[] = 'Update failed for an unknown reason.';
                }

                throw new \FleekDash\API\CoreUpdateException(implode(' ', $error_messages));
            }

            // Run db upgrade routines after files are in place
            if (file_exists(ABSPATH . self::PATH_UPGRADE_PHP)) {
                require_once ABSPATH . self::PATH_UPGRADE_PHP;
                wp_upgrade();
            }

            return \rest_ensure_response(array(
                'success' => true,
                'message' => 'WordPress core updated successfully',
                'old_version' => $old_version,
                'new_version' => $new_version,
                'details' => array(
                    'from_version' => $old_version,
                    'to_version' => $new_version,
                    'locale' => \get_locale(),
                ),
            ));

        } catch (Exception $e) {
            return new WP_Error(
                'update_error',
                $e->getMessage(),
                array(
                    'status' => 500,
                    'details' => array(
                        'file' => $e->getFile(),
                        'line' => $e->getLine(),
                        'trace' => $e->getTraceAsString()
                    )
                ),
            );
        }
    }
}

// Bootstrap the class
$fleekdash_core_update = new FleekDashCoreUpdate();
