<?php
/**
 * System requirements compatibility checker.
 *
 * @package PDFDraft
 */

namespace PDFDraft;

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

/**
 * Checks PHP and WordPress version requirements before plugin activation.
 */
final class SystemRequirementsChecker {

	/**
	 * Admin notices to display.
	 *
	 * @var array
	 */
	private array $notices = array();

	/**
	 * Requirements configuration.
	 *
	 * @var array
	 */
	private array $config = array();

	/**
	 * Configuration manager instance.
	 *
	 * @var Config
	 */
	private Config $configManager;

	/**
	 * Constructor.
	 *
	 * @param array|null  $config        Optional requirements configuration.
	 * @param Config|null $configManager Optional configuration manager instance.
	 */
	public function __construct( ?array $config = null, ?Config $configManager = null ) {
		$this->configManager = $configManager ?? new Config();
		$this->config        = $config ?? $this->loadConfig();
	}

	/**
	 * Load requirements configuration from file or defaults.
	 *
	 * @return array
	 */
	private function loadConfig(): array {
		$config = $this->configManager->all( 'requirements' );

		if ( empty( $config ) ) {
			return array(
				'min_php_version'     => PDFDRAFT_MIN_PHP_VERSION,
				'min_wp_version'      => PDFDRAFT_MIN_WP_VERSION,
				'notice_types'        => array(
					'error'   => 'error',
					'warning' => 'warning',
				),
				'plugin_name'         => 'PDFDraft',
				'deactivate_on_error' => true,
				'show_notices'        => true,
				'checks'              => array(
					'php_version'       => true,
					'wordpress_version' => true,
				),
			);
		}

		return $config;
	}

	/**
	 * Check system compatibility and handle failures.
	 *
	 * @return bool
	 */
	public function checkCompatibility(): bool {
		$this->runAllChecks();

		if ( ! empty( $this->notices ) ) {
			if ( $this->config['show_notices'] ?? true ) {
				$this->displayNotices();
			}
			if ( $this->config['deactivate_on_error'] ?? true ) {
				$this->maybeDeactivatePlugin();
			}
			return false;
		}

		return true;
	}

	/**
	 * Run all configured compatibility checks.
	 *
	 * @return void
	 */
	private function runAllChecks(): void {
		if ( $this->config['checks']['php_version'] ?? true ) {
			$this->checkPhpVersion();
		}
		if ( $this->config['checks']['wordpress_version'] ?? true ) {
			$this->checkWordPressVersion();
		}
		// Easy to add more checks here.
	}

	/**
	 * Check PHP version compatibility.
	 *
	 * @return void
	 */
	private function checkPhpVersion(): void {
		$min_version = $this->config['min_php_version'] ?? PDFDRAFT_MIN_PHP_VERSION;
		if ( ! version_compare( PHP_VERSION, $min_version, '>=' ) ) {
			$plugin_name = $this->config['plugin_name'] ?? 'PDFDraft';
			$this->addNotice(
				$this->config['notice_types']['error'] ?? 'error',
				sprintf(
					/* translators: %1$s: Plugin name, %2$s: Min PHP version, %3$s: Current PHP version */
					__( '%1$s requires PHP %2$s or higher. You are running PHP %3$s. Please upgrade PHP to continue.', 'pdfdraft' ),
					$plugin_name,
					$min_version,
					PHP_VERSION
				)
			);
		}
	}

	/**
	 * Check WordPress version compatibility.
	 *
	 * @return void
	 */
	private function checkWordPressVersion(): void {
		global $wp_version;

		$min_version = $this->config['min_wp_version'] ?? PDFDRAFT_MIN_WP_VERSION;
		if ( ! version_compare( $wp_version, $min_version, '>=' ) ) {
			$plugin_name = $this->config['plugin_name'] ?? 'PDFDraft';
			$this->addNotice(
				$this->config['notice_types']['error'] ?? 'error',
				sprintf(
					/* translators: %1$s: Plugin name, %2$s: Min WP version, %3$s: Current WP version */
					__( '%1$s requires WordPress %2$s or higher. You are running WordPress %3$s. Please update WordPress to continue.', 'pdfdraft' ),
					$plugin_name,
					$min_version,
					$wp_version
				)
			);
		}
	}

	/**
	 * Add an admin notice.
	 *
	 * @param string $type    Notice type (error or warning).
	 * @param string $message Notice message content.
	 * @return void
	 */
	private function addNotice( string $type, string $message ): void {
		$this->notices[] = array(
			'type'    => $type,
			'message' => $message,
		);
	}

	/**
	 * Register admin notice hooks.
	 *
	 * @return void
	 */
	private function displayNotices(): void {
		add_action( 'admin_notices', array( $this, 'renderNotices' ) );
		if ( is_multisite() ) {
			add_action( 'network_admin_notices', array( $this, 'renderNotices' ) );
		}
	}

	/**
	 * Render admin notices HTML.
	 *
	 * @return void
	 */
	public function renderNotices(): void {
		foreach ( $this->notices as $notice ) {
			printf(
				'<div class="notice notice-%s is-dismissible"><p><strong>%s:</strong> %s</p></div>',
				esc_attr( $notice['type'] ),
				esc_html__( 'Plugin Activation Error', 'pdfdraft' ),
				esc_html( $notice['message'] )
			);
		}
	}

	/**
	 * Conditionally schedule plugin deactivation.
	 *
	 * @return void
	 */
	private function maybeDeactivatePlugin(): void {
        // phpcs:disable WordPress.Security.NonceVerification.Recommended
		if ( isset( $_GET['activate'] ) ) {
			add_action( 'admin_init', array( $this, 'deactivatePlugin' ) );
		}
	}

	/**
	 * Deactivate the plugin and clear the activation flag.
	 *
	 * @return void
	 */
	public function deactivatePlugin(): void {
		deactivate_plugins( PDFDRAFT_PLUGIN_BASE );
		if ( isset( $_GET['activate'] ) ) {
			unset( $_GET['activate'] );
		}
        // phpcs:enable WordPress.Security.NonceVerification.Recommended
	}

	/**
	 * Get all collected notices.
	 *
	 * @return array
	 */
	public function getNotices(): array {
		return $this->notices;
	}

	/**
	 * Check if any error-level notices exist.
	 *
	 * @return bool
	 */
	public function hasErrors(): bool {
		$error_type = $this->config['notice_types']['error'] ?? 'error';
		return ! empty(
			array_filter(
				$this->notices,
				fn( $notice ) => $error_type === $notice['type']
			)
		);
	}
}
