<?php
/**
 * Plugin Kernel Class
 *
 * Main orchestrator for WP PowerSuite. This class manages the plugin lifecycle,
 * coordinates core components, and ensures proper initialization order.
 *
 * @package WP_PowerSuite\Core
 * @since 1.0.0
 */

namespace WP_PowerSuite\Core;

/**
 * Plugin Class
 *
 * Singleton instance that manages the plugin lifecycle and core components.
 * This class does NOT load modules - that is handled by {@see ModuleManager}.
 *
 * @since 1.0.0
 */
class Plugin {

	/**
	 * Plugin Instance
	 *
	 * Singleton instance of the Plugin class.
	 *
	 * @var Plugin|null
	 * @since 1.0.0
	 */
	private static ?Plugin $instance = null;

	/**
	 * Initialization Flag
	 *
	 * Tracks whether the plugin has been initialized.
	 *
	 * @var bool
	 * @since 1.0.0
	 */
	private bool $initialized = false;

	/**
	 * Core Components
	 *
	 * Array of core component instances.
	 *
	 * @var array<string, object>
	 * @since 1.0.0
	 */
	private array $components = [];

	/**
	 * Get Plugin Instance
	 *
	 * Returns the singleton instance of the Plugin class.
	 *
	 * @since 1.0.0
	 * @return Plugin Plugin instance.
	 */
	public static function getInstance(): Plugin {
		if ( self::$instance === null ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	/**
	 * Constructor
	 *
	 * Private constructor to enforce singleton pattern.
	 *
	 * @since 1.0.0
	 */
	private function __construct() {
		// Constructor is private to prevent direct instantiation
	}

	/**
	 * Prevent Cloning
	 *
	 * Prevents cloning of the singleton instance.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	private function __clone() {
		// Prevent cloning
	}

	/**
	 * Prevent Unserialization
	 *
	 * Prevents unserialization of the singleton instance.
	 *
	 * @since 1.0.0
	 * @return void
	 */
	public function __wakeup(): void {
		throw new \Exception( 'Cannot unserialize singleton' );
	}

	/**
	 * Initialize Plugin
	 *
	 * Initializes the plugin kernel and core components.
	 * This method should be called once during the 'plugins_loaded' hook.
	 *
	 * @since 1.0.0
	 * @return void
	 * @throws \Exception If initialization fails.
	 */
	public function init(): void {
		// Prevent multiple initializations
		if ( $this->initialized ) {
			return;
		}

		// Verify WordPress is loaded
		if ( ! function_exists( 'add_action' ) ) {
			throw new \Exception( 'WordPress functions not available. Plugin must be loaded within WordPress context.' );
		}

		$this->initialized = true;

		/**
		 * Fires after WP PowerSuite plugin has been initialized.
		 *
		 * @since 1.0.0
		 * @param Plugin $plugin Plugin instance.
		 */
		do_action( 'wp_powersuite_initialized', $this );
	}

	/**
	 * Get Component
	 *
	 * Retrieves a core component instance. Components are lazy-loaded
	 * when first accessed.
	 *
	 * @since 1.0.0
	 * @param string $component_name Component name (e.g., 'option_manager').
	 * @return object|null Component instance or null if not found.
	 */
	public function getComponent( string $component_name ): ?object {
		if ( isset( $this->components[ $component_name ] ) ) {
			return $this->components[ $component_name ];
		}

		return null;
	}

	/**
	 * Set Component
	 *
	 * Registers a core component instance.
	 *
	 * @since 1.0.0
	 * @param string $component_name Component name.
	 * @param object $component Component instance.
	 * @return void
	 */
	public function setComponent( string $component_name, object $component ): void {
		$this->components[ $component_name ] = $component;
	}

	/**
	 * Check if Plugin is Initialized
	 *
	 * Returns whether the plugin has been initialized.
	 *
	 * @since 1.0.0
	 * @return bool True if initialized, false otherwise.
	 */
	public function isInitialized(): bool {
		return $this->initialized;
	}

	/**
	 * Get Plugin Version
	 *
	 * Returns the current plugin version.
	 *
	 * @since 1.0.0
	 * @return string Plugin version.
	 */
	public function getVersion(): string {
		return defined( 'WP_POWERSUITE_VERSION' ) ? WP_POWERSUITE_VERSION : '1.0.0';
	}

	/**
	 * Get Plugin Directory Path
	 *
	 * Returns the absolute path to the plugin directory.
	 *
	 * @since 1.0.0
	 * @return string Plugin directory path.
	 */
	public function getPluginDir(): string {
		return defined( 'WP_POWERSUITE_PLUGIN_DIR' ) ? WP_POWERSUITE_PLUGIN_DIR : '';
	}

	/**
	 * Get Plugin Directory URL
	 *
	 * Returns the absolute URL to the plugin directory.
	 *
	 * @since 1.0.0
	 * @return string Plugin directory URL.
	 */
	public function getPluginUrl(): string {
		return defined( 'WP_POWERSUITE_PLUGIN_URL' ) ? WP_POWERSUITE_PLUGIN_URL : '';
	}
}

