<?php
/**
 * Render installer class.
 *
 * @package SaveToWishlist\Classes\Admin
 * @since 1.0.0
 */
namespace SaveToWishlist\Classes\Admin;

use SaveToWishlist\Abstracts\Singleton;
use SaveToWishlist\Helpers\Helper_Functions;

/**
 * Class Render_Installer
 *
 * This class serves as the render settings class.
 */
class Render_Installer extends Singleton {

    /**
     * REST action URL.
     *
     * @var string
     */
    public $rest_action_url;

    /**
     * Helper functions.
     *
     * @var Helper_Functions
     */
    private $helper_functions;

    /**
     * Get the allowed plugins.
     *
     * @var $allowed_plugins
     */
    private $allowed_plugins = array(
        'advanced-coupons-for-woocommerce-free' => 'advanced-coupons-for-woocommerce-free/advanced-coupons-for-woocommerce-free.php',
        'woocommerce-wholesale-prices'          => 'woocommerce-wholesale-prices/woocommerce-wholesale-prices.bootstrap.php',
        'wc-vendors'                            => 'wc-vendors/class-wc-vendors.php',
        'storeagent-ai-for-woocommerce'         => 'storeagent-ai-for-woocommerce/storeagent-ai-for-woocommerce.php',
        'invoice-gateway-for-woocommerce'       => 'invoice-gateway-for-woocommerce/invoice-gateway-for-woocommerce.php',
        'woo-product-feed-pro'                  => 'woo-product-feed-pro/woocommerce-sea.php',
        'woocommerce-store-toolkit'             => 'woocommerce-store-toolkit/store-toolkit.php',
        'woocommerce-exporter'                  => 'woocommerce-exporter/exporter.php',
    );

    /**
     * Constructor.
     *
     * @since 1.0.0
     * @access public
     */
    public function __construct() {
        $this->rest_action_url = rest_url( 'saveto-wishlist/v1/admin/settings/action' );

        $this->helper_functions = Helper_Functions::instance();
    }

    /**
     * Install and activate a plugin.
     *
     * @since 2.2.1
     * @access public
     *
     * @param array $params The parameters.
     *
     * @return void
     */
    public function install_activate_plugin( $params ) {
        $plugin_slug = isset( $params['plugin_slug'] ) ? sanitize_text_field( wp_unslash( $params['plugin_slug'] ) ) : '';
        $result      = $this->download_and_activate_plugin( $plugin_slug );

        if ( is_wp_error( $result ) ) {
            wp_send_json_error( $result->get_error_message() );
        } else {
            wp_send_json_success(
                array(
                    'status'  => 'success',
                    'extra'   => array(
                        'plugin_slug' => $plugin_slug,
                    ),
                    'message' => __( 'The plugin has been installed and activated.', 'saveto-wishlist-lite-for-woocommerce' ),
                )
            );
        }
    }

    /**
     * Download and activate a plugin.
     *
     * @param string $plugin_slug The plugin slug.
     *
     * @since 2.2.1
     * @access public
     *
     * @return bool|\WP_Error
     */
    public function download_and_activate_plugin( $plugin_slug ) {

        // Check if the current user has the required permissions.
        if ( ! current_user_can( 'install_plugins' ) || ! current_user_can( 'activate_plugins' ) ) {
            return new \WP_Error( 'permission_denied', __( 'You do not have sufficient permissions to install and activate plugins.', 'saveto-wishlist-lite-for-woocommerce' ) );
        }

        // Check if the plugin is valid.
        if ( ! $this->_is_plugin_allowed_for_install( $plugin_slug ) ) {
            return new \WP_Error( 'wwp_plugin_not_allowed', __( 'The plugin is not valid.', 'saveto-wishlist-lite-for-woocommerce' ) );
        }

        // Get required files since we're calling this outside of context.
        require_once ABSPATH . 'wp-admin/includes/plugin.php';
        require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
        require_once ABSPATH . 'wp-admin/includes/file.php';
        require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';

        // Get the plugin info from WordPress.org's plugin repository.
        $api = plugins_api( 'plugin_information', array( 'slug' => $plugin_slug ) );
        if ( is_wp_error( $api ) ) {
            return $api;
        }

        $plugin_basename = $this->get_plugin_basename_by_slug( $plugin_slug );

        // Check if the plugin is already active.
        if ( is_plugin_active( $plugin_basename ) ) {
            return new \WP_Error( 'wwp_plugin_already_active', __( 'The plugin is already installed.', 'saveto-wishlist-lite-for-woocommerce' ) );
        }

        // Check if the plugin is already installed but inactive, just activate it and return true.
        if ( $this->helper_functions->is_wp_plugin_installed( $plugin_basename ) ) {
            return $this->_activate_plugin( $plugin_basename );
        }

        // Download the plugin.
        $skin     = new \WP_Ajax_Upgrader_Skin();
        $upgrader = new \Plugin_Upgrader( $skin );

        $result = $upgrader->install( $api->download_link );

        // Check if the plugin was installed successfully.
        if ( is_wp_error( $result ) ) {
            return $result;
        }

        // Activate the plugin.
        return $this->_activate_plugin( $plugin_basename );
    }

    /**
     * Activate a plugin.
     *
     * @param string $plugin_basename The plugin basename.
     *
     * @since 2.2.1
     * @access private
     *
     * @return bool|\WP_Error
     */
    private function _activate_plugin( $plugin_basename ) {
        $result = activate_plugin( $plugin_basename );

        if ( ! is_wp_error( $result ) ) {
            // Get plugin slug from basename.
            $plugin_slug = explode( '/', $plugin_basename )[0];

            // Update plugin install information.
            $this->_update_plugin_install_information( $plugin_slug );
        }

        return is_wp_error( $result ) ? $result : true;
    }

    /**
     * Update tracking information after plugin installation.
     *
     * @param string $plugin_slug The plugin slug.
     *
     * @since 2.2.1
     * @access private
     *
     * @return void
     */
    private function _update_plugin_install_information( $plugin_slug ) {
        // Update StoreAgent AI source option when StoreAgent AI is installed.
        if ( 'storeagent-ai-for-woocommerce' === $plugin_slug ) {
            update_option( 'storeagent_installed_by', 'stwl' );
        }

        // Update Advanced Coupons source option when Advanced Coupons is installed.
        if ( 'advanced-coupons-for-woocommerce-free' === $plugin_slug ) {
            update_option( 'acfw_installed_by', 'stwl' );
        }
    }

    /**
     * Check if the plugin is allowed for install.
     *
     * @param string $plugin_slug The plugin slug.
     *
     * @since 2.2.1
     * @access private
     *
     * @return bool
     */
    private function _is_plugin_allowed_for_install( $plugin_slug ) {
        return in_array( $plugin_slug, array_keys( $this->get_allowed_plugins() ), true );
    }

    /**
     * Get the allowed plugins.
     *
     * @since 2.2.1
     * @access public
     *
     * @return array
     */
    public function get_allowed_plugins() {
        // Allow other plugins to be installed but not let them overwrite the ones listed above.
        $extra_allowed_plugins = apply_filters( 'stwlite_allowed_install_plugins', array() );

        return array_merge( $this->allowed_plugins, $extra_allowed_plugins );
    }

    /**
     * Get the plugin basename by the plugin slug.
     *
     * @param string $plugin_slug The plugin slug.
     *
     * @since 2.2.1
     * @access public
     *
     * @return string
     */
    public function get_plugin_basename_by_slug( $plugin_slug ) {
        $allowed_plugins = $this->get_allowed_plugins();

        return $allowed_plugins[ $plugin_slug ] ?? '';
    }
}
