<?php
/**
 * Disable Gutenberg Extension for Elementor Conditions
 *
 * This extension disables Gutenberg for specific post types.
 * This extension is designed to work with Elementor and follows its extension structure.
 *
 * @since 1.0.0
 *
 * @package    captain-widgets-kit
 * @subpackage captain-widgets-kit/includes
 */

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

// Admin page context is validated before using query parameters.
// phpcs:disable WordPress.Security.NonceVerification.Recommended

/**
 * Class Captwiki_Disable_Gutenberg
 */
if ( ! class_exists( 'Captwiki_Disable_Gutenberg' ) ) {

	/**
	 * Class Captwiki_Disable_Gutenberg
	 *
	 * @since 1.1.0
	 */
	class Captwiki_Disable_Gutenberg {

		/**
		 * Post type options
		 *
		 * @since 1.0.0
		 * @var array
		 */
		public $post_types = array();

		/**
		 * Constructor.
		 *
		 * @since 1.0.0
		 * @return void
		 */
		public function __construct() {

			$this->post_types = get_post_types( array( 'public' => true ) );
			unset( $this->post_types['attachment'] );

			add_action( 'admin_init', array( $this, 'captwiki_disable_gutenberg' ) );
			add_action( 'admin_print_styles', array( $this, 'captwiki_safari_fix' ) );

			add_action( 'init', array( $this, 'captwiki_disable_gutenberg_core' ), 100 );
			add_action( 'wp_enqueue_scripts', array( $this, 'captwiki_disable_gutenberg_frontend_style' ), 100 );
		}

		/**
		 * Disable Gutenberg for specific post types.
		 *
		 * @since 1.0.0
		 * @return void
		 */
		public function captwiki_disable_gutenberg() {

			if ( ! is_admin() ) {
				return;
			}

			global $pagenow, $typenow;

			// Get post type based on current page context.
			$post_type = $this->get_current_post_type( $pagenow, $typenow );

			if ( ! $post_type ) {
				return;
			}

			$gutenberg    = function_exists( 'gutenberg_register_scripts_and_styles' );
			$block_editor = has_action( 'enqueue_block_assets' );

			if ( ! $gutenberg && false === $block_editor ) {
				return;
			}

			add_filter( 'use_block_editor_for_post_type', '__return_false', 100 );

			if ( function_exists( 'gutenberg_register_scripts_and_styles' ) ) {
				add_filter( 'gutenberg_can_edit_post_type', '__return_false', 100 );
				$this->remove_gutenberg_hooks();
			}
		}

		/**
		 * Remove Gutenberg hooks.
		 *
		 * @since 1.0.0
		 * @return void
		 */
		public function remove_gutenberg_hooks() {
			$actions = array(
				array( 'admin_menu', 'gutenberg_menu' ),
				array( 'admin_init', 'gutenberg_redirect_demo' ),
				array( 'wp_enqueue_scripts', 'gutenberg_register_scripts_and_styles' ),
				array( 'admin_enqueue_scripts', 'gutenberg_register_scripts_and_styles' ),
				array( 'admin_notices', 'gutenberg_wordpress_version_notice' ),
				array( 'rest_api_init', 'gutenberg_register_rest_widget_updater_routes' ),
				array( 'admin_print_styles', 'gutenberg_block_editor_admin_print_styles' ),
				array( 'admin_print_scripts', 'gutenberg_block_editor_admin_print_scripts' ),
				array( 'admin_print_footer_scripts', 'gutenberg_block_editor_admin_print_footer_scripts' ),
				array( 'admin_footer', 'gutenberg_block_editor_admin_footer' ),
				array( 'admin_enqueue_scripts', 'gutenberg_widgets_init' ),
				array( 'admin_notices', 'gutenberg_build_files_notice' ),
				array( 'rest_api_init', 'gutenberg_register_rest_routes' ),
				array( 'rest_api_init', 'gutenberg_add_taxonomy_visibility_field' ),
				array( 'do_meta_boxes', 'gutenberg_meta_box_save' ),
				array( 'submitpost_box', 'gutenberg_intercept_meta_box_render' ),
				array( 'submitpage_box', 'gutenberg_intercept_meta_box_render' ),
				array( 'edit_page_form', 'gutenberg_intercept_meta_box_render' ),
				array( 'edit_form_advanced', 'gutenberg_intercept_meta_box_render' ),
			);

			$filters = array(
				array( 'load_script_translation_file', 'gutenberg_override_translation_file' ),
				array( 'block_editor_settings', 'gutenberg_extend_block_editor_styles' ),
				array( 'default_content', 'gutenberg_default_demo_content' ),
				array( 'default_title', 'gutenberg_default_demo_title' ),
				array( 'block_editor_settings', 'gutenberg_legacy_widget_settings' ),
				array( 'rest_request_after_callbacks', 'gutenberg_filter_oembed_result' ),
				array( 'wp_refresh_nonces', 'gutenberg_add_rest_nonce_to_heartbeat_response_headers' ),
				array( 'get_edit_post_link', 'gutenberg_revisions_link_to_editor' ),
				array( 'wp_prepare_revision_for_js', 'gutenberg_revisions_restore' ),
				array( 'redirect_post_location', 'gutenberg_meta_box_save_redirect' ),
				array( 'filter_gutenberg_meta_boxes', 'gutenberg_filter_meta_boxes' ),
				array( 'body_class', 'gutenberg_add_responsive_body_class' ),
				array( 'admin_url', 'gutenberg_modify_add_new_button_url' ),
				array( 'register_post_type_args', 'gutenberg_filter_post_type_labels' ),
			);

			foreach ( $actions as [$hook, $func] ) {
				remove_action( $hook, $func );
			}

			foreach ( $filters as [$hook, $func] ) {
				remove_filter( $hook, $func );
			}
		}

		/**
		 * Disable Gutenberg core functionality completely.
		 *
		 * @since 1.0.0
		 * @return void
		 */
		public function captwiki_disable_gutenberg_core() {

			// Remove Gutenberg from WordPress core.
			remove_action( 'wp_enqueue_scripts', 'wp_common_block_scripts_and_styles' );
			remove_action( 'admin_enqueue_scripts', 'wp_common_block_scripts_and_styles' );

			// Disable block editor.
			add_filter( 'use_block_editor_for_post', '__return_false' );
			add_filter( 'use_block_editor_for_post_type', '__return_false' );

			// Remove Gutenberg menu.
			remove_action( 'admin_menu', 'gutenberg_menu' );

			// Disable Gutenberg REST API endpoints.
			add_filter(
				'rest_authentication_errors',
				function ( $result ) {
					if ( ! empty( $result ) ) {
						return $result;
					}
					if ( ! is_user_logged_in() ) {
						return new WP_Error( 'rest_not_logged_in', 'You are not currently logged in.', array( 'status' => 401 ) );
					}
					return $result;
				}
			);

			// Remove Gutenberg styles and scripts.
			add_action(
				'wp_enqueue_scripts',
				function () {
					wp_dequeue_style( 'wp-block-library' );
					wp_dequeue_style( 'wp-block-library-theme' );
					wp_dequeue_style( 'wp-format-library' );
					wp_dequeue_script( 'wp-block-library' );
					wp_dequeue_script( 'wp-format-library' );
				},
				100
			);

			add_action(
				'admin_enqueue_scripts',
				function () {
					wp_dequeue_style( 'wp-block-library' );
					wp_dequeue_style( 'wp-block-library-theme' );
					wp_dequeue_style( 'wp-format-library' );
					wp_dequeue_script( 'wp-block-library' );
					wp_dequeue_script( 'wp-format-library' );
				},
				100
			);
		}

		/**
		 * Disable Gutenberg block styles on the frontend for selected post types.
		 *
		 * @since 1.0.0
		 * @return void
		 */
		public function captwiki_disable_gutenberg_frontend_style() {
			if ( ! is_singular() ) {
				return;
			}

			global $post;

			if ( ! isset( $post->post_type ) ) {
				return;
			}

			// Remove Gutenberg styles.
			$block_styles_to_keep = array();

			global $wp_styles;
			if ( isset( $wp_styles->queue ) && is_array( $wp_styles->queue ) ) {
				foreach ( $wp_styles->queue as $handle ) {
					if ( strpos( $handle, 'wp-block' ) === 0 && ! in_array( $handle, $block_styles_to_keep, true ) ) {
						wp_dequeue_style( $handle );
					}
				}
			}

			wp_dequeue_style( 'core-block-supports' );
			wp_dequeue_style( 'global-styles' );
			wp_dequeue_style( 'classic-theme-styles' );
			wp_deregister_style( 'wp-block-library' );
		}

		/**
		 * Safari 18 fix for classic editor.
		 *
		 * @since 1.0.0
		 * @return void
		 */
		public function captwiki_safari_fix() {
			global $current_screen;

			if ( ! isset( $current_screen->base ) || 'post' !== $current_screen->base ) {
				return;
			}

			$clear = is_rtl() ? 'right' : 'left';
			$css   = '_::-webkit-full-page-media, _:future, :root #post-body #postbox-container-2 { clear: ' . esc_attr( $clear ) . '; }';

			wp_register_style( 'captwiki-safari-fix', false, array(), CAPTWIKI_VERSION );
			wp_enqueue_style( 'captwiki-safari-fix' );
			wp_add_inline_style( 'captwiki-safari-fix', $css );
		}

		/**
		 * Get current post type based on page context.
		 *
		 * @since 1.0.0
		 * @param string $pagenow Current page context.
		 * @param string $typenow Current post type.
		 * @return string|null Current post type or null if not found.
		 */
		public function get_current_post_type( $pagenow, $typenow ) {

			switch ( $pagenow ) {
				case 'edit.php':
					return $typenow;
				case 'post.php':
					return isset( $_GET['post'] ) ? get_post_type( sanitize_text_field( wp_unslash( $_GET['post'] ) ) ) : 'post';
				case 'post-new.php':
					return isset( $_GET['post_type'] ) ? sanitize_text_field( wp_unslash( $_GET['post_type'] ) ) : 'post';
				default:
					return null;
			}
		}
	}

}

new Captwiki_Disable_Gutenberg();
