<?php
/**
 * WP ADMIN assets will be enqueued here.
 *
 * @package monsterinsights
 */

/**
 * Class MonsterInsights_Admin_Assets
 * This class is responsible for load CSS and JS in admin panel.
 */
class MonsterInsights_Admin_Assets {
	/**
	 * MonsterInsights handles.
	 */
	private $own_handles = array(
		'monsterinsights-vue-script',
		// 'monsterinsights-vue-frontend',
		'monsterinsights-vue-reports',
		'monsterinsights-vue-widget',
		// Vue 3 handles (type=module)
		'monsterinsights-vue3-custom-dashboard',
	);

	/**
	 * Store manifest.json file content.
	 *
	 * @var array
	 */
	private static $manifest_data;

	/**
	 * Directory path of assets.
	 */
	private $version_path;

	/**
	 * Store Vue 3 manifest.json file content.
	 *
	 * @var array
	 */
	private static $manifest_data_v3;

	/**
	 * Class constructor.
	 */
	public function __construct() {
		global $wp_version;
		// This filter will only run if WP version is greater than 6.4.0.
		if ( version_compare( $wp_version, '6.4', '>=' ) ) {
			add_filter( 'wp_script_attributes', array( $this, 'set_scripts_as_type_module' ), 99999 );
		} else {
			// Use script_loader_tag if WordPress version is lower than 5.7.0.
			add_filter( 'script_loader_tag', array( $this, 'script_loader_tag' ), 99999, 3 );
		}

		add_action( 'admin_enqueue_scripts', array( $this, 'admin_styles' ) );

		add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
		$this->get_manifest_data();

		// CSS files path.
		$this->version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';

		$this->get_manifest_data_v3();
	}

	/**
	 * Updates the script type for the plugin's handles to type module.
	 *
	 * @param array $attrs Key-value pairs representing <script> tag attributes.
	 * @return array $attrs
	 */
	public function set_scripts_as_type_module( $attrs ) {
		if ( isset( $attrs['id'] ) && in_array( str_replace( '-js', '', $attrs['id'] ), $this->own_handles, true ) ) {
			$attrs['type'] = 'module';
		}
		return $attrs;
	}

	/**
	 * Update script tag.
	 * The vue code needs type=module.
	 */
	public function script_loader_tag( $tag, $handle, $src ) {

		if ( ! in_array( $handle, $this->own_handles ) ) {
			return $tag;
		}

		// Change the script tag by adding type="module" and return it.
		$html = str_replace( '></script>', ' type="module"></script>', $tag );

		$domain = monsterinsights_is_pro_version() ? 'google-analytics-premium' : 'google-analytics-for-wordpress';
		$html   = monsterinsights_get_printable_translations( $domain ) . $html;

		return $html;
	}

	/**
	 * Loads styles for all MonsterInsights-based Administration Screens.
	 *
	 * @return null Return early if not on the proper screen.
	 */
	public function admin_styles() {

		$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';

		// Load Common admin styles.
		wp_register_style( 'monsterinsights-admin-common-style', plugins_url( 'assets/css/admin-common' . $suffix . '.css', MONSTERINSIGHTS_PLUGIN_FILE ), array(), monsterinsights_get_asset_version() );
		wp_enqueue_style( 'monsterinsights-admin-common-style' );

		wp_enqueue_style(
			'monsterinsights-admin-common-build',
			plugins_url( $this->version_path . '/assets/vue/css/admin.css', MONSTERINSIGHTS_PLUGIN_FILE ),
			array(),
			monsterinsights_get_asset_version()
		);

		// Get current screen.
		$screen = get_current_screen();

		// Bail if we're not on a MonsterInsights screen.
		if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
			return;
		}

		// If this is a Vue 3 page, enqueue only Vue 3 styles and return early.
		if ( $this->is_vue3_admin_page() ) {
			// In dev mode, Vite injects CSS via JS; skip manual CSS enqueues.
			if ( ! $this->is_vue3_dev() ) {
				list( $base_url, $entry ) = $this->get_vue3_entry( 'src/modules/custom-dashboard/main.js' );

				if ( ! empty( $entry['css'] ) && is_array( $entry['css'] ) ) {
					foreach ( $entry['css'] as $i => $css_file ) {
						wp_enqueue_style( 'monsterinsights-v3-style-' . $i, $base_url . ltrim( $css_file, '/' ), array(), monsterinsights_get_asset_version() );
					}
				}
			}
			return;
		}

		// For the settings pages, load the Vue app scripts.
		if ( monsterinsights_is_settings_page() ) {
			if ( ! defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
				$this->enqueue_script_specific_css( 'src/modules/settings/settings.js' );
			}

			// Don't load other scripts on the settings page.
			return;
		}

		// For the report pages, load the Vue app scripts.
		if ( monsterinsights_is_reports_page() ) {
			if ( ! defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
				$this->enqueue_script_specific_css( 'src/modules/reports/reports.js' );
			}

			return;
		}

		// Tooltips
		wp_enqueue_script( 'jquery-ui-tooltip' );
	}

	/**
	 * Loads scripts for all MonsterInsights-based Administration Screens.
	 *
	 * @return null Return early if not on the proper screen.
	 */
	public function admin_scripts() {

		// Our Common Admin JS.
		$suffix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min';

		wp_enqueue_script( 'monsterinsights-admin-common-script', plugins_url( 'assets/js/admin-common' . $suffix . '.js', MONSTERINSIGHTS_PLUGIN_FILE ), array( 'jquery' ), monsterinsights_get_asset_version(), true );

		wp_localize_script(
			'monsterinsights-admin-common-script',
			'monsterinsights_admin_common',
			array(
				'ajax'                 => admin_url( 'admin-ajax.php' ),
				'dismiss_notice_nonce' => wp_create_nonce( 'monsterinsights-dismiss-notice' ),
			)
		);

		// Load setup wizard handler script for all admin pages where the setup wizard link might appear
		// This includes MonsterInsights pages and any admin page where the setup notice might show
		wp_enqueue_script( 'monsterinsights-admin-setup-wizard', plugins_url( 'assets/js/admin-setup-wizard.js', MONSTERINSIGHTS_PLUGIN_FILE ), array( 'jquery' ), monsterinsights_get_asset_version(), true );

		wp_localize_script(
			'monsterinsights-admin-setup-wizard',
			'monsterinsights',
			array(
				'ajax'  => admin_url( 'admin-ajax.php' ),
				'nonce' => wp_create_nonce( 'mi-admin-nonce' ),
			)
		);

		// Get current screen.
		$screen = get_current_screen();

		// Bail if we're not on a MonsterInsights screen for other scripts.
		if ( empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
			return;
		}

		$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
		$text_domain  = monsterinsights_is_pro_version() ? 'google-analytics-premium' : 'google-analytics-for-wordpress';

		$license      = MonsterInsights()->license;
		$license_info = array(
			'type'      => $license->get_license_type(),
			'is_agency' => $license->is_agency(),
		);

		// Get auth data (shared across Vue 2 and Vue 3 apps)
		$auth      = MonsterInsights()->auth;
		$auth_data = array(
			'v4'                                  => $auth->get_v4_id(),
			'network_v4'                          => is_multisite() ? $auth->get_network_v4_id() : '',
			'manual_v4'                           => $auth->get_manual_v4_id(),
			'network_manual_v4'                   => is_multisite() ? $auth->get_network_manual_v4_id() : '',
			'viewname'                            => $auth->get_viewname(),
			'network_viewname'                    => is_multisite() ? $auth->get_network_viewname() : '',
			'measurement_protocol_secret'         => $auth->get_measurement_protocol_secret(),
			'network_measurement_protocol_secret' => is_multisite() ? $auth->get_network_measurement_protocol_secret() : '',
		);

		// If this is a Vue 3 page, enqueue only Vue 3 script and return early.
		if ( $this->is_vue3_admin_page() ) {
			$handle = 'monsterinsights-vue3-custom-dashboard';

			if ( $this->is_vue3_dev() ) {
				$dev_url = trailingslashit( $this->get_vue3_dev_url() ) . 'src/modules/custom-dashboard/main.js';
				wp_register_script( $handle, $dev_url, array( 'wp-i18n', 'wp-util' ), monsterinsights_get_asset_version(), true );
				wp_enqueue_script( $handle );
			} else {
				list( $base_url, $entry ) = $this->get_vue3_entry( 'src/modules/custom-dashboard/main.js' );
				if ( ! empty( $entry['file'] ) ) {
					$src = $base_url . ltrim( $entry['file'], '/' );
					wp_register_script( $handle, $src, array( 'wp-i18n', 'wp-util' ), monsterinsights_get_asset_version(), true );
					wp_enqueue_script( $handle );
				}
			}

			// Provide bootstrap payload for the Vue 3 app in build
			$site_auth = $auth->get_viewname();
			$ms_auth   = is_multisite() && $auth->get_network_viewname();

			wp_localize_script(
				$handle,
				'monsterinsights',
				array(
					'ajax'                 => admin_url( 'admin-ajax.php' ),
					'assets_url'           => apply_filters( 'monsterinsights_vue3_assets_url', plugins_url( $version_path . '/assets/vue3', MONSTERINSIGHTS_PLUGIN_FILE ) ),
					'nonce'                => wp_create_nonce( 'mi-admin-nonce' ),
					'cd_nonce'             => wp_create_nonce( 'mi_custom_dashboard_ajax_nonce' ), // Custom Dashboard nonce
					'network'              => is_network_admin(),
					'custom_dashboard_url' => add_query_arg( 'page', 'monsterinsights_custom_dashboard', admin_url( 'admin.php' ) ),
					'license'              => $license_info,
					'auth'                 => $auth_data,
					'authed'               => $site_auth || $ms_auth, // Boolean for admin bar compatibility
					'plugin_version'       => MONSTERINSIGHTS_VERSION,
					'wizard_url'           => monsterinsights_get_onboarding_url(),
					'rest_url'             => get_rest_url(),
					'rest_nonce'           => wp_create_nonce( 'wp_rest' ),
				)
			);

			// Load translations for Vue 3 app using WordPress's script translation system
			wp_set_script_translations( $handle, 'google-analytics-for-wordpress' );

			return;
		}

		// For the settings page, load the Vue app.
		if ( monsterinsights_is_settings_page() ) {
			$app_js_url = self::get_js_url( 'src/modules/settings/settings.js' );
			wp_register_script( 'monsterinsights-vue-script', $app_js_url, array( 'wp-i18n' ), monsterinsights_get_asset_version(), true );
			wp_enqueue_script( 'monsterinsights-vue-script' );

			$plugins         = get_plugins();
			$install_amp_url = false;
			if ( monsterinsights_can_install_plugins() ) {
				$amp_key = 'amp/amp.php';
				if ( array_key_exists( $amp_key, $plugins ) ) {
					$install_amp_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=' . $amp_key ), 'activate-plugin_' . $amp_key );
				} else {
					$install_amp_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=amp' ), 'install-plugin_amp' );
				}
			}

			$install_woocommerce_url = false;
			if ( monsterinsights_can_install_plugins() ) {
				$woo_key = 'woocommerce/woocommerce.php';
				if ( array_key_exists( $woo_key, $plugins ) ) {
					$install_woocommerce_url = wp_nonce_url( self_admin_url( 'plugins.php?action=activate&plugin=' . $woo_key ), 'activate-plugin_' . $woo_key );
				} else {
					$install_woocommerce_url = wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=woocommerce' ), 'install-plugin_woocommerce' );
				}
			}

			$prepared_dimensions = array();
			if ( class_exists( 'MonsterInsights_Admin_Custom_Dimensions' ) ) {
				$dimensions          = new MonsterInsights_Admin_Custom_Dimensions();
				$dimensions          = $dimensions->custom_dimensions();
				$prepared_dimensions = array();
				foreach ( $dimensions as $dimension_type => $dimension ) {
					$dimension['type']     = $dimension_type;
					$prepared_dimensions[] = $dimension;
				}
			}

			$is_authed = ( MonsterInsights()->auth->is_authed() || MonsterInsights()->auth->is_network_authed() );

			wp_localize_script(
				'monsterinsights-vue-script',
				'monsterinsights',
				array(
					'ajax'                            => admin_url( 'admin-ajax.php' ),
					'nonce'                           => wp_create_nonce( 'mi-admin-nonce' ),
					'network'                         => is_network_admin(),
					'assets'                          => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
					'roles'                           => monsterinsights_get_roles(),
					'roles_manage_options'            => monsterinsights_get_manage_options_roles(),
					'shareasale_id'                   => monsterinsights_get_shareasale_id(),
					'shareasale_url'                  => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
					'addons_url'                      => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
					'seo_settings_page_url'           => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/seo' ) : admin_url( 'admin.php?page=monsterinsights_settings#/seo' ),
					'aioseo_dashboard_url'            => is_multisite() ? network_admin_url( 'admin.php?page=aioseo' ) : admin_url( 'admin.php?page=aioseo' ),
					'wp_plugins_page_url'             => is_multisite() ? network_admin_url( 'plugins.php' ) : admin_url( 'plugins.php' ),
					'email_summary_url'               => admin_url( 'admin.php?monsterinsights_email_preview&monsterinsights_email_template=summary' ),
					'install_amp_url'                 => $install_amp_url,
					'install_woo_url'                 => $install_woocommerce_url,
					'dimensions'                      => $prepared_dimensions,
					'install_plugins'                 => monsterinsights_can_install_plugins(),
					'unfiltered_html'                 => current_user_can( 'unfiltered_html' ),
					'activate_nonce'                  => wp_create_nonce( 'monsterinsights-activate' ),
					'deactivate_nonce'                => wp_create_nonce( 'monsterinsights-deactivate' ),
					'install_nonce'                   => wp_create_nonce( 'monsterinsights-install' ),
					// Used to add notices for future deprecations.
					'versions'                        => monsterinsights_get_php_wp_version_warning_data(),
					'plugin_version'                  => MONSTERINSIGHTS_VERSION,
					'is_admin'                        => true,
					'admin_email'                     => get_option( 'admin_email' ),
					'site_url'                        => get_site_url(),
					'site_name'                       => get_bloginfo( 'name' ),
					'reports_url'                     => add_query_arg( 'page', 'monsterinsights_reports', admin_url( 'admin.php' ) ),
					'landing_pages_top_reports_url'   => add_query_arg( 'page', 'monsterinsights_reports#/top-landing-pages', admin_url( 'admin.php' ) ),
					'custom_view_url'                 => add_query_arg( 'page', 'monsterinsights_custom_dashboard', admin_url( 'admin.php' ) ),
					'ecommerce_report_url'            => add_query_arg( 'page', 'monsterinsights_reports#/ecommerce', admin_url( 'admin.php' ) ),
					'ecommerce_settings_tab_url'      => add_query_arg( 'page', 'monsterinsights_settings#/ecommerce', admin_url( 'admin.php' ) ),
					'first_run_notice'                => apply_filters( 'monsterinsights_settings_first_time_notice_hide', monsterinsights_get_option( 'monsterinsights_first_run_notice' ) ),
					'getting_started_url'             => is_network_admin() ? network_admin_url( 'admin.php?page=monsterinsights_network#/about' ) : admin_url( 'admin.php?page=monsterinsights_settings#/about/getting-started' ),
					'authed'                          => $is_authed,
					'new_pretty_link_url'             => admin_url( 'post-new.php?post_type=pretty-link' ),
					'wpmailsmtp_admin_url'            => admin_url( 'admin.php?page=wp-mail-smtp' ),
					'load_headline_analyzer_settings' => monsterinsights_load_gutenberg_app() ? 'true' : 'false',
					'exit_url'                        => add_query_arg( 'page', 'monsterinsights_settings', admin_url( 'admin.php' ) ),
					'timezone'                        => date( 'e' ), // phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date -- We need this to depend on the runtime timezone.
					'funnelkit_stripe_woo_page_url'   => admin_url( 'admin.php?page=wc-settings&tab=fkwcs_api_settings' ),
					'funnelkit_stripe_woo_nonce'      => wp_create_nonce( 'monsterinsights-funnelkit-stripe-woo-nonce' ),
					'site_notes_export_synced'        => monsterinsights_get_option( 'site_notes_export_synced', 0 ),
					'site_notes_import_synced'        => monsterinsights_get_option( 'site_notes_import_synced', 0 ),
					'license'                         => $license_info,
					'currency'                        => monsterinsights_get_ecommerce_currency(),
				)
			);

			wp_scripts()->add_inline_script(
				'monsterinsights-vue-script',
				monsterinsights_get_printable_translations( $text_domain ),
				'translation'
			);

			// Don't load other scripts on the settings page.
			return;
		}

		// For the report pages, load the Vue app.
		if ( monsterinsights_is_reports_page() ) {

			$app_js_url = self::get_js_url( 'src/modules/reports/reports.js' );
			wp_register_script( 'monsterinsights-vue-reports', $app_js_url, array( 'wp-i18n' ), monsterinsights_get_asset_version(), true );
			wp_enqueue_script( 'monsterinsights-vue-reports' );

			// We do not have a current auth.
			$auth      = MonsterInsights()->auth;
			$site_auth = $auth->get_viewname();
			$ms_auth   = is_multisite() && $auth->get_network_viewname();

			// Localize the script with the necessary data.
			wp_localize_script(
				'monsterinsights-vue-reports',
				'monsterinsights',
				array(
					'ajax'                => admin_url( 'admin-ajax.php' ),
					'nonce'               => wp_create_nonce( 'mi-admin-nonce' ),
					'rest_nonce'          => wp_create_nonce( 'wp_rest' ),
					'rest_url'            => get_rest_url(),
					'network'             => is_network_admin(),
					'assets'              => plugins_url( $version_path . '/assets/vue', MONSTERINSIGHTS_PLUGIN_FILE ),
					'pro_assets'          => plugins_url( $version_path . '/assets', MONSTERINSIGHTS_PLUGIN_FILE ),
					'shareasale_id'       => monsterinsights_get_shareasale_id(),
					'shareasale_url'      => monsterinsights_get_shareasale_url( monsterinsights_get_shareasale_id(), '' ),
					'addons_url'          => is_multisite() ? network_admin_url( 'admin.php?page=monsterinsights_network#/addons' ) : admin_url( 'admin.php?page=monsterinsights_settings#/addons' ),
					'timezone'            => date('e'), // phpcs:ignore
					'authed'              => $site_auth || $ms_auth,
					'settings_url'        => add_query_arg( 'page', 'monsterinsights_settings', admin_url( 'admin.php' ) ),
					// Used to add notices for future deprecations.
					'versions'            => monsterinsights_get_php_wp_version_warning_data(),
					'plugin_version'      => MONSTERINSIGHTS_VERSION,
					'is_admin'            => true,
					'admin_email'         => get_option( 'admin_email' ),
					'site_url'            => get_site_url(),
					'wizard_url'          => is_network_admin() ? network_admin_url( 'index.php?page=monsterinsights-onboarding' ) : admin_url( 'index.php?page=monsterinsights-onboarding' ),
					'install_nonce'       => wp_create_nonce( 'monsterinsights-install' ),
					'activate_nonce'      => wp_create_nonce( 'monsterinsights-activate' ),
					'deactivate_nonce'    => wp_create_nonce( 'monsterinsights-deactivate' ),
					'update_settings'     => current_user_can( 'monsterinsights_save_settings' ),
					'migrated'            => monsterinsights_get_option( 'gadwp_migrated', 0 ),
					'yearinreview'        => monsterinsights_yearinreview_dates(),
					'reports_url'         => add_query_arg( 'page', 'monsterinsights_reports', admin_url( 'admin.php' ) ),
					'feedback'            => MonsterInsights_Feature_Feedback::get_settings(),
					'addons_pre_check'    => array(
						'ai_insights' => is_plugin_active( 'monsterinsights-ai-insights/monsterinsights-ai-insights.php' ),
						'woo_product_feed_pro' => is_plugin_active( 'woo-product-feed-pro/woocommerce-sea.php' ),
					),
					'license'             => $license_info,
					'charitablewp_notice' => $this->show_charitablewp_notice(),
					'currency'            => monsterinsights_get_ecommerce_currency(),
				)
			);

			wp_scripts()->add_inline_script(
				'monsterinsights-vue-reports',
				monsterinsights_get_printable_translations( $text_domain ),
				'translation'
			);

			return;
		}

		// ublock notice
		add_action( 'admin_print_footer_scripts', array( $this, 'monsterinsights_settings_ublock_error_js' ), 9999999 );
	}

	/**
	 * Need to identify why this function is using.
	 */
	public function monsterinsights_settings_ublock_error_js() {
		echo "<script type='text/javascript'>\n";
		echo "jQuery( document ).ready( function( $ ) {
				if ( window.uorigindetected == null){
				   $('#monsterinsights-ublock-origin-error').show();
				   $('.monsterinsights-nav-tabs').hide();
				   $('.monsterinsights-nav-container').hide();
				   $('#monsterinsights-addon-heading').hide();
				   $('#monsterinsights-addons').hide();
				   $('#monsterinsights-reports').hide();
				}
			});";
		echo "\n</script>";
	}

	/**
	 * Load CSS from manifest.json
	 */
	public static function enqueue_script_specific_css( $js_file_path ) {
		if ( defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) ) {
			return;
		}

		$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
		$plugin_path  = plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE );

		if ( ! isset( self::$manifest_data[ $js_file_path ] ) ) {
			return;
		}

		$js_imports    = self::$manifest_data[ $js_file_path ]['imports'];
		$css_file_path = $plugin_path . $version_path . '/assets/vue/';

		// Add JS own CSS file.
		if ( isset( self::$manifest_data[ $js_file_path ]['css'] ) ) {
			self::add_js_own_css_files( self::$manifest_data[ $js_file_path ]['css'], $version_path );
		}

		// Loop through all imported js file of entry file.
		foreach ( $js_imports as $js_filename ) {
			// Check imported file available in manifest.json
			if ( ! isset( self::$manifest_data[ $js_filename ] ) ) {
				continue;
			}

			// Check imported js file has it's own css.
			if ( ! isset( self::$manifest_data[ $js_filename ]['css'] ) ) {
				continue;
			}

			$js_file_css = self::$manifest_data[ $js_filename ]['css'];

			// css must be array.
			if ( ! is_array( $js_file_css ) ) {
				continue;
			}

			// Loop to css files of a imported js file.
			foreach ( $js_file_css as $css_hash_name ) {
				if ( file_exists( $css_file_path . $css_hash_name ) ) {
					wp_enqueue_style(
						'monsterinsights-style-' . basename( $css_hash_name ),
						plugins_url( $version_path . '/assets/vue/' . $css_hash_name, MONSTERINSIGHTS_PLUGIN_FILE ),
						array(),
						monsterinsights_get_asset_version()
					);
				}
			}
		}
	}

	/**
	 * Add JS it's own CSS build file.
	 */
	private static function add_js_own_css_files( $css_files, $version_path ) {
		foreach ( $css_files as $css_filename ) {
			wp_enqueue_style(
				'monsterinsights-style-' . basename( $css_filename ),
				plugins_url( $version_path . '/assets/vue/' . $css_filename, MONSTERINSIGHTS_PLUGIN_FILE ),
				array(),
				monsterinsights_get_asset_version()
			);
		}
	}

	/**
	 * Get JS build file URL of a entry file.
	 *
	 * @return string
	 */
	public static function get_js_url( $path ) {
		if ( ! $path ) {
			return;
		}

		if ( defined( 'MONSTERINSIGHTS_LOCAL_JS_URL' ) && MONSTERINSIGHTS_LOCAL_JS_URL ) {
			return MONSTERINSIGHTS_LOCAL_JS_URL . $path;
		}

		// If the file is not available on manifest.
		if ( ! isset( self::$manifest_data[ $path ] ) ) {
			return;
		}

		$js_file      = self::$manifest_data[ $path ]['file'];
		$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';

		return plugins_url( $version_path . '/assets/vue/' . $js_file, MONSTERINSIGHTS_PLUGIN_FILE );
	}

	/**
	 * Fetch manifest.json data and store it to array for future use.
	 *
	 * @return void
	 */
	private function get_manifest_data() {
		$version_path  = monsterinsights_is_pro_version() ? 'pro' : 'lite';
		$plugin_path   = plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE );
		$manifest_path = $plugin_path . $version_path . '/assets/vue/manifest.json';

		// Return if manifest.json not exists.
		if ( ! file_exists( $manifest_path ) ) {
			return;
		}

		self::$manifest_data = json_decode( file_get_contents( $manifest_path ), true );
	}

	/**
	 * Fetch Vue 3 manifest.json data and store it to array for future use.
	 *
	 * @return void
	 */
	private function get_manifest_data_v3() {
		$version_path  = monsterinsights_is_pro_version() ? 'pro' : 'lite';
		$plugin_path   = plugin_dir_path( MONSTERINSIGHTS_PLUGIN_FILE );
		$manifest_path = $plugin_path . $version_path . '/assets/vue3/manifest.json';

		if ( ! file_exists( $manifest_path ) ) {
			return;
		}

		self::$manifest_data_v3 = json_decode( file_get_contents( $manifest_path ), true );
	}

	/**
	 * Determine if current admin page should load Vue 3 assets.
	 * Uses the `page` query arg (menu_slug from add_submenu_page) and allows filters for future modules.
	 *
	 * @return bool
	 */
	private function is_vue3_admin_page() {
		// Ensure we are on a MI admin screen first.
		$screen = function_exists( 'get_current_screen' ) ? get_current_screen() : false;
		if ( empty( $screen ) || empty( $screen->id ) || strpos( $screen->id, 'monsterinsights' ) === false ) {
			return false;
		}

		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
		if ( empty( $page ) ) {
			return false;
		}

		// Slugs that should be served by Vue 3. Start with Custom Views; extend via filter as modules migrate.
		$vue3_pages = apply_filters( 'monsterinsights_vue3_pages', array(
			'monsterinsights_custom_dashboard',
			'monsterinsights-custom-dashboards', // Support hyphenated plural version
		) );

		return in_array( $page, $vue3_pages, true );
	}

	/**
	 * Get Vue 3 entry and base URL from manifest for a given key.
	 *
	 * @param string $entry_key Manifest key (e.g., 'custom-dashboard').
	 * @return array [ base_url, entry_array ]
	 */
	private function get_vue3_entry( $entry_key ) {
		$version_path = monsterinsights_is_pro_version() ? 'pro' : 'lite';
		$base_url     = plugins_url( $version_path . '/assets/vue3/', MONSTERINSIGHTS_PLUGIN_FILE );
		$entry        = array();

		if ( isset( self::$manifest_data_v3[ $entry_key ] ) ) {
			$entry = self::$manifest_data_v3[ $entry_key ];
		} elseif ( isset( self::$manifest_data_v3[ 'src/' . $entry_key . '/main.js' ] ) ) {
			$entry = self::$manifest_data_v3[ 'src/' . $entry_key . '/main.js' ];
		}

		// Apply SCRIPT_DEBUG suffix pattern: use unminified version when debugging.
		// Manifest always contains .min.js paths, but we also build .js versions.
		if ( ! empty( $entry['file'] ) && defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
			$entry['file'] = str_replace( '.min.js', '.js', $entry['file'] );
		}

		return array( $base_url, $entry );
	}

	/**
	 * Check if Vue 3 dev server is enabled.
	 *
	 * @return bool
	 */
	private function is_vue3_dev() {
		$dev_url = $this->get_vue3_dev_url();
		return ! empty( $dev_url );
	}

	/**
	 * Get Vue 3 dev server base URL.
	 * Define MONSTERINSIGHTS_V3_DEV_URL in wp-config.php (e.g. http://localhost:5174)
	 *
	 * @return string
	 */
	private function get_vue3_dev_url() {
		if ( defined( 'MONSTERINSIGHTS_V3_DEV_URL' ) && MONSTERINSIGHTS_V3_DEV_URL ) {
			return MONSTERINSIGHTS_V3_DEV_URL;
		}
		return '';
	}

	/**
	 * Sanitization specific to each field.
	 *
	 * @param string $field The key of the field to sanitize.
	 * @param string $value The value of the field to sanitize.
	 *
	 * @return mixed The sanitized input.
	 */
	private function handle_sanitization( $field, $value ) {

		$value = wp_unslash( $value );

		// Textarea fields.
		$textarea_fields = array();

		if ( in_array( $field, $textarea_fields, true ) ) {
			if ( function_exists( 'sanitize_textarea_field' ) ) {
				return sanitize_textarea_field( $value );
			} else {
				return wp_kses( $value, array() );
			}
		}

		$array_value = $value;
		if ( is_array( $array_value ) ) {
			$value = $array_value;
			// Don't save empty values.
			foreach ( $value as $key => $item ) {
				if ( is_array( $item ) ) {
					$empty = true;
					foreach ( $item as $item_value ) {
						if ( ! empty( $item_value ) ) {
							$empty = false;
						}
					}
					if ( $empty ) {
						unset( $value[ $key ] );
					}
				}
			}
			// Reset array keys because JavaScript can't handle arrays with non-sequential keys.
			$value = array_values( $value );

			return $value;
		}
		return sanitize_text_field( $value );
	}

	/**
	 * Check if the CharitableWP notice should be shown.
	 */
	private function show_charitablewp_notice() {
		// Check if user has permission to show the notice.
		if ( ! current_user_can( 'monsterinsights_save_settings' ) ) {
			return false;
		}

		$installed_plugins = get_plugins();
		$plugin_path = 'charitable/charitable.php';

		if ( isset( $installed_plugins[$plugin_path] ) ) {
			return false;
		}

		return monsterinsights_get_option( 'show_charitable_notice', false );
	}
}

new MonsterInsights_Admin_Assets();
