<?php
/**
 * Plugin Name: WP PowerSuite
 * Plugin URI: https://wppowersuite.com/
 * Description: A modular WordPress plugin system with 150+ modules. Zero runtime cost for disabled modules.
 * Version: 1.0.6
 * Author: Muhammad Muzammil
 * Author URI: https://wppowersuite.com
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: wp-powersuite
 * Domain Path: /languages
 * Requires at least: 6.0
 * Requires PHP: 8.1
 * Network: true
 *
 * @package WP_PowerSuite
 * @version 1.0.6
 * @since 1.0.0
 */

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

define( 'WP_POWERSUITE_VERSION', '1.0.6' );
define( 'WP_POWERSUITE_MIN_PHP_VERSION', '8.1' );
define( 'WP_POWERSUITE_MIN_WP_VERSION', '6.0' );
define( 'WP_POWERSUITE_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'WP_POWERSUITE_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'WP_POWERSUITE_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
define( 'WP_POWERSUITE_PLUGIN_FILE', __FILE__ );
define( 'WP_POWERSUITE_SRC_DIR', WP_POWERSUITE_PLUGIN_DIR . 'src' . DIRECTORY_SEPARATOR );
define( 'WP_POWERSUITE_MODULES_DIR', WP_POWERSUITE_PLUGIN_DIR . 'modules' . DIRECTORY_SEPARATOR );
define( 'WP_POWERSUITE_MODULES_MANIFEST', WP_POWERSUITE_PLUGIN_DIR . 'data' . DIRECTORY_SEPARATOR . 'modules-manifest.json' );
define( 'WP_POWERSUITE_OPTION_PREFIX', 'wp_powersuite_' );
define( 'WP_POWERSUITE_TRANSIENT_PREFIX', 'wp_powersuite_' );
define( 'WP_POWERSUITE_PRODUCT_URL', 'https://wppowersuite.com/' );
define( 'WP_POWERSUITE_RENEW_URL', 'https://wppowersuite.com/renew' );
define( 'WP_POWERSUITE_SUPPORT_URL', 'https://wppowersuite.com/support' );
define( 'WP_POWERSUITE_DOCS_URL', 'https://wppowersuite.com/docs' );
// Optional: override in wp-config.php to receive deactivation feedback by email or webhook.
if ( ! defined( 'WP_POWERSUITE_DEACTIVATION_FEEDBACK_WEBHOOK' ) ) {
	define( 'WP_POWERSUITE_DEACTIVATION_FEEDBACK_WEBHOOK', 'https://wppowersuite.com/wp-json/licensor/deactivation-feedback' );
}

/** @var list<array{title_id: string, message_id: string, message_args: list<string|int|float>}> */
$GLOBALS['wp_powersuite_admin_notices'] = [];

/**
 * HTML attribute marking a notice as owned by WP PowerSuite (excluded from hide-notices).
 *
 * @since 1.0.0
 */
function wp_powersuite_plugin_notice_attr(): string {
	return ' data-wpps-plugin="true"';
}

/**
 * Queue an admin error notice for deferred translation and display.
 *
 * @since 1.0.0
 * @param string               $message_id   English message (gettext msgid).
 * @param list<string|int|float> $message_args Optional sprintf args applied after translation.
 * @param string               $title_id     English title (gettext msgid).
 */
function wp_powersuite_queue_admin_notice( string $message_id, array $message_args = [], string $title_id = 'WP PowerSuite Error' ): void {
	$GLOBALS['wp_powersuite_admin_notices'][] = [
		'title_id'     => $title_id,
		'message_id'   => $message_id,
		'message_args' => $message_args,
	];

	wp_powersuite_register_deferred_admin_notices();
}

/**
 * Register the init hook that renders queued admin notices after textdomain load.
 *
 * @since 1.0.0
 */
function wp_powersuite_register_deferred_admin_notices(): void {
	static $registered = false;
	if ( $registered ) {
		return;
	}

	$registered = true;
	add_action( 'init', 'wp_powersuite_render_deferred_admin_notices', 1 );
}

/**
 * Translate queued notices and attach them to admin_notices.
 *
 * @since 1.0.0
 */
function wp_powersuite_render_deferred_admin_notices(): void {
	if ( empty( $GLOBALS['wp_powersuite_admin_notices'] ) ) {
		return;
	}

	$notices = $GLOBALS['wp_powersuite_admin_notices'];

	add_action(
		'admin_notices',
		static function () use ( $notices ): void {
			foreach ( $notices as $notice ) {
				$title = __( $notice['title_id'], 'wp-powersuite' );
				$message = __( $notice['message_id'], 'wp-powersuite' );
				if ( ! empty( $notice['message_args'] ) ) {
					$message = vsprintf( $message, $notice['message_args'] );
				}

				printf(
					'<div class="notice notice-error"%1$s><p><strong>%2$s</strong>: %3$s</p></div>',
					wp_powersuite_plugin_notice_attr(),
					esc_html( $title ),
					esc_html( $message )
				);
			}
		}
	);
}

/**
 * Check PHP Version Compatibility
 *
 * Exits with an admin notice if PHP version is below minimum requirement.
 *
 * @since 1.0.0
 */
function wp_powersuite_check_php_version() {
	if ( version_compare( PHP_VERSION, WP_POWERSUITE_MIN_PHP_VERSION, '<' ) ) {
		wp_powersuite_queue_admin_notice(
			'WP PowerSuite requires PHP %2$s or higher. You are running PHP %1$s.',
			[ PHP_VERSION, WP_POWERSUITE_MIN_PHP_VERSION ]
		);
		return false;
	}
	return true;
}

/**
 * Check WordPress Version Compatibility
 *
 * Exits with an admin notice if WordPress version is below minimum requirement.
 *
 * @since 1.0.0
 */
function wp_powersuite_check_wp_version() {
	global $wp_version;
	if ( version_compare( $wp_version, WP_POWERSUITE_MIN_WP_VERSION, '<' ) ) {
		wp_powersuite_queue_admin_notice(
			'WP PowerSuite requires WordPress %2$s or higher. You are running WordPress %1$s.',
			[ $wp_version, WP_POWERSUITE_MIN_WP_VERSION ]
		);
		return false;
	}
	return true;
}

/**
 * Bootstrap Directory Path
 *
 * Absolute path to the bootstrap directory (with trailing slash).
 *
 * @var string
 */
define( 'WP_POWERSUITE_BOOTSTRAP_DIR', WP_POWERSUITE_PLUGIN_DIR . 'bootstrap' . DIRECTORY_SEPARATOR );

/**
 * Licensing Directory Path
 *
 * Absolute path to the licensing directory (with trailing slash).
 *
 * @var string
 */
define( 'WP_POWERSUITE_LICENSING_DIR', WP_POWERSUITE_PLUGIN_DIR . 'includes' . DIRECTORY_SEPARATOR . 'licensing' . DIRECTORY_SEPARATOR );

/**
 * Required licensing class files (relative to {@see WP_POWERSUITE_LICENSING_DIR}).
 *
 * @since 1.0.0
 * @return list<string>
 */
function wp_powersuite_licensing_required_files(): array {
	return [
		'license-bootstrap.php',
		'class-wpps-elite-licenser-client.php',
		'class-w-p-power-suite-premium-base.php',
		'class-wpps-license-manager.php',
	];
}

/**
 * Whether this build ships with premium licensing infrastructure.
 *
 * Licensing is expected when the bootstrap file and all required class files exist.
 *
 * @since 1.0.0
 * @return bool True when licensing files are present in this distribution.
 */
function wp_powersuite_is_licensing_expected(): bool {
	foreach ( wp_powersuite_licensing_required_files() as $file ) {
		if ( ! file_exists( WP_POWERSUITE_LICENSING_DIR . $file ) ) {
			return false;
		}
	}
	return true;
}

/**
 * Load License Bootstrap
 *
 * Loads Elite Licenser base class and LicenseManager. Must be called
 * before plugin init to perform license validation.
 *
 * @since 1.0.0
 * @return bool True if licensing files loaded, false otherwise.
 */
function wp_powersuite_load_license_bootstrap(): bool {
	if ( ! wp_powersuite_is_licensing_expected() ) {
		return false;
	}

	require_once WP_POWERSUITE_LICENSING_DIR . 'license-bootstrap.php';
	return class_exists( 'W_P_Power_Suite_Premium_Base', false ) && class_exists( 'WPPS_License_Manager', false );
}

/**
 * Check if license is valid (for premium module gating).
 *
 * Entitlement: activated on this site and not revoked. Expired subscriptions
 * remain entitled to premium features. Builds without licensing files are not gated.
 *
 * @since 1.0.0
 * @return bool True when premium features may run, false otherwise.
 */
function wp_powersuite_is_license_valid(): bool {
	if ( ! wp_powersuite_is_licensing_expected() ) {
		return true;
	}

	if ( ! class_exists( 'WPPS_License_Manager', false ) ) {
		return false;
	}

	return WPPS_License_Manager::get_instance()->is_valid();
}

/**
 * Whether the license is current for plugin updates and support.
 *
 * Requires entitlement via {@see wp_powersuite_is_license_valid()} and a
 * non-expired license period.
 *
 * @since 1.0.0
 */
function wp_powersuite_is_license_current(): bool {
	if ( ! wp_powersuite_is_licensing_expected() ) {
		return true;
	}

	if ( ! class_exists( 'WPPS_License_Manager', false ) ) {
		return false;
	}

	return WPPS_License_Manager::get_instance()->is_current();
}

/**
 * Whether the site has an Agency / white-label license tier.
 *
 * Requires a valid license. Builds without licensing never qualify unless
 * filtered via {@see 'wp_powersuite_is_agency_license'}.
 *
 * @since 1.0.0
 */
function wp_powersuite_has_agency_license(): bool {
	if ( ! wp_powersuite_is_license_valid() ) {
		return false;
	}

	if ( ! class_exists( 'WPPS_License_Manager', false ) ) {
		return false;
	}

	return WPPS_License_Manager::get_instance()->is_agency_license();
}

/**
 * Whether the current request is a PowerSuite admin-ajax action.
 *
 * @since 1.0.0
 */
function wp_powersuite_is_ajax_request(): bool {
	if ( ! defined( 'DOING_AJAX' ) || ! DOING_AJAX ) {
		return false;
	}

	$action = isset( $_REQUEST['action'] ) ? sanitize_key( wp_unslash( $_REQUEST['action'] ) ) : '';
	if ( $action === '' ) {
		return false;
	}

	if ( str_starts_with( $action, 'wp_powersuite_' ) ) {
		return true;
	}

	return in_array( $action, [ 'wpps_set_delete_preference', 'wpps_deactivation_feedback' ], true );
}

/**
 * Load Bootstrap Files
 *
 * Loads the autoloader and kernel bootstrap files.
 *
 * @since 1.0.0
 * @return bool True if bootstrap files were loaded, false otherwise.
 */
function wp_powersuite_load_bootstrap(): bool {
	$autoloader_file = WP_POWERSUITE_BOOTSTRAP_DIR . 'autoloader.php';
	$kernel_file     = WP_POWERSUITE_BOOTSTRAP_DIR . 'kernel.php';

	if ( ! file_exists( $autoloader_file ) || ! file_exists( $kernel_file ) ) {
		return false;
	}

	require_once $autoloader_file;
	require_once $kernel_file;

	return true;
}

/**
 * Register PSR-4 Autoloader
 *
 * Registers the PSR-4 autoloader for the WP PowerSuite namespace.
 * Maps 'WP_PowerSuite' namespace to 'src' directory.
 *
 * @since 1.0.0
 * @return bool True if autoloader was registered, false otherwise.
 */
function wp_powersuite_register_autoloader() {
	// Load bootstrap files if not already loaded (contains register_autoloader function)
	if ( ! function_exists( '\WP_PowerSuite\Bootstrap\register_autoloader' ) ) {
		if ( ! wp_powersuite_load_bootstrap() ) {
			return false;
		}
	}

	// Verify function exists after loading bootstrap
	if ( ! function_exists( '\WP_PowerSuite\Bootstrap\register_autoloader' ) ) {
		return false;
	}

	// Register autoloader using bootstrap function
	return \WP_PowerSuite\Bootstrap\register_autoloader( 'WP_PowerSuite', WP_POWERSUITE_SRC_DIR );
}

/**
 * Add plugin row action links (Settings, Docs, Support) next to Deactivate.
 *
 * @since 1.0.0
 * @param array<string> $links Existing plugin action links.
 * @return array<string> Modified links.
 */
function wp_powersuite_plugin_action_links( array $links ): array {
	if ( class_exists( '\WP_PowerSuite\Core\WhiteLabel', false ) ) {
		return \WP_PowerSuite\Core\WhiteLabel::filterPluginActionLinks( $links );
	}

	$settings_url = admin_url( 'admin.php?page=powersuite-settings' );
	$links['settings'] = '<a href="' . esc_url( $settings_url ) . '">' . esc_html__( 'Settings', 'wp-powersuite' ) . '</a>';

	return $links;
}

/**
 * Global branding helpers (delegate to WhiteLabel when available).
 */
function wp_powersuite_get_plugin_name(): string {
	return class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
		? \WP_PowerSuite\Core\WhiteLabel::get_plugin_name()
		: __( 'WP PowerSuite', 'wp-powersuite' );
}

function wp_powersuite_get_plugin_short_name(): string {
	return class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
		? \WP_PowerSuite\Core\WhiteLabel::get_plugin_short_name()
		: __( 'PowerSuite', 'wp-powersuite' );
}

function wp_powersuite_get_company_name(): string {
	return class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
		? \WP_PowerSuite\Core\WhiteLabel::get_company_name()
		: __( 'WP PowerSuite', 'wp-powersuite' );
}

function wp_powersuite_get_support_url(): string {
	return class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
		? \WP_PowerSuite\Core\WhiteLabel::get_support_url()
		: ( defined( 'WP_POWERSUITE_SUPPORT_URL' ) ? WP_POWERSUITE_SUPPORT_URL : 'https://wppowersuite.com/support' );
}

function wp_powersuite_get_documentation_url(): string {
	return class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
		? \WP_PowerSuite\Core\WhiteLabel::get_documentation_url()
		: ( defined( 'WP_POWERSUITE_DOCS_URL' ) ? WP_POWERSUITE_DOCS_URL : 'https://wppowersuite.com/docs' );
}

function wp_powersuite_is_vendor_branding_hidden(): bool {
	return class_exists( '\WP_PowerSuite\Core\WhiteLabel', false )
		&& \WP_PowerSuite\Core\WhiteLabel::is_vendor_branding_hidden();
}

/**
 * Log init failure details and register a generic admin notice.
 *
 * @since 1.0.0
 * @param string $log_message  Detailed message for error_log only.
 * @param string $user_message Optional user-facing message.
 * @return void
 */
function wp_powersuite_init_error_notice( string $log_message, string $user_message = '' ): void {
	error_log( 'WP PowerSuite initialization error: ' . $log_message );

	if ( $user_message === '' ) {
		$user_message = 'WP PowerSuite could not initialize. Please reinstall the plugin or contact support.';
	}

	wp_powersuite_queue_admin_notice( $user_message );
}

/**
 * Initialize WP PowerSuite Plugin
 *
 * Main initialization function that sets up the plugin kernel.
 * This function is hooked into 'plugins_loaded' to ensure WordPress
 * is fully loaded before plugin initialization.
 *
 * @since 1.0.0
 * @return void
 */
function wp_powersuite_init() {
	// Step 1: Load bootstrap files (contains Kernel class)
	if ( ! wp_powersuite_load_bootstrap() ) {
		$bootstrap_dir = defined( 'WP_POWERSUITE_BOOTSTRAP_DIR' ) ? WP_POWERSUITE_BOOTSTRAP_DIR : 'Not defined';
		wp_powersuite_init_error_notice(
			'Bootstrap files missing or unreadable. Bootstrap dir: ' . $bootstrap_dir,
			'Failed to load WP PowerSuite bootstrap files. Please reinstall the plugin.'
		);
		return;
	}

	// Step 2: Register autoloader (needed for Plugin and other core classes)
	if ( ! wp_powersuite_register_autoloader() ) {
		$src_dir = defined( 'WP_POWERSUITE_SRC_DIR' ) ? WP_POWERSUITE_SRC_DIR : 'Not defined';
		wp_powersuite_init_error_notice(
			'Autoloader registration failed. Src dir: ' . $src_dir,
			'Failed to register WP PowerSuite autoloader. Please reinstall the plugin.'
		);
		return;
	}

	// Step 3: Translations load on init@0 via Kernel::loadTextdomainOnInit (WordPress 6.7+).
	// Do not call loadTextdomain here on plugins_loaded — it triggers _load_textdomain_just_in_time notices.

	// Step 4: License - load licensing and validate (never blocks plugin)
	if ( wp_powersuite_load_license_bootstrap() ) {
		$license_manager = WPPS_License_Manager::get_instance();
		$license_manager->init();
		$license_manager->register_admin_hooks();
	}

	// Step 5: Verify Kernel class exists (should exist after loading bootstrap)
	if ( ! class_exists( 'WP_PowerSuite\Bootstrap\Kernel', false ) ) {
		wp_powersuite_init_error_notice(
			'Kernel class not found after loading bootstrap files.',
			'Kernel class not found after loading bootstrap files.'
		);
		return;
	}

	// Step 6: Verify Plugin class exists (should be autoloadable)
	if ( ! class_exists( 'WP_PowerSuite\Core\Plugin', false ) ) {
		// Try to trigger autoloader
		if ( ! class_exists( 'WP_PowerSuite\Core\Plugin', true ) ) {
			$plugin_file = defined( 'WP_POWERSUITE_SRC_DIR' )
				? WP_POWERSUITE_SRC_DIR . 'Core' . DIRECTORY_SEPARATOR . 'Plugin.php'
				: 'Not defined';
			wp_powersuite_init_error_notice(
				sprintf(
					'Plugin class not autoloadable. Plugin file: %s; file exists: %s',
					$plugin_file,
					file_exists( $plugin_file ) ? 'yes' : 'no'
				),
				'Failed to load Plugin class. Please reinstall the plugin.'
			);
			return;
		}
	}

	// Initialize the plugin kernel
	try {
		$kernel = \WP_PowerSuite\Bootstrap\Kernel::getInstance();
		$kernel->init();

		// Plugin row action links are registered by WhiteLabel::init() via the kernel bootstrap.
	} catch ( \Exception $e ) {
		wp_powersuite_init_error_notice(
			sprintf(
				'%s in %s:%d',
				$e->getMessage(),
				$e->getFile(),
				$e->getLine()
			)
		);
	}
}

// Perform compatibility checks before proceeding
if ( ! wp_powersuite_check_php_version() || ! wp_powersuite_check_wp_version() ) {
	return;
}

/**
 * Get WP PowerSuite Plugin Instance
 *
 * Global helper function to access the main Plugin instance.
 * Returns null if plugin is not initialized.
 *
 * @since 1.0.0
 * @return \WP_PowerSuite\Core\Plugin|null Plugin instance or null if not initialized.
 */
function wp_powersuite(): ?\WP_PowerSuite\Core\Plugin {
	try {
		$kernel = \WP_PowerSuite\Bootstrap\Kernel::getInstance();
		if ( $kernel->isInitialized() ) {
			return $kernel->getPlugin();
		}
	} catch ( \Exception $e ) {
		unset( $e );
	}
	return null;
}

/**
 * Get WP PowerSuite Kernel Instance
 *
 * Global helper function to access the Kernel instance.
 * Returns null if kernel is not initialized.
 *
 * @since 1.0.0
 * @return \WP_PowerSuite\Bootstrap\Kernel|null Kernel instance or null if not initialized.
 */
function wp_powersuite_kernel(): ?\WP_PowerSuite\Bootstrap\Kernel {
	try {
		$kernel = \WP_PowerSuite\Bootstrap\Kernel::getInstance();
		if ( $kernel->isInitialized() ) {
			return $kernel;
		}
	} catch ( \Exception $e ) {
		unset( $e );
	}
	return null;
}

/**
 * Uninstall handler - prompts user to delete all data
 */
function wpps_uninstall_plugin() {
	if ( class_exists( 'W_P_Power_Suite_Premium_Base' ) ) {
		W_P_Power_Suite_Premium_Base::run_on_delete_callbacks();
	}

	// Include uninstall.php which handles the actual deletion
	if ( file_exists( __DIR__ . '/uninstall.php' ) ) {
		require_once __DIR__ . '/uninstall.php';
		
		// Check if user wants to delete all data
		if ( function_exists( 'wpps_should_delete_all_data' ) && wpps_should_delete_all_data() ) {
			if ( function_exists( 'wpps_delete_all_plugin_data' ) ) {
				wpps_delete_all_plugin_data();
			}
		}
	}
}

/**
 * Bootstrap core classes required during activation/deactivation.
 *
 * @since 1.0.0
 * @return bool True when autoloader is available.
 */
function wp_powersuite_bootstrap_for_lifecycle(): bool {
	if ( ! wp_powersuite_load_bootstrap() ) {
		return false;
	}

	return wp_powersuite_register_autoloader();
}

/**
 * Plugin activation callback.
 *
 * Multisite: WordPress invokes this once per site. When the plugin is
 * network-activated, shared settings use site options ({@see NetworkScope});
 * per-site activation stores settings in each blog's options table. See
 * {@see \WP_PowerSuite\Core\PluginLifecycle} for full behavior.
 *
 * @since 1.0.0
 * @return void
 */
function wp_powersuite_activate(): void {
	if ( ! wp_powersuite_bootstrap_for_lifecycle() ) {
		return;
	}

	wp_powersuite_load_license_bootstrap();
	\WP_PowerSuite\Core\PluginLifecycle::activate();
}

/**
 * Plugin deactivation callback.
 *
 * Clears core plugin crons only; settings and module data are preserved.
 *
 * @since 1.0.0
 * @return void
 */
function wp_powersuite_deactivate(): void {
	if ( ! wp_powersuite_bootstrap_for_lifecycle() ) {
		wp_clear_scheduled_hook( 'wp_powersuite_license_recheck' );
		return;
	}

	\WP_PowerSuite\Core\PluginLifecycle::deactivate();
}

register_activation_hook( __FILE__, 'wp_powersuite_activate' );
register_deactivation_hook( __FILE__, 'wp_powersuite_deactivate' );

// Register uninstall hook
register_uninstall_hook( __FILE__, 'wpps_uninstall_plugin' );

require_once __DIR__ . '/includes/backup-restore-retire.php';
require_once WP_POWERSUITE_SRC_DIR . 'Core' . DIRECTORY_SEPARATOR . 'BootServiceProvider.php';
\WP_PowerSuite\Core\BootServiceProvider::registerEarly();

// Hook into plugins_loaded with priority 5 to ensure early initialization
// but after WordPress core is fully loaded
add_action( 'plugins_loaded', 'wp_powersuite_retire_backup_restore_module_run', 4 );
add_action( 'before_woocommerce_init', 'wp_powersuite_declare_woocommerce_compatibility' );
add_action( 'plugins_loaded', 'wp_powersuite_init', 5 );

/**
 * Declare WooCommerce HPOS and Checkout Blocks compatibility for the whole plugin.
 */
function wp_powersuite_declare_woocommerce_compatibility(): void {
	if ( ! class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
		return;
	}
	\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
		'custom_order_tables',
		WP_POWERSUITE_PLUGIN_FILE,
		true
	);
	\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
		'cart_checkout_blocks',
		WP_POWERSUITE_PLUGIN_FILE,
		true
	);
	\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
		'product_block_editor',
		WP_POWERSUITE_PLUGIN_FILE,
		true
	);
}

