<?php
/**
 * Admin AJAX handlers for enabling/disabling modules.
 *
 * @package WP_PowerSuite\Core\Http\Controllers
 * @since 1.0.0
 */

namespace WP_PowerSuite\Core\Http\Controllers;

use WP_PowerSuite\Core\ApplicationPasswordConflictPolicy;
use WP_PowerSuite\Core\Http\AjaxRouter;
use WP_PowerSuite\Core\Http\Concerns\ParsesModuleAjaxInput;
use WP_PowerSuite\Core\ModuleActivationService;
use WP_PowerSuite\Core\ModuleRegistry;
use WP_PowerSuite\Core\OptionStore;
use WP_PowerSuite\Core\TemporarySessionGuard;

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

final class ModuleManagementController {

	use ParsesModuleAjaxInput;

	private static ?self $instance = null;

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

	public static function register(): void {
		$controller = self::getInstance();
		AjaxRouter::registerAdminAction( 'wp_powersuite_toggle_module', [ $controller, 'toggleModule' ] );
	}

	public function toggleModule(): void {
		$module_id = $this->getPostedModuleId();
		if ( $module_id === '' ) {
			wp_send_json_error(
				[
					'message' => __( 'Invalid module ID provided.', 'wp-powersuite' ),
					'code'    => 'invalid_module_id',
				]
			);
		}

		$enable = $this->getPostedEnableFlag();

		if ( TemporarySessionGuard::isActive() && TemporarySessionGuard::blocksModule( $module_id ) ) {
			wp_send_json_error( TemporarySessionGuard::deniedPayload() );
		}

		$option_store    = OptionStore::getInstance();
		$module_registry = ModuleRegistry::getInstance();
		$module_registry->init();
		$module_metadata = $module_registry->getModuleMetadata( $module_id );

		if ( empty( $module_metadata ) ) {
			wp_send_json_error(
				[
					'message' => __( 'Module not found in registry.', 'wp-powersuite' ),
					'code'    => 'module_not_found',
				]
			);
		}

		$module_dir = isset( $module_metadata['_directory'] ) ? (string) $module_metadata['_directory'] : '';
		if ( $enable && ( $module_dir === '' || ! is_dir( $module_dir ) ) ) {
			wp_send_json_error(
				[
					'message' => __( 'This module is included with WP PowerSuite Pro. Install the Pro add-on from wppowersuite.com.', 'wp-powersuite' ),
					'code'    => 'pro_addon_required',
					'product_url' => defined( 'WP_POWERSUITE_PRODUCT_URL' ) ? WP_POWERSUITE_PRODUCT_URL : 'https://wppowersuite.com/',
				]
			);
		}

		if ( $enable && ! empty( $module_metadata['is_pro'] ) && ! wp_powersuite_is_license_valid() ) {
			wp_send_json_error(
				[
					'message'      => __( 'A valid license is required to enable premium modules. Open License in the menu or header to activate.', 'wp-powersuite' ),
					'code'         => 'license_required',
					'license_page' => admin_url( 'admin.php?page=powersuite-license' ),
				]
			);
		}

		$activation = ModuleActivationService::getInstance();

		if ( $enable ) {
			$enabled_list = $option_store->getEnabledModules();
			$validation   = $activation->validateEnable( $module_id, $enabled_list, $module_metadata );

			if ( ! $validation['allowed'] && $validation['code'] === 'missing_dependencies' ) {
				$missing_dependencies = $validation['missing_dependencies'];
				$names                = [];
				foreach ( $missing_dependencies as $dependency_id ) {
					$dependency_meta = $module_registry->getModuleMetadata( $dependency_id );
					$names[]         = $dependency_meta['name'] ?? $dependency_id;
				}
				wp_send_json_error(
					[
						'message'      => sprintf(
							/* translators: 1: module being enabled, 2: comma-separated dependency module names */
							__( 'Cannot enable "%1$s" until required module(s) are enabled: %2$s.', 'wp-powersuite' ),
							$module_metadata['name'] ?? $module_id,
							implode( ', ', $names )
						),
						'code'         => 'missing_dependencies',
						'dependencies' => $missing_dependencies,
					]
				);
			}

			if ( ! $validation['allowed'] && $validation['code'] === 'module_conflict' ) {
				$blocking = $validation['conflicts'];
				$names    = [];
				foreach ( $blocking as $blocking_id ) {
					$blocking_meta = $module_registry->getModuleMetadata( $blocking_id );
					$names[]       = $blocking_meta['name'] ?? $blocking_id;
				}

				if (
					$module_id === ApplicationPasswordConflictPolicy::MODULE_DISABLE_APP_PASSWORDS
					&& in_array( ApplicationPasswordConflictPolicy::MODULE_TWO_FACTOR, $blocking, true )
				) {
					$message = ApplicationPasswordConflictPolicy::getEnableConflictMessage( $module_id, $blocking );
				} else {
					$message = sprintf(
						/* translators: 1: module being enabled, 2: comma-separated list of conflicting module names */
						__( 'Cannot enable "%1$s": it conflicts with %2$s. Disable the conflicting module(s) first.', 'wp-powersuite' ),
						$module_metadata['name'] ?? $module_id,
						implode( ', ', $names )
					);
				}

				wp_send_json_error(
					[
						'message'   => $message,
						'code'      => 'module_conflict',
						'conflicts' => $blocking,
					]
				);
			}
		}

		// Persistence + post-toggle side effects are shared with the WP-CLI
		// integration via ModuleActivationService so behavior cannot drift.
		$success = $activation->applyToggle( $module_id, $enable, $module_metadata );

		if ( ! $success ) {
			wp_send_json_error(
				[
					'message' => __( 'Failed to update module status. Please try again.', 'wp-powersuite' ),
					'code'    => 'update_failed',
				]
			);
		}

		$enabled_modules = $option_store->getEnabledModules();
		$favorites       = $option_store->getFavorites();

		AjaxRouter::sendJsonSuccess(
			[
				'module_id'    => $module_id,
				'enabled'      => $enable,
				'module_state' => [
					'id'             => $module_id,
					'enabled'        => in_array( $module_id, $enabled_modules, true ),
					'favorite'       => in_array( $module_id, $favorites, true ),
					'enabled_list'   => $enabled_modules,
					'favorites_list' => $favorites,
				],
				'message'      => $enable
					? __( 'Module enabled successfully.', 'wp-powersuite' )
					: __( 'Module disabled successfully.', 'wp-powersuite' ),
			]
		);
	}
}
