<?php
/**
 * Firevert System Check Class
 *
 * This class checks system requirements for the Firevert plugin,
 * including PHP version, required plugins, and PHP extensions.
 *
 * @package Firevert
 * @subpackage Core
 * @since 1.0.0
 */

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

/**
 * Class Firevert_System
 *
 * Performs environment checks (PHP version, required plugins, PHP extensions).
 *
 * @since 1.0.0
 */
class Firevert_System_Check {

    /**
     * Plugin active status.
     *
     * @since 1.0.0
     */
    public const TEST_PLUGIN_ACTIVE = 1;

    /**
     * Plugin installed but inactive status.
     *
     * @since 1.0.0
     */
    public const TEST_PLUGIN_INSTALLED = 2;

    /**
     * Plugin not installed status.
     *
     * @since 1.0.0
     */
    public const TEST_PLUGIN_NOT_INSTALLED = 0;

    /**
     * Result of system checks.
     *
     * @var bool
     */
    private bool $result = true;

    /**
     * Plugin configuration.
     *
     * @var array<string,mixed>
     */
    private array $plugin_config;

    /**
     * Plugin basename.
     *
     * @var string
     */
    private string $basename = '';

    /**
     * Constructor.
     *
     * @param array<string,mixed> $plugin_config Plugin configuration array.
     */
    public function __construct( array $plugin_config ) {
        $this->plugin_config = $plugin_config;
    }

    /**
     * Run all system requirement checks.
     *
     * @return bool True if all checks passed, false otherwise.
     */
    public function evaluate_system(): bool {
        $this->basename = basename( __DIR__ );

        $this->test_php();
        $this->test_required_plugins();
        $this->test_php_extensions();

        return $this->result;
    }

    /**
     * Check PHP version.
     *
     * @return void
     */
    private function test_php(): void {
        if ( PHP_VERSION_ID < $this->get( 'min_php_int' ) ) {
            $this->fail_with_notice(
                sprintf(
                    /* translators: %s: minimum required PHP version. */
                    __( 'PHP version is older than %s. This plugin requires a newer PHP version.', 'firevert' ),
                    $this->get( 'min_php' )
                )
            );
        }
    }

    /**
     * Check if required plugins are active.
     *
     * @return void
     */
    private function test_required_plugins(): void {
        $required_plugins = $this->get( 'required_plugins' );

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

        include_once ABSPATH . 'wp-admin/includes/plugin.php';

        foreach ( $required_plugins as $slug ) {
            $status = $this->test_plugin( $slug );

            if ( self::TEST_PLUGIN_INSTALLED === $status ) {
                $this->fail_with_notice(
                    sprintf(
                        /* translators: %s: plugin slug. */
                        __( 'Required plugin "%s" is installed but not activated.', 'firevert' ),
                        $slug
                    )
                );
            }

            if ( self::TEST_PLUGIN_NOT_INSTALLED === $status ) {
                $this->fail_with_notice(
                    sprintf(
                        /* translators: %s: plugin slug. */
                        __( 'Required plugin "%s" is not installed.', 'firevert' ),
                        $slug
                    )
                );
            }
        }
    }

    /**
     * Check if required PHP extensions are loaded.
     *
     * @return void
     */
    private function test_php_extensions(): void {
        $required_extensions = $this->get( 'required_php_extensions' );

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

        $missing = array();

        foreach ( $required_extensions as $ext ) {
            if ( ! extension_loaded( $ext ) ) {
                $missing[] = $ext;
            }
        }

        if ( ! empty( $missing ) ) {
            $this->fail_with_notice(
                sprintf(
                    /* translators: %s: list of missing PHP extensions. */
                    __( 'Required PHP extensions missing: %s', 'firevert' ),
                    implode( ', ', $missing )
                )
            );
        }
    }

    /**
     * Add admin notice and set failure flag.
     *
     * @param string $message Message to display.
     * @return void
     */
    private function fail_with_notice( string $message ): void {
        $this->result = false;

        add_action(
            'admin_notices',
            function () use ( $message ) {
                printf(
                    '<div class="notice notice-error error"><p><strong style="color:red;">%s: </strong>%s</p></div>',
                    esc_html( $this->get( 'name' ) ),
                    esc_html( $message )
                );
            }
        );
    }

    /**
     * Check plugin activation status.
     *
     * @param string $slug Plugin slug.
     * @return int One of the TEST_PLUGIN_* constants.
     */
    private function test_plugin( string $slug ): int {
        $path = $slug . '/' . $slug . '.php';

        if ( is_plugin_active( $path ) ) {
            return self::TEST_PLUGIN_ACTIVE;
        }

        if ( is_plugin_inactive( $path ) ) {
            return self::TEST_PLUGIN_INSTALLED;
        }

        return self::TEST_PLUGIN_NOT_INSTALLED;
    }

    /**
     * Get plugin config value.
     *
     * @param string $key Config key.
     * @return mixed|null Config value or null.
     */
    private function get( string $key ) {
        return $this->plugin_config[ $key ] ?? null;
    }
}
