<?php
/**
 * Admin AJAX bootstrap — lazy controller registration.
 *
 * @package WP_PowerSuite\Core
 * @since 1.0.0
 */

namespace WP_PowerSuite\Core;

use WP_PowerSuite\Core\Http\Controllers\CaptchaController;
use WP_PowerSuite\Core\Http\Controllers\ConfigController;
use WP_PowerSuite\Core\Http\Controllers\ModuleManagementController;
use WP_PowerSuite\Core\Http\Controllers\ModuleSettingsController;
use WP_PowerSuite\Core\Http\Controllers\ModuleToolsController;
use WP_PowerSuite\Core\Http\Controllers\ModuleUiController;
use WP_PowerSuite\Core\Http\Controllers\AdsTxtController;
use WP_PowerSuite\Core\Http\Controllers\RobotsTxtController;
use WP_PowerSuite\Core\Http\Controllers\WpConfigEditorController;
use WP_PowerSuite\Core\Http\AjaxRouter;
use WP_PowerSuite\Core\OptionStoreModuleSettingsRepository;

/**
 * Registers admin AJAX handlers via focused controllers.
 *
 * @since 1.0.0
 */
class Ajax {

	private static ?Ajax $instance = null;

	private string $nonce_action = 'wp_powersuite_ajax';

	private bool $router_registered = false;

	private bool $controllers_registered = false;

	public static function getInstance(): Ajax {
		if ( self::$instance === null ) {
			self::$instance = new self();
		}
		return self::$instance;
	}

	private function __construct() {
	}

	private function __clone() {
	}

	public function __wakeup(): void {
		throw new \Exception( 'Cannot unserialize singleton' );
	}

	/**
	 * Register the lazy controller bootstrap (cheap; safe on every request).
	 */
	public function registerRouter(): void {
		if ( $this->router_registered ) {
			return;
		}

		$this->router_registered = true;
		add_action( 'init', [ $this, 'maybeRegisterControllers' ], 0 );
	}

	/**
	 * Register controllers when in wp-admin or a PowerSuite AJAX request.
	 */
	public function maybeRegisterControllers(): void {
		if ( $this->controllers_registered ) {
			return;
		}

		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
			if ( ! function_exists( 'wp_powersuite_is_ajax_request' ) || ! wp_powersuite_is_ajax_request() ) {
				return;
			}
		} elseif ( ! is_admin() ) {
			return;
		}

		$this->registerControllers();
	}

	/**
	 * Register all admin AJAX controllers.
	 */
	public function registerControllers(): void {
		if ( $this->controllers_registered ) {
			return;
		}

		ModuleManagementController::register();
		ModuleSettingsController::register();
		ModuleUiController::register();
		ConfigController::register();
		if ( OptionStoreModuleSettingsRepository::isModuleEnabled( 'wp-config-editor' ) ) {
			WpConfigEditorController::register();
		}
		if ( OptionStoreModuleSettingsRepository::isModuleEnabled( 'robots-txt-manager' ) ) {
			RobotsTxtController::register();
		}
		if ( OptionStoreModuleSettingsRepository::isModuleEnabled( 'ads-txt-manager' ) ) {
			AdsTxtController::register();
		}
		ModuleToolsController::register();
		CaptchaController::register();
		UninstallHandler::registerAjaxHandlers();

		$this->controllers_registered = true;
	}

	/**
	 * @deprecated Use {@see self::registerRouter()} and {@see self::registerControllers()}.
	 */
	public function init(): void {
		$this->registerRouter();
		$this->maybeRegisterControllers();
	}

	public function isInitialized(): bool {
		return $this->controllers_registered;
	}

	public function getNonceAction(): string {
		return $this->nonce_action;
	}

	/**
	 * @deprecated Use AjaxRouter::NONCE_ACTION.
	 */
	public static function getRouterNonceAction(): string {
		return AjaxRouter::NONCE_ACTION;
	}
}
