<?php
/**
 * Elementor Editor Settings Integration.
 *
 * Adds custom React-based settings to the Elementor editor page settings panel.
 *
 * @package     Astra
 * @link        https://wpastra.com/
 * @since       4.11.3
 */

defined( 'ABSPATH' ) || exit; // Exit if accessed directly.

/**
 * Elementor Editor Settings integration class.
 *
 * @since 4.11.3
 */
if ( ! class_exists( 'Astra_Elementor_Editor_Settings' ) ) {
	/**
	 * Elementor Editor Settings integration class.
	 *
	 * @since 4.11.3
	 */
	class Astra_Elementor_Editor_Settings {
		/**
		 * Class instance.
		 *
		 * @var self|null
		 * @since 4.11.3
		 */
		private static $instance = null;

		/**
		 * Get instance.
		 *
		 * @since 4.11.3
		 * @return self
		 */
		public static function get_instance() {
			if ( ! isset( self::$instance ) ) {
				self::$instance = new self();
			}

			return self::$instance;
		}

		/**
		 * Constructor.
		 *
		 * @since 4.11.3
		 */
		private function __construct() {
			// Bail if Elementor is not active.
			if ( ! did_action( 'elementor/loaded' ) ) {
				return;
			}

			// Get post ID.
			$post_id = 0;
			if ( isset( $_REQUEST['post'] ) ) {
				$post_id = absint( $_REQUEST['post'] );
			}
			if ( isset( $_REQUEST['editor_post_id'] ) ) {
				$post_id = absint( $_REQUEST['editor_post_id'] );
			}

			$post_type = get_post_type( $post_id );
			// Bail if post type is excluded.
			if ( ! $post_id || in_array( $post_type, self::get_excluded_post_types(), true ) ) {
				return;
			}

			$this->init_hooks();
		}

		/**
		 * Initialize WordPress hooks.
		 *
		 * @since 4.11.3
		 */
		private function init_hooks() {
			// Registering actions for Elementor editor assets, document controls, and custom control styles.
			add_action( 'elementor/editor/after_enqueue_scripts', array( $this, 'enqueue_editor_assets' ) );
			add_action( 'elementor/documents/register_controls', array( $this, 'register_document_controls' ), 20 );
			add_action( 'elementor/editor/after_enqueue_styles', array( $this, 'add_custom_control_style' ) );

			// Hook into Elementor's document saving process to persist Astra-specific settings.
			add_action( 'elementor/document/after_save', array( $this, 'sync_save_settings' ) );

			// Hook into the template redirect action to handle Elementor preview.
			add_action( 'template_redirect', array( $this, 'handle_preview' ) );

			// Hook into wp_after_insert_post to sync site-post-title with Elementor hide_title.
			add_action( 'wp_after_insert_post', array( $this, 'sync_site_post_title_to_elementor' ) );
		}

		/**
		 * Check if in Elementor editor mode.
		 *
		 * @since 4.11.9
		 * @return bool
		 */
		public static function is_elementor_editor() {
			// Check if in Elementor editor mode.
			/** @psalm-suppress UndefinedClass */
			if ( ! class_exists( '\Elementor\Plugin' ) || ! \Elementor\Plugin::$instance->editor || ! \Elementor\Plugin::$instance->editor->is_edit_mode() ) {
				return false;
			}

			return true;
		}

		/**
		 * Get array of setting keys for Astra Elementor settings.
		 *
		 * @since 4.11.3
		 *
		 * @return array Array of setting keys.
		 */
		public static function get_astra_elementor_setting_keys() {
			$settings = array(
				'site-post-title', // Astra Disable Title.
				'ast-site-content-layout', // Container Layout.
				'site-content-style', // Container Style.
				'site-sidebar-layout', // Sidebar Layout.
				'site-sidebar-style', // Sidebar Style.
				'ast-global-header-display', // Disable Header.
				'footer-sml-layout', // Disable Footer.
				'ast-banner-title-visibility', // Disable Banner Area.
				'ast-breadcrumbs-content', // Disable breadcrumb.
				'ast-hfb-above-header-display', // Disable Above Header.
				'ast-main-header-display', // Disable Primary Header.
				'ast-hfb-below-header-display', // Disable Below Header.
				'ast-hfb-mobile-header-display', // Disable Mobile Header.
				'theme-transparent-header-meta', // Transparent Header.
				'stick-header-meta', // Sticky Header (Pro Option).
				'header-above-stick-meta', // Stick Above Header (Pro Option).
				'header-main-stick-meta', // Stick Primary Header (Pro Option).
				'header-below-stick-meta', // Stick Below Header (Pro Option).
			);

			/**
			 * Filter to modify the Astra Elementor setting keys.
			 *
			 * @since 4.11.3
			 *
			 * @param array $keys Array of Astra Elementor setting keys.
			 */
			return apply_filters( 'astra_elementor_page_setting_keys', $settings );
		}

		/**
		 * Enqueue scripts for Elementor editor settings React app.
		 *
		 * @since 4.11.3
		 */
		public function enqueue_editor_assets() {
			// Check if in Elementor editor mode.
			if ( ! self::is_elementor_editor() ) {
				return;
			}

			$handle = 'astra-elementor-meta-settings';
			$path   = ASTRA_THEME_URI . '/inc/metabox/extend-metabox/build/elementor.js';

			// Get the script dependencies from the asset file.
			$dependencies = array();
			if ( file_exists( ASTRA_THEME_DIR . 'inc/metabox/extend-metabox/build/elementor.asset.php' ) ) {
				$assets = require ASTRA_THEME_DIR . 'inc/metabox/extend-metabox/build/elementor.asset.php';
				if ( isset( $assets['dependencies'] ) ) {
					$dependencies = $assets['dependencies'];
				}
			}

			wp_enqueue_script(
				$handle,
				$path,
				$dependencies,
				ASTRA_THEME_VERSION,
				true
			);

			/**
			 * Filter to modify the localized data for Astra astraElementor editor settings.
			 *
			 * @since 4.11.3
			 * @param array $localize_data Localized data for astraElementor editor settings.
			 */
			$localize_data = apply_filters(
				'astra_elementor_editor_localize_data',
				array(
					'themeName'    => astra_get_theme_name(),
					'themeIconUrl' => esc_url( apply_filters( 'astra_admin_menu_icon', ASTRA_THEME_URI . 'inc/assets/images/astra-logo.svg' ) ),
					'postTitle'    => get_post_meta( intval( get_the_ID() ), 'site-post-title', true ),
				)
			);

			wp_localize_script( $handle, 'astraElementorEditor', $localize_data );
		}

		/**
		 * Get formatted container layout options with 'title' and 'icon'.
		 *
		 * @return array Formatted content layout options.
		 */
		public static function get_formatted_container_layout_options() {
			$options = Astra_Meta_Boxes::get_instance()->get_content_layout_options();

			foreach ( $options as $key => $label ) {
				$options[ $key ] = array(
					'title' => $label,
					'icon'  => 'default' === $key ? 'layout-default' : $key, // alternatively we can use 'image' key to provide custom image URLs.
				);
			}

			return $options;
		}

		/**
		 * Get formatted container style options with only 'title'.
		 *
		 * @return array Formatted content style options.
		 */
		public static function get_formatted_container_style_options() {
			$options = Astra_Meta_Boxes::get_instance()->get_content_style_options();

			return array_map(
				static function( $title ) {
					return array( 'title' => $title );
				},
				$options
			);
		}

		/**
		 * Get formatted sidebar layout options with 'title' and 'icon'.
		 *
		 * @return array Formatted sidebar layout options.
		 */
		public static function get_formatted_sidebar_layout_options() {
			$options = Astra_Meta_Boxes::get_instance()->get_sidebar_options();

			foreach ( $options as $key => $label ) {
				$options[ $key ] = array(
					'title' => $label,
					'icon'  => 'default' === $key ? 'layout-default' : $key,
				);
			}

			return $options;
		}

		/**
		 * Get formatted sidebar style options with only 'title'.
		 *
		 * @return array Formatted sidebar style options.
		 */
		public static function get_formatted_sidebar_style_options() {
			$options = Astra_Meta_Boxes::get_instance()->get_sidebar_style_options();

			return array_map(
				static function( $title ) {
					return array( 'title' => $title );
				},
				$options
			);
		}

		/**
		 * Get formatted header enabled options with only 'title'.
		 * Usage: For Transparent and Sticky Header options.
		 *
		 * @return array Formatted header enabled options.
		 */
		public static function get_formatted_header_enabled_options() {
			$options = Astra_Meta_Boxes::get_instance()->get_header_enabled_options();

			return array_map(
				static function( $title ) {
					return array( 'title' => $title );
				},
				$options
			);
		}

		/**
		 * Register additional document controls.
		 *
		 * Adds a new section and control to the Elementor Page Settings panel,
		 * providing a placeholder div for the React-powered Astra Settings UI.
		 *
		 * @param \Elementor\Core\DocumentTypes\PageBase $document The PageBase document instance.
		 *
		 * @since 4.11.3
		 *
		 * @psalm-suppress DocblockTypeContradiction
		 * @psalm-suppress UndefinedDocblockClass
		 * @psalm-suppress UndefinedClass
		 */
		public function register_document_controls( $document ) {
			if ( ! class_exists( '\Elementor\Controls_Manager' ) || ! class_exists( '\Elementor\Core\DocumentTypes\PageBase' ) ) {
				return;
			}

			// Only proceed if the document is a valid Elementor PageBase type and has elements.
			if ( ! $document instanceof \Elementor\Core\DocumentTypes\PageBase || ! $document::get_property( 'has_elements' ) ) {
				return;
			}

			$id = intval( get_the_ID() );

			// Start a new section in the Elementor Page Settings -> Setting tab.
			$document->start_controls_section(
				'astra_section',
				array(
					'label' => esc_html__( 'Astra Settings', 'astra' ),
					'tab'   => \Elementor\Controls_Manager::TAB_SETTINGS,
				)
			);

			// Container Section Title.
			$document->add_control(
				'ast-container-heading',
				array(
					'label' => __( 'Container', 'astra' ),
					'type'  => \Elementor\Controls_Manager::HEADING,
				)
			);

			// Container Layout using Choose control with images.
			$document->add_control(
				'ast-site-content-layout',
				array(
					'classes' => 'ast-layout-control',
					'label'   => __( 'Container Layout', 'astra' ),
					'type'    => \Elementor\Controls_Manager::CHOOSE,
					'options' => self::get_formatted_container_layout_options(),
					'default' => get_post_meta( $id, 'ast-site-content-layout', true ),
					'toggle'  => false,
				)
			);

			// Container Style using Choose control (button group style).
			$document->add_control(
				'site-content-style',
				array(
					'classes'     => 'ast-selector-control',
					'label'       => __( 'Container Style', 'astra' ),
					'type'        => \Elementor\Controls_Manager::CHOOSE,
					'options'     => self::get_formatted_container_style_options(),
					'default'     => get_post_meta( $id, 'site-content-style', true ),
					'description' => __( 'Container style will apply only when layout is set to either Normal or Narrow.', 'astra' ),
					'toggle'      => false,
				)
			);

			// Sidebar Section Title.
			$document->add_control(
				'ast-sidebar-heading',
				array(
					'label'     => __( 'Sidebar', 'astra' ),
					'type'      => \Elementor\Controls_Manager::HEADING,
					'separator' => 'before',
				)
			);

			$document->add_control(
				'site-sidebar-layout',
				array(
					'classes'     => 'ast-layout-control',
					'label'       => __( 'Sidebar Layout', 'astra' ),
					'type'        => \Elementor\Controls_Manager::CHOOSE,
					'options'     => self::get_formatted_sidebar_layout_options(),
					'default'     => get_post_meta( $id, 'site-sidebar-layout', true ),
					'description' => __( 'Sidebar will only apply when container layout is set to normal.', 'astra' ),
					'toggle'      => false,
				)
			);

			$document->add_control(
				'site-sidebar-style',
				array(
					'classes' => 'ast-selector-control',
					'label'   => __( 'Sidebar Style', 'astra' ),
					'type'    => \Elementor\Controls_Manager::CHOOSE,
					'options' => self::get_formatted_sidebar_style_options(),
					'default' => get_post_meta( $id, 'site-sidebar-style', true ),
					'toggle'  => false,
				)
			);

			// Disable Elements Section Title.
			$document->add_control(
				'ast-disable-elements-heading',
				array(
					'label'     => __( 'Disable Elements', 'astra' ),
					'type'      => \Elementor\Controls_Manager::HEADING,
					'separator' => 'before',
				)
			);

			$controls = Astra_Meta_Boxes::get_instance()->get_disable_section_fields();
			foreach ( $controls as $details ) {
				$meta_key = $details['key'];
				$document->add_control(
					$meta_key,
					array(
						'label'   => $details['label'],
						'type'    => \Elementor\Controls_Manager::SWITCHER,
						'default' => get_post_meta( $id, $meta_key, true ) === 'disabled' ? 'yes' : '',
					)
				);
			}

			$document->add_control(
				'ast-advanced-settings-heading',
				array(
					'label'     => __( 'Advanced Settings', 'astra' ),
					'type'      => \Elementor\Controls_Manager::HEADING,
					'separator' => 'before',
				)
			);

			$document->add_control(
				'ast-header-rows-popover',
				array(
					'classes' => 'ast-popover-control',
					'type'    => \Elementor\Controls_Manager::POPOVER_TOGGLE,
					'label'   => __( 'Header Rows', 'astra' ),
				)
			);

			$document->start_popover();

			$controls = Astra_Meta_Boxes::get_instance()->get_header_disable_meta_fields();
			foreach ( $controls as $details ) {
				$meta_key = $details['key'];
				$document->add_control(
					$meta_key,
					array(
						'label'   => $details['label'],
						'type'    => \Elementor\Controls_Manager::SWITCHER,
						'default' => get_post_meta( $id, $meta_key, true ) === 'disabled' ? 'yes' : '',
					)
				);
			}

			$document->end_popover();

			$document->add_control(
				'theme-transparent-header-meta',
				array(
					'classes' => 'ast-selector-control',
					'label'   => __( 'Transparent Header', 'astra' ),
					'type'    => \Elementor\Controls_Manager::CHOOSE,
					'options' => self::get_formatted_header_enabled_options(),
					'default' => get_post_meta( $id, 'theme-transparent-header-meta', true ),
					'toggle'  => false,
				)
			);

			if ( defined( 'ASTRA_EXT_VER' ) && class_exists( 'Astra_Ext_Extension' ) && Astra_Ext_Extension::is_active( 'sticky-header' ) ) {
				$document->add_control(
					'stick-header-meta',
					array(
						'classes' => 'ast-selector-control',
						'label'   => __( 'Sticky Header', 'astra' ),
						'type'    => \Elementor\Controls_Manager::CHOOSE,
						'options' => self::get_formatted_header_enabled_options(),
						'default' => get_post_meta( $id, 'stick-header-meta', true ),
						'toggle'  => false,
					)
				);

				$document->add_control(
					'ast-sticky-header-rows-popover',
					array(
						'classes'   => 'ast-popover-control',
						'type'      => \Elementor\Controls_Manager::POPOVER_TOGGLE,
						'label'     => __( 'Sticky Header Rows', 'astra' ),
						'condition' => array(
							'stick-header-meta' => 'enabled', // show only when Sticky Header is enabled.
						),
					)
				);

				$document->start_popover();

				$controls = Astra_Meta_Boxes::get_instance()->get_sticky_header_options();
				foreach ( $controls as $details ) {
					$meta_key = $details['key'];
					$document->add_control(
						$meta_key,
						array(
							'label'   => $details['label'],
							'type'    => \Elementor\Controls_Manager::SWITCHER,
							'default' => get_post_meta( $id, $meta_key, true ) === 'disabled' ? 'yes' : '',
						)
					);
				}

				$document->end_popover();
			}

			$document->add_control(
				'ast-save-changes-notice',
				array(
					'type'        => \Elementor\Controls_Manager::NOTICE,
					'notice_type' => 'warning',
					'content'     => __( 'Make sure to update your post for changes to take effect.', 'astra' ),
				)
			);

			// Preview changes button.
			$document->add_control(
				'ast-preview-changes-button',
				array(
					'type'        => \Elementor\Controls_Manager::BUTTON,
					'button_type' => 'success',
					'text'        => esc_html__( 'Preview Changes', 'astra' ),
					'event'       => 'namespace:editor:astraRefresh',
					'disabled'    => true,
				)
			);

			if ( ! defined( 'ASTRA_EXT_VER' ) ) {
				$document->add_control(
					'ast-pro-notice',
					array(
						'type' => \Elementor\Controls_Manager::RAW_HTML,
						'raw'  => sprintf(
							'<div class="ast-pro-upgrade-cta-wrapper">
								<img src="%1$s" alt="Astra Logo">
								<p class="elementor-control-field-description">%2$s</p>
								<a href="%3$s" class="ast-pro-upgrade-link" target="_blank">%4$s</a>
							</div>',
							esc_url( ASTRA_THEME_URI . 'inc/assets/images/astra-logo.svg' ),
							__( 'Unlock your full design potential and build a website to be proud of with Astra Pro.', 'astra' ),
							astra_get_pro_url( '/pricing/', 'free-theme', 'elementor-editor', 'upgrade' ),
							__( 'Upgrade Now', 'astra' )
						),
					)
				);
			}

			$document->end_controls_section();

			// Add a info notice below the Hide Title control.
			$document->start_injection(
				array(
					'of'       => 'post_status',
					'fallback' => array(
						'of' => 'post_title',
					),
				)
			);

			$document->add_control(
				'ast-hide-title-notice',
				array(
					'type'        => \Elementor\Controls_Manager::NOTICE,
					'notice_type' => 'info',
					'content'     => __( "Changes to 'Hide Title' will automatically sync with Astra’s 'Disable Title' option.", 'astra' ),
				)
			);

			$document->end_injection();
		}

		/**
		 * Adds inline styles to enhance Astra controls in Elementor Page Settings.
		 *
		 * Optimizes layout and display of CHOOSE controls (like container and sidebar settings).
		 * by using grid layouts and ensuring button labels are visible.
		 *
		 * @since 4.11.3
		 *
		 * @return void
		 */
		public function add_custom_control_style() {
			$css_rules = '
				<style>
					.ast-layout-control .elementor-control-field,
					.ast-selector-control .elementor-control-field {
						flex-direction: column;
						align-items: flex-start;
						gap: 10px;
					}

					.ast-layout-control .elementor-control-input-wrapper,
					.ast-selector-control .elementor-control-input-wrapper {
						width: 100%;
					}

					.ast-layout-control .elementor-choices {
						display: grid;
						grid-template-columns: repeat(2, 1fr);
						gap: 10px;
						height: auto;
					}

					.ast-layout-control .elementor-choices-label,
					.ast-selector-control .elementor-choices-label {
						position: relative;
						width: 100%;
					}

					.ast-layout-control .elementor-choices-label {
						min-height: 92.5px;
						border-radius: 3px;
						border: none !important;
					}

					.ast-selector-control .elementor-choices-label::before {
						content: attr(data-tooltip);
					}

					.ast-popover-control .elementor-control-popover-toggle-reset-label {
						display: none;
					}

					.elementor-control-ast-preview-changes-button.elementor-control {
						position: sticky;
						bottom: 0;
						padding-top: 15px;
						backdrop-filter: blur(2px);
					}

					.elementor-control-ast-preview-changes-button.elementor-control .elementor-control-input-wrapper,
					.elementor-control-ast-preview-changes-button.elementor-control .elementor-button {
						width: 100%;
					}

					.ast-pro-upgrade-cta-wrapper {
						padding: 20px 0;
						text-align: center;
						display: flex;
						flex-direction: column;
						align-items: center;
						gap: 15px;
					}

					.ast-pro-upgrade-cta-wrapper .elementor-control-field-description {
						margin-top: 0;
					}

					.ast-pro-upgrade-cta-wrapper a.ast-pro-upgrade-link {
						color: #0284C7;
						width: 100%;
						padding: 8px;
						border: 1px solid #0284C7;
						border-radius: 2px;
					}
				';

			// Icons CSS.
			$icon_svgs = array(
				'.layout-default'         => self::get_svg( 'layout-default' ),
				'.normal-width-container' => self::get_svg( 'normal-width-container' ),
				'.narrow-width-container' => self::get_svg( 'narrow-width-container' ),
				'.full-width-container'   => self::get_svg( 'full-width-container' ),
				'.no-sidebar'             => self::get_svg( 'no-sidebar' ),
				'.left-sidebar'           => self::get_svg( 'left-sidebar' ),
				'.right-sidebar'          => self::get_svg( 'right-sidebar' ),
			);

			foreach ( $icon_svgs as $selector => $svg ) {
				$encoded_svg = self::transform_svg( $svg );

				$css_rules .= "{$selector}::before {
					content: '';
					position: absolute;
					width: 100%;
					height: 100%;
					top: 0;
					left: 0;
					background: url(\"data:image/svg+xml;utf8,{$encoded_svg}\") no-repeat center / contain;
				}";
			}

			$css_rules .= '</style>';

			// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- This is inline CSS and does not require escaping.
			echo class_exists( 'Astra_Minify' ) ? Astra_Minify::trim_css( $css_rules ) : $css_rules;
		}

		/**
		 * Handle Elementor template redirect for previewing Astra settings changes.
		 *
		 * @since 4.11.3
		 */
		public function handle_preview() {
			$post_id       = intval( get_the_ID() );
			$preview_id    = intval( isset( $_GET['preview_id'] ) ? $_GET['preview_id'] : 0 );
			$preview_nonce = isset( $_GET['preview_nonce'] ) && is_scalar( $_GET['preview_nonce'] ) ? sanitize_text_field( $_GET['preview_nonce'] ) : '';

			/** @psalm-suppress UndefinedClass */
			$is_elementor_editor_preview   = class_exists( '\Elementor\Plugin' ) && \Elementor\Plugin::$instance->preview->is_preview_mode();
			$is_elementor_frontend_preview = is_preview() && $post_id === $preview_id && wp_verify_nonce( $preview_nonce, 'post_preview_' . $preview_id );

			// Bail early if not in Elementor preview.
			if ( ! $is_elementor_editor_preview && ! $is_elementor_frontend_preview ) {
				return;
			}

			$revision_id = $post_id;
			$revisions   = wp_get_post_revisions(
				$post_id,
				array(
					'order'   => 'DESC',
					'orderby' => 'ID',
				)
			);

			foreach ( $revisions as $revision ) {
				// Elementor stores this meta in preview revisions.
				if ( get_post_meta( $revision->ID, '_elementor_edit_mode', true ) ) {
					$revision_id = $revision->ID;
					break;
				}
			}

			$settings = get_post_meta( $revision_id, '_elementor_page_settings', true );
			$keys     = self::get_astra_elementor_setting_keys();
			foreach ( $keys as $meta_key ) {
				$meta_val = isset( $settings[ $meta_key ] ) ? $settings[ $meta_key ] : get_post_meta( $post_id, $meta_key, true );

				add_filter(
					'get_post_metadata',
					static function( $value, $object_id, $key ) use ( $post_id, $meta_key, $meta_val ) {
						if ( $object_id === $post_id && $key === $meta_key ) {
							return array( $meta_val === 'yes' ? 'disabled' : $meta_val );
						}
						return $value;
					},
					10,
					3
				);
			}

			// Ensure the title is enabled for Elementor preview so that Hide Title toggle works correctly.
			add_action( 'astra_the_title_enabled', '__return_true', 999 );
		}

		/**
		 * Sync specific Astra settings from Elementor's Page Settings to post meta.
		 *
		 * This function checks if certain custom Elementor controls are enabled (like disabling the header, footer,
		 * or banner area) and updates the corresponding post meta values accordingly. If the setting is not enabled,
		 * the meta key is removed.
		 *
		 * @psalm-suppress UndefinedDocblockClass
		 * @param \Elementor\Core\Base\Document $document The Elementor document object being saved.
		 *
		 * @since 4.11.3
		 *
		 * @return void
		 */
		public function sync_save_settings( $document ) {
			$post_id = $document->get_id();

			if ( ! $post_id || wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
				return;
			}

			// Get fresh saved settings directly from the meta.
			$page_settings = $document->get_meta( '_elementor_page_settings' );

			// If the settings are not an array, initialize it as an empty array.
			if ( ! is_array( $page_settings ) ) {
				$page_settings = array();
			}

			// Sync astra site-post-title with elementor hide_title.
			$page_settings['site-post-title'] = isset( $page_settings['hide_title'] ) ? $page_settings['hide_title'] : '';

			$keys = array(
				'ast-site-content-layout', // Container Layout.
				'site-content-style', // Container Style.
				'site-sidebar-layout', // Sidebar Layout.
				'site-sidebar-style', // Sidebar Style.
				'theme-transparent-header-meta', // Transparent Header.
				'stick-header-meta', // Sticky Header (Pro Option).
			);

			foreach ( $keys as $meta_key ) {
				if ( isset( $page_settings[ $meta_key ] ) ) {
					$value = $page_settings[ $meta_key ];
					if ( $value ) {
						update_post_meta( $post_id, $meta_key, $value );
					} else {
						delete_post_meta( $post_id, $meta_key );
					}

					// Remove setting from Elementor's saved settings.
					unset( $page_settings[ $meta_key ] );
				}
			}

			$keys = array(
				'site-post-title', // Astra Disable Title.
				'ast-global-header-display', // Disable Header.
				'footer-sml-layout', // Disable Footer.
				'ast-banner-title-visibility', // Disable Banner Area.
				'ast-breadcrumbs-content', // Disable breadcrumb.
				'ast-hfb-above-header-display', // Disable Above Header.
				'ast-main-header-display', // Disable Primary Header.
				'ast-hfb-below-header-display', // Disable Below Header.
				'ast-hfb-mobile-header-display', // Disable Mobile Header.
				'header-above-stick-meta', // Stick Above Header (Pro Option).
				'header-main-stick-meta', // Stick Primary Header (Pro Option).
				'header-below-stick-meta', // Stick Below Header (Pro Option).
			);

			foreach ( $keys as $meta_key ) {
				if ( isset( $page_settings[ $meta_key ] ) ) {
					$value = $page_settings[ $meta_key ];

					if ( $value === 'yes' ) {
						update_post_meta( $post_id, $meta_key, 'disabled' );
					} else {
						delete_post_meta( $post_id, $meta_key );
					}

					// Remove setting from Elementor's saved settings.
					unset( $page_settings[ $meta_key ] );
				}
			}

			// $document->update_meta( '_elementor_page_settings', $page_settings );
			update_post_meta( $post_id, '_elementor_page_settings', $page_settings );
		}

		/**
		 * Retrieves an SVG icon based on the given icon name.
		 *
		 * @param string $icon The name of the icon to retrieve.
		 *
		 * @since 4.11.3
		 *
		 * @return string The SVG code for the icon or an empty string if the icon does not exist.
		 */
		public static function get_svg( $icon = '' ) {
			if ( ! class_exists( 'Astra_Builder_UI_Controller' ) ) {
				return '';
			}

			// Ensure the SVG icons are loaded.
			$svg_icons = Astra_Builder_UI_Controller::$ast_svgs;
			if ( ! Astra_Builder_UI_Controller::$ast_svgs ) {
				Astra_Builder_UI_Controller::fetch_svg_icon();
				$svg_icons = Astra_Builder_UI_Controller::$ast_svgs;
			}

			return isset( $svg_icons[ $icon ] ) ? $svg_icons[ $icon ] : '';
		}

		/**
		 * Transforms SVG markup for use in inline CSS by modifying colors and encoding.
		 *
		 * @param string $svg The raw SVG markup.
		 *
		 * @since 4.11.3
		 *
		 * @return string The transformed and encoded SVG string.
		 */
		private static function transform_svg( $svg ) {
			// Basic validation: check if input is a non-empty string.
			if ( trim( $svg ) === '' ) {
				return rawurlencode( "<svg xmlns='http://www.w3.org/2000/svg' width='1' height='1'></svg>" );
			}

			// Replace only the first occurrence of stroke='#D1D5DB' with a semi-transparent color.
			// phpcs:ignore Generic.PHP.ForbiddenFunctions.FoundWithAlternative -- Safe usage: no /e modifier, transforms SVG colors for dark mode
			$svg = preg_replace( "/stroke='#D1D5DB'/", "stroke='#9DA5AE55'", $svg, 1 );

			// Perform bulk replacements for remaining known values.
			$svg = str_replace(
				array( "fill='white'", "stroke='#D8DBDF'", "fill='#E5E7EB'", "fill='#D1D5DB'", "stroke='#D1D5DB'" ),
				array( "fill='#9DA5AE55'", "stroke='#9DA5AE55'", "fill='currentColor'", "fill='currentColor'", "stroke='currentColor'" ),
				$svg
			);

			// URL-encode the SVG for embedding as a background-image.
			return rawurlencode( $svg );
		}

		/**
		 * Sync site-post-title meta to Elementor hide_title when post is saved via WP editor.
		 *
		 * @param int $post_id Post id.
		 *
		 * @since 4.11.9
		 */
		public function sync_site_post_title_to_elementor( $post_id ) {
			// Skip if this is a revision or autosave.
			if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
				return;
			}

			// Bail early if this is an Elementor AJAX request.
			if ( ( isset( $_REQUEST['action'] ) && 'elementor_ajax' === $_REQUEST['action'] ) ) {
				return true;
			}

			// Skip if saving from Elementor to avoid conflicts.
			if ( did_action( 'elementor/document/after_save' ) ) {
				return;
			}

			// Skip if post builder is not Elementor.
			if ( 'builder' !== get_post_meta( $post_id, '_elementor_edit_mode', true ) ) {
				return;
			}

			// Get the site-post-title meta value.
			$site_post_title = get_post_meta( $post_id, 'site-post-title', true );

			// Get current Elementor page settings.
			$elementor_settings = get_post_meta( $post_id, '_elementor_page_settings', true );
			if ( ! is_array( $elementor_settings ) ) {
				$elementor_settings = array();
			}

			// Check if we need to update the hide_title setting.
			$current_hide_title = isset( $elementor_settings['hide_title'] ) ? $elementor_settings['hide_title'] : '';
			$new_hide_title     = 'disabled' === $site_post_title ? 'yes' : '';

			// Only update if the value has changed.
			if ( $current_hide_title !== $new_hide_title ) {
				if ( 'yes' === $new_hide_title ) {
					$elementor_settings['hide_title'] = 'yes';
				} else {
					unset( $elementor_settings['hide_title'] );
				}

				// Update the Elementor page settings meta.
				empty( $elementor_settings )
					? delete_post_meta( $post_id, '_elementor_page_settings' )
					: update_post_meta( $post_id, '_elementor_page_settings', $elementor_settings );

				// Regenerate Elementor CSS cache to update --page-title-display variable.
				if ( class_exists( '\Elementor\Plugin' ) ) {
					/** @psalm-suppress UndefinedClass */
					\Elementor\Plugin::$instance->files_manager->clear_cache();
				}
			}
		}

		/**
		 * Get excluded post types for Astra Meta setting in Elementor editor.
		 *
		 * @since 4.11.11
		 * @return array
		 */
		public static function get_excluded_post_types() {
			/**
			 * Filter to exclude post types from rendering Astra Meta setting in Elementor editor.
			 *
			 * @param array $excluded_post_types Array of post types to exclude.
			 */
			return apply_filters(
				'astra_elementor_editor_excluded_post_types',
				array(
					'astra-advanced-hook', // Astra Theme Builder Advanced Layout.
					'elementskit_template', // ElementsKit Template.
				)
			);
		}
	}
}

/**
 * Initialize the class singleton.
 */
Astra_Elementor_Editor_Settings::get_instance();
