<?php

if (! defined('ABSPATH')) {
    exit;
} class PufferGo_Plugin_Setup
{
    public function __construct()
    {
        add_action('rest_api_init', array($this, 'register_rest_routes'));
    }

    public function register_rest_routes()
    {
        register_rest_route('puffergo/v1', '/plugin-setup/config', array('methods' => 'GET', 'callback' => array($this, 'rest_config'), 'permission_callback' => array($this, 'can_manage_plugins'), ));
        register_rest_route('puffergo/v1', '/plugin-setup/install', array('methods' => 'POST', 'callback' => array($this, 'rest_install'), 'permission_callback' => array($this, 'can_manage_plugins'), ));
    }

    public function can_manage_plugins()
    {
        return current_user_can('install_plugins');
    }

    public function rest_config()
    {
        $config = $this->fetch_remote_config();

        if (is_wp_error($config)) {
            return $config;
        } $config['plugins'] = array_map(function ($plugin) {
            $plugin['install_status'] = $this->get_plugin_install_status($plugin);

            return $plugin;
        }, $config['plugins']);

        return rest_ensure_response(array('success' => true, 'data' => $config, ));
    }

    public function rest_install(WP_REST_Request $request)
    {
        $selected = $request->get_param('selected');

        if (! is_array($selected)) {
            return new WP_Error('puffergo_plugin_setup_invalid_request', __('Invalid selected plugins payload.', 'puffergo'), array('status' => 400));
        } $config = $this->fetch_remote_config();

        if (is_wp_error($config)) {
            return $config;
        } $catalog = $this->index_plugins_by_slug($config['plugins']);
        $allowed_slugs = array_keys($catalog);
        $selected_slugs = array_values(array_unique(array_map('sanitize_key', $selected)));

        foreach ($selected_slugs as $slug) {
            if (! in_array($slug, $allowed_slugs, true)) {
                return new WP_Error('puffergo_plugin_setup_forbidden_plugin', __('One or more selected plugins are not allowed.', 'puffergo'), array('status' => 400));
            }
        } $results = array();

        foreach ($selected_slugs as $slug) {
            $results[] = $this->install_and_activate_plugin($catalog[ $slug ]);
        }

return rest_ensure_response(array('success' => true, 'results' => $results, ));
    }

    private function fetch_remote_config()
    {
        $request_url = add_query_arg(array('locale' => $this->get_current_locale(), ), $this->get_remote_config_url());
        $response = wp_remote_get(esc_url_raw($request_url), array('timeout' => 15, 'headers' => array('Accept' => 'application/json', ), ));

        if (is_wp_error($response)) {
            return new WP_Error('puffergo_plugin_setup_remote_error', $response->get_error_message(), array('status' => 502));
        } $code = wp_remote_retrieve_response_code($response);

        if ($code < 200 || $code >= 300) {
            return new WP_Error('puffergo_plugin_setup_remote_status', __('Failed to fetch plugin setup config.', 'puffergo'), array('status' => 502));
        } $body = json_decode(wp_remote_retrieve_body($response), true);

        if (! is_array($body) || empty($body['success']) || empty($body['data'])) {
            return new WP_Error('puffergo_plugin_setup_remote_payload', __('Invalid plugin setup config response.', 'puffergo'), array('status' => 502));
        }

return $this->normalize_remote_config($body['data']);
    }

    private function get_remote_config_url()
    {
        $default_url = trailingslashit(untrailingslashit(PUFFERGO_AI_PAGE_BUILDER_BASE_URL)) . 'api/wp-plugin/config';

        return apply_filters('puffergo_plugin_setup_config_url', $default_url);
    }

    private function get_current_locale()
    {
        if (function_exists('get_user_locale')) {
            return sanitize_text_field(get_user_locale());
        }

return sanitize_text_field(get_locale());
    }

    private function index_plugins_by_slug($plugins)
    {
        $indexed = array();

        foreach ($plugins as $plugin) {
            if (empty($plugin['slug'])) {
                continue;
            } $indexed[ sanitize_key($plugin['slug']) ] = $plugin;
        }

return $indexed;
    }

    private function normalize_remote_config($config)
    {
        $scenarios = array();

        foreach (isset($config['scenarios']) && is_array($config['scenarios']) ? $config['scenarios'] : array() as $scenario) {
            if (empty($scenario['key'])) {
                continue;
            } $scenarios[] = array('key' => sanitize_key($scenario['key']), 'label' => isset($scenario['label']) ? sanitize_text_field($scenario['label']) : '', );
        } $plugins = array();

        foreach (isset($config['plugins']) && is_array($config['plugins']) ? $config['plugins'] : array() as $plugin) {
            $normalized = $this->normalize_remote_plugin($plugin);

            if ($normalized) {
                $plugins[] = $normalized;
            }
        } $plugin_catalog = $this->index_plugins_by_slug($plugins);
        $rules = array();

        foreach (isset($config['rules']) && is_array($config['rules']) ? $config['rules'] : array() as $scenario_key => $plugin_slugs) {
            $normalized_key = sanitize_key($scenario_key);

            if (! is_array($plugin_slugs)) {
                continue;
            } $rules[ $normalized_key ] = array_values(array_filter(array_unique(array_map('sanitize_key', $plugin_slugs)), function ($slug) use ($plugin_catalog) { return isset($plugin_catalog[ $slug ]); }));
        }

return array('version' => isset($config['version']) ? sanitize_text_field($config['version']) : '', 'scenarios' => $scenarios, 'plugins' => $plugins, 'rules' => $rules, );
    }

    private function normalize_remote_plugin($plugin)
    {
        if (! is_array($plugin) || empty($plugin['slug']) || empty($plugin['file']) || empty($plugin['name'])) {
            return null;
        } $slug = sanitize_key($plugin['slug']);

        return array('slug' => $slug, 'file' => sanitize_text_field($plugin['file']), 'name' => sanitize_text_field($plugin['name']), 'description' => isset($plugin['description']) ? sanitize_text_field($plugin['description']) : '', 'author' => isset($plugin['author']) ? sanitize_text_field($plugin['author']) : '', 'icon' => isset($plugin['icon']) ? esc_url_raw($plugin['icon']) : '', 'active_installs' => isset($plugin['active_installs']) ? sanitize_text_field($plugin['active_installs']) : '', 'settings_url' => isset($plugin['settings_url']) ? esc_url_raw($plugin['settings_url']) : '', 'notes' => isset($plugin['notes']) ? sanitize_text_field($plugin['notes']) : '', );
    }

    private function get_plugin_install_status($plugin)
    {
        $plugin_file = isset($plugin['file']) ? $plugin['file'] : '';

        if (! $plugin_file) {
            return 'not_installed';
        }

if (! function_exists('get_plugins')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        } $installed_plugins = get_plugins();

        if (! isset($installed_plugins[ $plugin_file ])) {
            return 'not_installed';
        }

return is_plugin_active($plugin_file) ? 'activated' : 'installed';
    }

    private function install_and_activate_plugin($plugin)
    {
        $slug = sanitize_key($plugin['slug']);
        $plugin_file = $plugin['file'];
        $name = $plugin['name'];
        $before = $this->get_plugin_install_status($plugin);

        if ('activated' === $before) {
            return array('slug' => $slug, 'name' => $name, 'status_before' => $before, 'status_after' => 'activated', 'result' => 'already_activated', 'message' => __('Already installed and activated.', 'puffergo'), );
        }

if ('installed' === $before) {
            $activated = activate_plugin($plugin_file);

            if (is_wp_error($activated)) {
                return array('slug' => $slug, 'name' => $name, 'status_before' => $before, 'status_after' => 'installed', 'result' => 'activate_failed', 'message' => $activated->get_error_message(), );
            }

return array('slug' => $slug, 'name' => $name, 'status_before' => $before, 'status_after' => 'activated', 'result' => 'activated_existing_install', 'message' => __('Activated successfully.', 'puffergo'), );
        } require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/misc.php';
        require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
        $api = plugins_api('plugin_information', array('slug' => $slug, 'fields' => array('sections' => false, ), ));

        if (is_wp_error($api)) {
            return array('slug' => $slug, 'name' => $name, 'status_before' => $before, 'status_after' => 'not_installed', 'result' => 'install_failed', 'message' => $api->get_error_message(), );
        } $skin = new Automatic_Upgrader_Skin();
        $upgrader = new Plugin_Upgrader($skin);
        $installed = $upgrader->install($api->download_link);

        if (is_wp_error($installed)) {
            return array('slug' => $slug, 'name' => $name, 'status_before' => $before, 'status_after' => 'not_installed', 'result' => 'install_failed', 'message' => $installed->get_error_message(), );
        }

if (false === $installed) {
            return array('slug' => $slug, 'name' => $name, 'status_before' => $before, 'status_after' => 'not_installed', 'result' => 'install_failed', 'message' => __('Plugin installation failed.', 'puffergo'), );
        } $activated = activate_plugin($plugin_file);

        if (is_wp_error($activated)) {
            return array('slug' => $slug, 'name' => $name, 'status_before' => $before, 'status_after' => 'installed', 'result' => 'activate_failed', 'message' => $activated->get_error_message(), );
        }

return array('slug' => $slug, 'name' => $name, 'status_before' => $before, 'status_after' => 'activated', 'result' => 'installed_and_activated', 'message' => __('Installed and activated successfully.', 'puffergo'), );
    }
}
