<?php
/**
 * Code Snippet Safe Mode
 *
 * When ?wpps-cs-safe-mode=1 is present and user can manage_options,
 * prevents all snippet execution via wpps_do_auto_insert filter.
 * Keeps the param in URLs so admin can navigate with snippets disabled.
 *
 * @package CodeSnippet
 * @since 1.0.0
 */

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

add_action( 'init', 'wpps_cs_maybe_enable_safe_mode', 999 );
add_filter( 'wpps_do_auto_insert', 'wpps_cs_maybe_prevent_execution' );

/**
 * Enable safe mode logic when query param is present.
 *
 * @return void
 */
function wpps_cs_maybe_enable_safe_mode(): void {
	if ( ! isset( $_GET['wpps-cs-safe-mode'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		return;
	}

	if ( ! is_user_logged_in() || ! current_user_can( 'manage_options' ) ) {
		return;
	}

	add_filter( 'home_url', 'wpps_cs_keep_safe_mode' );
	add_filter( 'admin_url', 'wpps_cs_keep_safe_mode' );
	add_filter( 'site_url', 'wpps_cs_keep_safe_mode_login', 10, 3 );
	add_action( 'admin_footer', 'wpps_cs_keep_safe_mode_admin_menu' );
	add_action( 'admin_notices', 'wpps_cs_safe_mode_notice' );
}

/**
 * Keep safe mode param in home/admin URLs.
 *
 * @param string $url URL.
 * @return string
 */
function wpps_cs_keep_safe_mode( string $url ): string {
	return add_query_arg( 'wpps-cs-safe-mode', '1', $url );
}

/**
 * Add safe mode param to admin menu links via JS.
 *
 * @return void
 */
function wpps_cs_keep_safe_mode_admin_menu(): void {
	?>
	<script type="text/javascript">
		document.querySelectorAll( 'a:not(.wpps-cs-safe-mode-exit)' ).forEach( function( el ) {
			if ( el.href && el.href.indexOf( 'admin.php' ) !== -1 ) {
				var url = new URL( el.href );
				url.searchParams.set( 'wpps-cs-safe-mode', '1' );
				el.href = url.toString();
			}
		} );
	</script>
	<?php
}

/**
 * Safe mode admin notice.
 *
 * @return void
 */
function wpps_cs_safe_mode_notice(): void {
	?>
	<div class="notice notice-warning">
		<p><?php esc_html_e( 'Code Snippets are in Safe Mode for your admin session. Snippets still run for other visitors. Disable problematic snippets, then exit safe mode below.', 'wp-powersuite' ); ?></p>
		<p>
			<a class="button button-secondary wpps-cs-safe-mode-exit" href="<?php echo esc_url( remove_query_arg( 'wpps-cs-safe-mode' ) ); ?>" target="_blank"><?php esc_html_e( 'Exit Safe Mode', 'wp-powersuite' ); ?></a>
		</p>
	</div>
	<?php
}

/**
 * Prevent snippet execution when in safe mode.
 *
 * @param bool $execute Whether to execute snippets.
 * @return bool
 */
function wpps_cs_maybe_prevent_execution( bool $execute ): bool {
	if ( ! $execute ) {
		return false;
	}

	if ( defined( 'WPPS_CS_DISABLE' ) && WPPS_CS_DISABLE ) {
		return false;
	}

	if ( get_option( 'wpps_cs_global_safe_mode', false ) || \CodeSnippet\Module::getSetting( 'global_safe_mode', false ) ) {
		return false;
	}

	if ( ! isset( $_GET['wpps-cs-safe-mode'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
		return $execute;
	}

	if ( is_user_logged_in() && current_user_can( 'manage_options' ) ) {
		return false;
	}

	// Early PHP locations run at plugins_loaded — before init auth. Validate the logged-in cookie directly.
	if ( ! did_action( 'init' ) && function_exists( 'wp_validate_auth_cookie' ) ) {
		$user_id = wp_validate_auth_cookie( '', 'logged_in' );
		if ( $user_id && user_can( $user_id, 'manage_options' ) ) {
			return false;
		}
	}

	return $execute;
}

/**
 * Keep safe mode on login URL for site_url( ..., 'login_post' ).
 *
 * @param string      $url    URL.
 * @param string      $path   Path.
 * @param string|null $scheme Scheme (WordPress may pass null).
 * @return string
 */
function wpps_cs_keep_safe_mode_login( string $url, string $path, ?string $scheme ): string {
	if ( 'login_post' !== $scheme ) {
		return $url;
	}
	return add_query_arg( 'wpps-cs-safe-mode', '1', $url );
}
