<?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\ConflictDetector;
use WP_PowerSuite\Core\Http\AjaxRouter;
use WP_PowerSuite\Core\Http\Concerns\ParsesModuleAjaxInput;
use WP_PowerSuite\Core\ModuleRegistry;
use WP_PowerSuite\Core\OptionStore;

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();

		$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',
				]
			);
		}

		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' ),
				]
			);
		}

		if ( $enable ) {
			$dependencies = isset( $module_metadata['dependencies'] ) && is_array( $module_metadata['dependencies'] )
				? array_values( array_filter( array_map( 'sanitize_key', $module_metadata['dependencies'] ) ) )
				: [];
			$enabled_list           = $option_store->getEnabledModules();
			$missing_dependencies   = array_values( array_diff( $dependencies, $enabled_list ) );
			if ( $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,
					]
				);
			}

			$blocking = ConflictDetector::getInstance()->getBlockingConflictsForEnable( $module_id, $enabled_list );
			if ( $blocking !== [] ) {
				$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,
					]
				);
			}
		}

		$success = $enable
			? $option_store->enableModule( $module_id )
			: $option_store->disableModule( $module_id );

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

		// Persist succeeded — keep the toggle successful even if a listener fatals.
		try {
			do_action( 'wp_powersuite_module_toggled', $module_id, $enable, $module_metadata );

			if ( $module_id === 'link-shortener' ) {
				set_transient( 'wpps_link_shortener_flush_rewrite', 1, 60 );
			}

			if ( $module_id === 'obfuscate-author-slugs' ) {
				set_transient( 'wpps_author_slugs_flush_rewrite', 1, MINUTE_IN_SECONDS );
				if ( ! $enable ) {
					delete_transient( 'wpps_author_slugs_rewrite_flushed' );
				}
			}

			if ( $module_id === 'disable-author-archives' ) {
				set_transient( 'wpps_disable_author_archives_flush_rewrite', 1, MINUTE_IN_SECONDS );
			}

			if ( $module_id === 'cloudflare-turnstile' && ! $enable ) {
				delete_transient( 'wpps_turnstile_cf_probe' );
			}
		} catch ( \Throwable $e ) {
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
				error_log(
					sprintf(
						'WP PowerSuite: module toggle side effect failed for "%s": %s',
						$module_id,
						$e->getMessage()
					)
				);
			}
		}

		$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' ),
			]
		);
	}
}
