<?php
/**
 * Plugin Utility REST Controller
 *
 * @category   WordPress_Plugin
 * @package    Common
 * @subpackage Controllers\Rest_API
 * @author     miniOrange <info@miniorange.com>
 * @license    miniOrange
 * @link       https://plugins.miniorange.com
 */

namespace MOWCPS\Common\Controllers\Rest_API;

use WP_REST_Request;
use WP_REST_Response;
use WP_Error;
use MOWCPS\Common\Constants\Constants;
use MOWCPS\Common\Abstracts\Base_Rest_Controller;
use MOWCPS\Common\Utils\Response_Builder;

if ( ! defined( 'ABSPATH' ) ) {
	die;
}

/**
 * Class Plugin_Utility_Rest_Controller
 *
 * Handles plugin utility operations like checking plugin status
 */
class Plugin_Utility_Rest_Controller extends Base_Rest_Controller {

	/**
	 * Check if a plugin is active
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error Response object or error.
	 */
	public function check_plugin( $request ) {
		$plugin_slug = sanitize_text_field( wp_unslash( $request->get_param( 'slug' ) ) );

		if ( empty( $plugin_slug ) ) {
			return Response_Builder::error( Constants::MSG_PLUGIN_SLUG_REQUIRED, Constants::HTTP_BAD_REQUEST );
		}

		// Get plugin path.
		$plugin_path = $this->get_plugin_path( $plugin_slug );

		// Check plugin status.
		$is_installed = $this->check_plugin_installed( $plugin_path );
		$is_active    = false;

		if ( $is_installed ) {
			$is_active = $this->check_plugin_active( $plugin_path );
		}

		// Determine status.
		$status = Constants::PLUGIN_STATUS_NOT_INSTALLED;
		if ( $is_active ) {
			$status = Constants::PLUGIN_STATUS_ACTIVE;
		} elseif ( $is_installed ) {
			$status = Constants::PLUGIN_STATUS_INSTALLED;
		}

		return Response_Builder::success(
			array(
				'is_active'    => $is_active,
				'is_installed' => $is_installed,
				'status'       => $status,
				'slug'         => $plugin_slug,
				'plugin_path'  => $plugin_path,
			),
			Constants::MSG_PLUGIN_STATUS_CHECKED
		);
	}

	/**
	 * Get plugin path based on slug
	 *
	 * @param string $plugin_slug Plugin slug.
	 * @return string Plugin path.
	 */
	private function get_plugin_path( $plugin_slug ) {
		// Map of known plugin slugs to their file paths.
		$plugin_paths = array(
			'woo-variation-swatches' => 'woo-variation-swatches/woo-variation-swatches.php',
			'woo-variation-gallery'  => 'woo-variation-gallery/woo-variation-gallery.php',
		);

		// Check if we have a known path for this slug.
		if ( isset( $plugin_paths[ $plugin_slug ] ) ) {
			return $plugin_paths[ $plugin_slug ];
		}

		// If not found in map, try to construct the path.
		return $plugin_slug . '/' . $plugin_slug . '.php';
	}

	/**
	 * Check if plugin is installed
	 *
	 * @param string $plugin_path Plugin path (e.g., 'plugin-folder/plugin-file.php').
	 * @return bool True if installed, false otherwise.
	 */
	private function check_plugin_installed( $plugin_path ) {
		// Include plugin.php if not already loaded.
		if ( ! function_exists( 'get_plugins' ) ) {
			include_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		// Get all installed plugins.
		$all_plugins = get_plugins();

		// Check if the plugin exists in the installed plugins array.
		return isset( $all_plugins[ $plugin_path ] );
	}

	/**
	 * Check if plugin is active
	 *
	 * @param string $plugin_path Plugin path (e.g., 'plugin-folder/plugin-file.php').
	 * @return bool True if active, false otherwise.
	 */
	private function check_plugin_active( $plugin_path ) {
		// Include plugin.php if not already loaded.
		if ( ! function_exists( 'is_plugin_active' ) ) {
			include_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		return is_plugin_active( $plugin_path );
	}

	/**
	 * Activate a plugin
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error Response object or error.
	 */
	public function activate_plugin( $request ) {
		$plugin_path = sanitize_text_field( wp_unslash( $request->get_param( 'plugin_path' ) ) );

		if ( empty( $plugin_path ) ) {
			return Response_Builder::error( Constants::MSG_PLUGIN_PATH_REQUIRED, Constants::HTTP_BAD_REQUEST );
		}

		// Include plugin.php if not already loaded.
		if ( ! function_exists( 'activate_plugin' ) ) {
			include_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		// Check if plugin exists before activating.
		$is_installed = $this->check_plugin_installed( $plugin_path );

		if ( ! $is_installed ) {
			return Response_Builder::error( Constants::MSG_PLUGIN_NOT_INSTALLED, Constants::HTTP_NOT_FOUND );
		}

		// Attempt to activate the plugin.
		$result = activate_plugin( $plugin_path );

		if ( is_wp_error( $result ) ) {
			$message = Constants::MSG_PLUGIN_ACTIVATE_FAILED . $result->get_error_message();
			return Response_Builder::error( $message, Constants::HTTP_INTERNAL_SERVER_ERROR );
		}

		return Response_Builder::success(
			array(
				'plugin_path' => $plugin_path,
				'is_active'   => true,
			),
			Constants::MSG_PLUGIN_ACTIVATED
		);
	}

	/**
	 * Install and activate a plugin from WordPress.org
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error Response object or error.
	 */
	public function install_plugin( $request ) {
		$plugin_slug = sanitize_text_field( wp_unslash( $request->get_param( 'slug' ) ) );

		if ( empty( $plugin_slug ) ) {
			return Response_Builder::error( Constants::MSG_PLUGIN_SLUG_REQUIRED, Constants::HTTP_BAD_REQUEST );
		}

		// Check if user has permission to install plugins.
		if ( ! current_user_can( 'install_plugins' ) ) {
			return Response_Builder::error( Constants::MSG_NO_INSTALL_PERMISSION, Constants::HTTP_FORBIDDEN );
		}

		// Include required files for plugin installation.
		if ( ! function_exists( 'plugins_api' ) ) {
			include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
		}
		if ( ! class_exists( 'Plugin_Upgrader' ) ) {
			include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
		}
		if ( ! function_exists( 'show_message' ) ) {
			include_once ABSPATH . 'wp-admin/includes/misc.php';
		}
		// Include file.php for wp_install_plugin_promotion() and other file functions.
		if ( ! function_exists( 'request_filesystem_credentials' ) ) {
			include_once ABSPATH . 'wp-admin/includes/file.php';
		}

		// Get plugin information from WordPress.org.
		$api = plugins_api(
			'plugin_information',
			array(
				'slug'   => $plugin_slug,
				'fields' => array(
					'short_description' => false,
					'sections'          => false,
					'requires'          => false,
					'rating'            => false,
					'ratings'           => false,
					'downloaded'        => false,
					'last_updated'      => false,
					'added'             => false,
					'tags'              => false,
					'compatibility'     => false,
					'homepage'          => false,
					'donate_link'       => false,
				),
			)
		);

		if ( is_wp_error( $api ) ) {
			$message = Constants::MSG_PLUGIN_INFO_FAILED . $api->get_error_message();
			return Response_Builder::error( $message, Constants::HTTP_INTERNAL_SERVER_ERROR );
		}

		ob_start();

		$upgrader = new \Plugin_Upgrader( new \WP_Upgrader_Skin() );

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

		// Discard any output generated during installation.
		ob_end_clean();

		if ( is_wp_error( $install_result ) ) {
			$message = Constants::MSG_PLUGIN_INSTALL_FAILED . $install_result->get_error_message();
			return Response_Builder::error( $message, Constants::HTTP_INTERNAL_SERVER_ERROR );
		}

		if ( true !== $install_result ) {
			// Get any errors from the skin.
			$errors = $skin->get_errors();
			if ( $errors->has_errors() ) {
				$message = Constants::MSG_PLUGIN_INSTALLATION_FAILED . ' ' . $errors->get_error_message();
				return Response_Builder::error( $message, Constants::HTTP_INTERNAL_SERVER_ERROR );
			}
			return Response_Builder::error( Constants::MSG_PLUGIN_INSTALLATION_FAILED, Constants::HTTP_INTERNAL_SERVER_ERROR );
		}

		// Get the plugin path after installation.
		$plugin_path = $this->get_plugin_path( $plugin_slug );

		// Activate the plugin.
		$activate_result = activate_plugin( $plugin_path );

		if ( is_wp_error( $activate_result ) ) {
			$message = Constants::MSG_PLUGIN_INSTALL_ACTIVATE_FAILED . $activate_result->get_error_message();
			return Response_Builder::error( $message, Constants::HTTP_INTERNAL_SERVER_ERROR );
		}

		return Response_Builder::success(
			array(
				'plugin_slug' => $plugin_slug,
				'plugin_path' => $plugin_path,
				'is_active'   => true,
			),
			Constants::MSG_PLUGIN_INSTALLED_ACTIVATED
		);
	}
}
