<?php
/**
 * Plugin activation: requirements check and safe auto-deactivation.
 *
 * @package EmberPrice
 */

namespace EmberPrice\Core;

defined( 'ABSPATH' ) || exit;

/**
 * Runs on plugin activation. Verifies PHP/WordPress/WooCommerce requirements
 * and deactivates the plugin with an admin notice instead of fataling.
 */
final class Activator {

	const MIN_PHP_VERSION = '8.2';
	const MIN_WP_VERSION  = '6.4';
	const MIN_WC_VERSION  = '8.0';

	const NOTICE_TRANSIENT     = 'embp_activation_requirements_notice';
	const DEACTIVATE_TRANSIENT = 'embp_activation_requirements_deactivate';

	/**
	 * Activation hook callback.
	 *
	 * WordPress re-adds this plugin to the `active_plugins` option right
	 * after this hook runs (see `activate_plugin()` in wp-admin/includes/
	 * plugin.php), so calling `deactivate_plugins()` here would be silently
	 * undone. The actual deactivation is deferred to `admin_init` on the
	 * next request via {@see self::maybe_self_deactivate()}.
	 */
	public static function activate(): void {
		$missing = self::get_missing_requirements();

		if ( ! empty( $missing ) ) {
			set_transient( self::NOTICE_TRANSIENT, $missing, MINUTE_IN_SECONDS );
			set_transient( self::DEACTIVATE_TRANSIENT, true, MINUTE_IN_SECONDS );
			return;
		}

		Migrations::maybe_upgrade();
	}

	/**
	 * Deactivates the plugin if a prior activation attempt found unmet
	 * requirements. Hooked to `admin_init`.
	 */
	public static function maybe_self_deactivate(): void {
		if ( ! get_transient( self::DEACTIVATE_TRANSIENT ) ) {
			return;
		}

		delete_transient( self::DEACTIVATE_TRANSIENT );
		deactivate_plugins( plugin_basename( EMBP_PLUGIN_FILE ) );

		if ( isset( $_GET['activate'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			unset( $_GET['activate'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		}

		add_action( 'admin_notices', array( __CLASS__, 'render_activation_notice' ) );
	}

	/**
	 * Returns human-readable messages for every unmet requirement.
	 *
	 * @return string[]
	 */
	public static function get_missing_requirements(): array {
		$missing = array();

		if ( version_compare( PHP_VERSION, self::MIN_PHP_VERSION, '<' ) ) {
			$missing[] = sprintf(
				/* translators: 1: required PHP version, 2: current PHP version */
				__( 'EmberPrice requires PHP %1$s or higher (current: %2$s).', 'emberprice' ),
				self::MIN_PHP_VERSION,
				PHP_VERSION
			);
		}

		if ( version_compare( get_bloginfo( 'version' ), self::MIN_WP_VERSION, '<' ) ) {
			$missing[] = sprintf(
				/* translators: 1: required WordPress version, 2: current WordPress version */
				__( 'EmberPrice requires WordPress %1$s or higher (current: %2$s).', 'emberprice' ),
				self::MIN_WP_VERSION,
				get_bloginfo( 'version' )
			);
		}

		if ( ! self::is_woocommerce_compatible() ) {
			$missing[] = sprintf(
				/* translators: %s: required WooCommerce version */
				__( 'EmberPrice requires WooCommerce %s or higher, active.', 'emberprice' ),
				self::MIN_WC_VERSION
			);
		}

		return $missing;
	}

	/**
	 * Whether an active, sufficiently recent WooCommerce is present.
	 */
	private static function is_woocommerce_compatible(): bool {
		if ( ! defined( 'WC_VERSION' ) ) {
			return false;
		}

		return version_compare( WC_VERSION, self::MIN_WC_VERSION, '>=' );
	}

	/**
	 * Renders the requirements notice stored during {@see self::activate()}.
	 */
	public static function render_activation_notice(): void {
		$missing = get_transient( self::NOTICE_TRANSIENT );

		if ( empty( $missing ) ) {
			return;
		}

		delete_transient( self::NOTICE_TRANSIENT );
		self::render_requirements_notice( $missing );
	}

	/**
	 * Renders a requirements notice for the given list of missing requirements.
	 *
	 * @param string[] $missing Human-readable requirement messages.
	 */
	public static function render_requirements_notice( array $missing ): void {
		if ( empty( $missing ) ) {
			return;
		}

		echo '<div class="notice notice-error"><p><strong>';
		esc_html_e( 'EmberPrice has been deactivated:', 'emberprice' );
		echo '</strong></p><ul>';

		foreach ( $missing as $message ) {
			echo '<li>' . esc_html( $message ) . '</li>';
		}

		echo '</ul></div>';
	}
}
