<?php
/**
 * Plugins REST API Controller.
 *
 * Provides endpoints to check, install and activate plugins from the Setup Wizard.
 *
 * @package Ugcify\Admin\API
 */

namespace Ugcify\Admin\API;

use WP_REST_Controller;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class PluginsAPI
 */
class PluginsAPI extends WP_REST_Controller {

	/**
	 * Namespace.
	 *
	 * @var string
	 */
	protected $namespace = 'ugcify/v1';

	/**
	 * Rest base.
	 *
	 * @var string
	 */
	protected $rest_base = 'setup-wizard/plugins';

	/**
	 * Supported plugins — slug => plugin file path.
	 *
	 * @var array
	 */
	const PLUGINS = array(
		'woocommerce' => array(
			'name' => 'WooCommerce',
			'file' => 'woocommerce/woocommerce.php',
			'slug' => 'woocommerce',
		),
		'mail-mint'   => array(
			'name' => 'Mail Mint',
			'file' => 'mail-mint/mail-mint.php',
			'slug' => 'mail-mint',
		),
	);

	/**
	 * Register routes.
	 */
	public function register_routes() {
		// GET /setup-wizard/plugins/status
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/status',
			array(
				array(
					'methods'             => WP_REST_Server::READABLE,
					'callback'            => array( $this, 'get_status' ),
					'permission_callback' => array( $this, 'check_permission' ),
				),
			)
		);

		// POST /setup-wizard/plugins/install
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/install',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'install_plugin' ),
					'permission_callback' => array( $this, 'check_permission' ),
					'args'                => array(
						'slug' => array(
							'type'              => 'string',
							'required'          => true,
							'sanitize_callback' => 'sanitize_text_field',
						),
					),
				),
			)
		);

		// POST /setup-wizard/plugins/activate
		register_rest_route(
			$this->namespace,
			'/' . $this->rest_base . '/activate',
			array(
				array(
					'methods'             => WP_REST_Server::CREATABLE,
					'callback'            => array( $this, 'activate_plugin_endpoint' ),
					'permission_callback' => array( $this, 'check_permission' ),
					'args'                => array(
						'slug' => array(
							'type'              => 'string',
							'required'          => true,
							'sanitize_callback' => 'sanitize_text_field',
						),
					),
				),
			)
		);
	}

	/**
	 * Permission callback — requires install_plugins capability.
	 *
	 * @return bool|WP_Error
	 */
	public function check_permission() {
		if ( ! current_user_can( 'install_plugins' ) ) {
			return new WP_Error(
				'rest_forbidden',
				__( 'Sorry, you are not allowed to manage plugins.', 'ugcify' ),
				array( 'status' => 403 )
			);
		}
		return true;
	}

	/**
	 * GET /status — return installed/active status for each supported plugin.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response
	 */
	public function get_status( WP_REST_Request $request ) {
		$this->load_plugin_functions();

		$statuses = array();
		foreach ( self::PLUGINS as $slug => $plugin ) {
			$statuses[ $slug ] = $this->resolve_plugin_status( $plugin['file'] );
		}

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

	/**
	 * POST /install — install (from WordPress.org) and activate a plugin.
	 * If the plugin is already installed, it is only activated.
	 * If it is already active, a success response is returned immediately.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function install_plugin( WP_REST_Request $request ) {
		$slug = $request->get_param( 'slug' );

		if ( ! isset( self::PLUGINS[ $slug ] ) ) {
			return new WP_Error(
				'invalid_plugin',
				__( 'Unknown plugin slug.', 'ugcify' ),
				array( 'status' => 400 )
			);
		}

		$this->load_plugin_functions();
		$plugin = self::PLUGINS[ $slug ];
		$status = $this->resolve_plugin_status( $plugin['file'] );

		// Already active — nothing to do.
		if ( 'active' === $status ) {
			return rest_ensure_response(
				array(
					'success' => true,
					'data'    => array( 'status' => 'active' ),
				)
			);
		}

		// Installed but not active — just activate.
		if ( 'installed' === $status ) {
			return $this->do_activate( $plugin['file'] );
		}

		// Not installed — fetch from WordPress.org, install and activate.
		return $this->do_install_and_activate( $slug, $plugin['file'] );
	}

	/**
	 * POST /activate — activate an already-installed plugin.
	 *
	 * @param WP_REST_Request $request Request object.
	 * @return WP_REST_Response|WP_Error
	 */
	public function activate_plugin_endpoint( WP_REST_Request $request ) {
		$slug = $request->get_param( 'slug' );

		if ( ! isset( self::PLUGINS[ $slug ] ) ) {
			return new WP_Error(
				'invalid_plugin',
				__( 'Unknown plugin slug.', 'ugcify' ),
				array( 'status' => 400 )
			);
		}

		$this->load_plugin_functions();
		$plugin = self::PLUGINS[ $slug ];

		return $this->do_activate( $plugin['file'] );
	}

	// ─── Private helpers ─────────────────────────────────────────────────────

	/**
	 * Determine the status of a plugin: 'active', 'installed', or 'not_installed'.
	 *
	 * Uses both is_plugin_active() and a direct option lookup to ensure correctness
	 * in REST API contexts where the active-plugin state may not be fully initialised.
	 *
	 * @param string $plugin_file Relative plugin file (e.g. 'woocommerce/woocommerce.php').
	 * @return string
	 */
	private function resolve_plugin_status( $plugin_file ) {
		// Primary check via WordPress helper (works when wp-admin context is loaded).
		if ( is_plugin_active( $plugin_file ) ) {
			return 'active';
		}

		// Fallback: read active_plugins option directly — reliable in REST API context.
		$active_plugins = (array) get_option( 'active_plugins', array() );
		if ( in_array( $plugin_file, $active_plugins, true ) ) {
			return 'active';
		}

		// Network-activated plugins (multisite).
		if ( is_multisite() ) {
			$network_plugins = (array) get_site_option( 'active_sitewide_plugins', array() );
			if ( isset( $network_plugins[ $plugin_file ] ) ) {
				return 'active';
			}
		}

		if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin_file ) ) {
			return 'installed';
		}

		return 'not_installed';
	}

	/**
	 * Activate a plugin and return a REST response.
	 *
	 * @param string $plugin_file Relative plugin file path.
	 * @return WP_REST_Response|WP_Error
	 */
	private function do_activate( $plugin_file ) {
		if ( ! function_exists( 'activate_plugin' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}

		$result = activate_plugin( $plugin_file );

		if ( is_wp_error( $result ) ) {
			return new WP_Error(
				'activation_failed',
				$result->get_error_message(),
				array( 'status' => 500 )
			);
		}

		$this->suppress_plugin_activation_redirects( $plugin_file );

		return rest_ensure_response(
			array(
				'success' => true,
				'data'    => array( 'status' => 'active' ),
			)
		);
	}

	/**
	 * Suppress third-party onboarding redirects after activation from UGCify setup.
	 *
	 * @param string $plugin_file Relative plugin file path.
	 * @return void
	 */
	private function suppress_plugin_activation_redirects( $plugin_file ) {
		if ( 'mail-mint/mail-mint.php' === $plugin_file ) {
			delete_transient( 'mailmint_show_setup_wizard' );
		}
	}

	/**
	 * Download from WordPress.org, install, then activate.
	 *
	 * @param string $slug        WordPress.org plugin slug.
	 * @param string $plugin_file Relative plugin file path.
	 * @return WP_REST_Response|WP_Error
	 */
	private function do_install_and_activate( $slug, $plugin_file ) {
		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-install.php';

		// Fetch plugin info to get the download_link.
		$api = plugins_api(
			'plugin_information',
			array(
				'slug'   => $slug,
				'fields' => array(
					'downloadlink'     => true,
					'short_description' => false,
					'sections'         => false,
					'requires'         => false,
					'downloaded'       => false,
					'last_updated'     => false,
					'added'            => false,
					'tags'             => false,
					'compatibility'    => false,
					'homepage'         => false,
					'donate_link'      => false,
				),
			)
		);

		if ( is_wp_error( $api ) ) {
			return new WP_Error(
				'plugin_info_failed',
				/* translators: %s: error message */
				sprintf( __( 'Could not fetch plugin info: %s', 'ugcify' ), $api->get_error_message() ),
				array( 'status' => 502 )
			);
		}

		$upgrader = new \Plugin_Upgrader( new \WP_Ajax_Upgrader_Skin() );
		$result   = $upgrader->install( $api->download_link );

		if ( is_wp_error( $result ) ) {
			return new WP_Error(
				'install_failed',
				$result->get_error_message(),
				array( 'status' => 500 )
			);
		}

		// $result can be false/null when WP refuses to re-install an existing plugin.
		// In that case the file is now on disk — just activate it.
		if ( false === $result || null === $result ) {
			if ( file_exists( WP_PLUGIN_DIR . '/' . $plugin_file ) ) {
				return $this->do_activate( $plugin_file );
			}
			return new WP_Error(
				'install_failed',
				__( 'Plugin installation failed.', 'ugcify' ),
				array( 'status' => 500 )
			);
		}

		// Activate after a successful install.
		return $this->do_activate( $plugin_file );
	}

	/**
	 * Load WordPress plugin administration functions.
	 */
	private function load_plugin_functions() {
		if ( ! function_exists( 'is_plugin_active' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin.php';
		}
	}
}
