<?php
// IMPORTANT: This plugin is dynamically updated - MODIFICATIONS WILL BE OVERWRITTEN

/**
 * Nutshell WP
 *  - Contains primary functionality - Nutshell script integrations
 */

// phpcs:disable WordPress.WP.EnqueuedResources.NonEnqueuedScript
// - Scripts are intentionally not output with enqueue functions
// - We don't want any WP or plugin functionality messing with these scripts - moving, combining, minifying, etc.

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

final class Nutshell_Analytics {

	const NUTSHELL_DOMAIN = 'https://loader.nutshell.com/';

	/**
	* Singleton pattern
	*  - This makes working with WP Hooks fairly nice
	*/
	private static $instance = null;
	public static function instance() {
		return is_null( self::$instance ) ? new self() : self::$instance;
	}
	private function __construct() {

		// Already instantiated, and new called on the class directly
		if ( ! is_null( self::$instance ) ) {
			$class = get_called_class();
			throw new Exception( $class . ' uses forced singleton pattern - call ' . $class . '::instance() instead to get existing instance.' );
		}

		self::$instance = $this;

		$this->init_hooks();
	}

	/**
	 * Get Nutshell ID from option table
	 */
	private $nutshell_instance_id = null;
	public function get_nutshell_instance_id() {
		if ( is_null( $this->nutshell_instance_id ) ) {
			// will return false if option doesn't exist
			$this->nutshell_instance_id = get_option( 'nutshell_instance_id' );

			// if there's no value, check for legacy MCFX ID
			if( empty( $this->nutshell_instance_id ) ) {
				$nutshell_instance_id = $this->get_legacy_mcfx_id();

				if( !empty( $nutshell_instance_id ) ) {
					$nutshell_instance_id = $this->standardize_nutshell_instance_id( $nutshell_instance_id );
					
					// update for future usage
					$this->set_nutshell_instance_id( $nutshell_instance_id );

					$this->nutshell_instance_id = $nutshell_instance_id;
				}
			}

			$this->nutshell_instance_id = $this->standardize_nutshell_instance_id( $this->nutshell_instance_id );
		}
		
		return $this->nutshell_instance_id;
	}

	/**
	 * Set nutshell ID to new value
	 */
	public function set_nutshell_instance_id( $nutshell_instance_id ) {
		$nutshell_instance_id = $this->standardize_nutshell_instance_id( $nutshell_instance_id );

		update_option( 'nutshell_instance_id', $nutshell_instance_id );

		$this->nutshell_instance_id = $nutshell_instance_id;
	}
	
	/**
	 * Get Nutshell auth token from options table
	 */
	private $nutshell_auth_token = null;
	public function get_nutshell_auth_token() {
		if ( is_null( $this->nutshell_auth_token ) ) {
			$this->nutshell_auth_token = get_option( 'nutshell_auth_token' );
		}
		return $this->nutshell_auth_token;
	}

	/**
	 * Set nutshell ID to new value
	 */
	public function set_nutshell_auth_token( $nutshell_auth_token ) {
		update_option( 'nutshell_auth_token', $nutshell_auth_token );
		$this->nutshell_auth_token = $nutshell_auth_token;
	}

	/**
	 * Get Nutshell domain from options table
	 */
	private $nutshell_domain = null;
	public function get_nutshell_domain() {
		if ( is_null( $this->nutshell_domain ) ) {
			$this->nutshell_domain = get_option( 'nutshell_domain' );

			if( !empty( $this->nutshell_domain ) ) {
				$this->nutshell_domain = $this->standardize_nutshell_domain( $this->nutshell_domain );
			}

			// if value is still null, use Nutshell's default domain
			if( empty( $this->nutshell_domain ) ) {
				$this->nutshell_domain = self::NUTSHELL_DOMAIN;
			}
		}

		return $this->nutshell_domain;
	}

	/**
	 * Set nutshell ID to new value
	 */
	public function set_nutshell_domain( $nutshell_domain ) {
		$nutshell_domain = $this->standardize_nutshell_domain( $nutshell_domain );

		// if no value, use Nutshell's default domain
		if( empty( $nutshell_domain ) ) {
			$nutshell_domain = self::NUTSHELL_DOMAIN;
		}

		update_option( 'nutshell_domain', $nutshell_domain );
		$this->nutshell_domain = $nutshell_domain;
	}

	/**
	 * Combine domain parts into full domain when saving settings
	 * Uses a static flag to ensure we only combine once per request
	 * 
	 * @param mixed $value The new value being saved (already sanitized by WordPress)
	 * @param mixed $old_value The old value
	 * @return mixed The value to save (unchanged)
	 */
	private static $domain_parts_combined = false;
	private static $sanitized_domain_parts = [];
	private static $filters_called = [];
	public function maybe_combine_domain_parts_on_save( $value, $old_value ) {
		// Store the sanitized value for the current field
		$current_filter = current_filter();
		if ( 'pre_update_option_nutshell_protocol' === $current_filter ) {
			self::$sanitized_domain_parts['protocol'] = $value;
			self::$filters_called[] = 'protocol';
		} elseif ( 'pre_update_option_nutshell_subdomain' === $current_filter ) {
			self::$sanitized_domain_parts['subdomain'] = $value;
			self::$filters_called[] = 'subdomain';
		} elseif ( 'pre_update_option_nutshell_root_domain' === $current_filter ) {
			self::$sanitized_domain_parts['root_domain'] = $value;
			self::$filters_called[] = 'root_domain';
		} elseif ( 'pre_update_option_nutshell_tld' === $current_filter ) {
			self::$sanitized_domain_parts['tld'] = $value;
			self::$filters_called[] = 'tld';
		}
		
		// Only combine once per request, and only if we're processing a form submission
		if ( self::$domain_parts_combined ) {
			return $value;
		}
		
		if ( ! is_admin() || empty( $_POST ) ) {
			return $value;
		}
		
		if ( ! current_user_can( 'manage_options' ) ) {
			return $value;
		}
		
		// Schedule combination to run after all filters have been called
		// Use a shutdown hook to ensure all pre_update_option filters have run
		if ( ! has_action( 'shutdown', [ $this, 'combine_domain_parts_on_shutdown' ] ) ) {
			add_action( 'shutdown', [ $this, 'combine_domain_parts_on_shutdown' ], 999 );
		}
		
		return $value;
	}

	/**
	 * Combine domain parts after all options have been processed
	 * This runs on shutdown to ensure all pre_update_option filters have completed
	 */
	public function combine_domain_parts_on_shutdown() {
		if ( self::$domain_parts_combined ) {
			return;
		}
		
		if ( ! is_admin() || empty( $_POST ) ) {
			return;
		}
		
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}
		
		// Use the already-sanitized values from WordPress, fallback to existing options for fields not being updated
		// Force HTTPS - always use https:// regardless of what was submitted
		$protocol = 'https://';
		$subdomain = isset( self::$sanitized_domain_parts['subdomain'] ) ? self::$sanitized_domain_parts['subdomain'] : get_option( 'nutshell_subdomain', 'loader' );
		$root_domain = isset( self::$sanitized_domain_parts['root_domain'] ) ? self::$sanitized_domain_parts['root_domain'] : get_option( 'nutshell_root_domain', 'nutshell' );
		$tld = isset( self::$sanitized_domain_parts['tld'] ) ? self::$sanitized_domain_parts['tld'] : get_option( 'nutshell_tld', 'com' );

		$full_domain = $protocol;
		
		if ( ! empty( $subdomain ) ) {
			$full_domain .= $subdomain . '.';
		}
		
		$full_domain .= $root_domain . '.' . $tld;

		$full_domain = $this->standardize_nutshell_domain( $full_domain );
		if ( ! empty( $full_domain ) ) {
			update_option( 'nutshell_domain', $full_domain, false );
			$this->nutshell_domain = $full_domain;
		}
		
		self::$domain_parts_combined = true;
	}	

	/**
	 * Get extra nutshell integrations list and whether they are enabled
	 */
	private $nutshell_integrations = null;
	private function get_nutshell_integrations() {
		if ( is_null( $this->nutshell_integrations ) ) {
			$integrations            = [];
			$available_integrations  = scandir( NUTSHELL_ANALYTICS_INTEGRATIONS_DIR );
			$configured_integrations = get_option( 'mcfx_integrations' );
			if ( empty( $configured_integrations ) || ! is_array( $configured_integrations ) ) {
				$configured_integrations = [];
			}

			// Parse integration files
			foreach ( $available_integrations as $filename ) {

				$integration_file = NUTSHELL_ANALYTICS_INTEGRATIONS_DIR . DIRECTORY_SEPARATOR . $filename;
				$filename         = basename( $integration_file );
				$file_parts       = explode( '.', $filename );
				$ext              = array_pop( $file_parts );

				// Only allow PHP files given that we will include them directly
				if ( 'php' !== $ext ) {
					continue;
				}

				$integration_data = get_file_data(
					$integration_file,
					[
						'name'        => 'Name',
						'description' => 'Description',
						'link'        => 'Link',
						'slug'        => 'Slug',
					]
				);

				// Automatic values and fallbacks
				$integration_data['enabled']  = 0;
				$integration_data['filepath'] = $integration_file;
				if ( empty( $integration_data['slug'] ) ) {
					$integration_data['slug'] = array_shift( $file_parts );
				}
				$file_slug = $integration_data['slug'];
				if ( empty( $integration_data['name'] ) ) {
					$integration_data['name'] = ucwords( preg_replace( '/[^0-9a-z]+/', ' ', $file_slug ) );
				}
				if ( empty( $integration_data['description'] ) ) {
					$integration_data['description'] = $filename;
				}

				$integrations[ $file_slug ] = $integration_data;
			}

			foreach ( $configured_integrations as $config_slug => $config ) {
				$integrations[ $config_slug ] = array_merge( $integrations[ $config_slug ], $config );
			}
			$this->nutshell_integrations = $integrations;
		}

		return $this->nutshell_integrations;
	}

	/**
	 * Check if this looks like a live site
	 * - based on database name
	 */
	public function is_live() {
		return ( false === stripos( DB_NAME, 'fxstage' ) && 'project' !== DB_NAME );
	}

	public function init_hooks() {

		// Admin notices
		add_action( 'admin_notices', [ $this, 'admin_notices' ] );

		// Admin settings page
		add_action( 'admin_init', [ $this, 'register_settings' ] );
		add_action( 'admin_menu', [ $this, 'add_menu' ] );

		// Output scripts - only if nutshell tracking is enabled
		$nutshell_script_active = get_option( 'mcfx_script_active' );
		if ( $nutshell_script_active ) {
			add_action( 'wp_head', [ $this, 'header_scripts' ] );
			add_action( 'wp_body_open', [ $this, 'body_scripts' ] );
			add_action( 'wp_footer', [ $this, 'footer_scripts' ] );
		}

		// Exclude JS from WP Rocket Optimizations
		add_filter( 'get_rocket_option_exclude_js', [ $this, 'wp_rocket_exclude_js' ] );
		add_filter( 'get_rocket_option_exclude_defer_js', [ $this, 'wp_rocket_exclude_js' ] );
		add_filter( 'get_rocket_option_exclude_inline_js', [ $this, 'wp_rocket_exclude_js' ] );
		add_filter( 'get_rocket_option_delay_js_exclusions', [ $this, 'wp_rocket_exclude_js' ] );

		add_filter( 'plugin_action_links_' . plugin_basename( NUTSHELL_ANALYTICS_PLUGIN_FILE ), [ $this, 'add_action_links' ] );

		add_action( 'pre_update_option_nutshell_instance_id', [ $this, 'standardize_nutshell_instance_id' ] );
		add_action( 'pre_update_option_nutshell_domain', [ $this, 'standardize_nutshell_domain' ] );
		
		// Combine domain parts into full domain before they are saved
		add_filter( 'pre_update_option_nutshell_protocol', [ $this, 'maybe_combine_domain_parts_on_save' ], 10, 2 );
		add_filter( 'pre_update_option_nutshell_subdomain', [ $this, 'maybe_combine_domain_parts_on_save' ], 10, 2 );
		add_filter( 'pre_update_option_nutshell_root_domain', [ $this, 'maybe_combine_domain_parts_on_save' ], 10, 2 );
		add_filter( 'pre_update_option_nutshell_tld', [ $this, 'maybe_combine_domain_parts_on_save' ], 10, 2 );
	}

	public function admin_notices() {

		$nutshell_instance_id   = $this->get_nutshell_instance_id();
		$nutshell_script_active = get_option( 'mcfx_script_active' );
		$nutshell_incomplete    = ( $nutshell_script_active && empty( $nutshell_instance_id ) );

		// Show an alert if:
		if (
			// Missing either Nutshell ID
			( $nutshell_incomplete )
			// and this is a live site
			&& $this->is_live()
			// and we're not on the settings page
			&& ! $this->is_nutshell_settings_page()
		) {
			?>
				<br/>
				<div class="notice notice-warning update-nag">
					<?php echo esc_html_e( 'Nutshell Analytics Plugin is not configured.', 'nutshell' ); ?>
					<a href='<?php echo esc_html( admin_url( 'options-general.php?page=nutshell-analytics-settings' ) ); ?>'>
						<?php esc_html_e( 'Click here to configure.', 'nutshell' ); ?>
					</a>
				</div>
			<?php
		}
	}

	/**
	 * Check if current admin screen is nutshell settings page
	 */
	public function is_nutshell_settings_page() {
		$admin_screen = get_current_screen();
		return ( 'settings_page_nutshell-analytics-settings' === $admin_screen->base );
	}

	/**
	 * Register settings fields
	 */
	public function register_settings() {
		register_setting( 'mcfx_wp_settings', 'custom_mcfx_config' );
		register_setting( 'mcfx_wp_settings', 'mcfx_id' );
		register_setting(
			'mcfx_wp_settings',
			'mcfx_integrations',
			[
				'type'    => 'array',
				'default' => [],
			]
		);
		register_setting( 'mcfx_wp_settings', 'mcfx_script_active', [ 'default' => 1 ] );

		// new settings starting with 3.0.0
		register_setting( 'mcfx_wp_settings', 'nutshell_instance_id' ); // legacy MCFX ID will pre-populate this field
		register_setting( 'mcfx_wp_settings', 'nutshell_auth_token' );
		register_setting( 'mcfx_wp_settings', 'nutshell_domain' );
		
		// domain parts (these get combined into nutshell_domain on save)
		register_setting( 
			'mcfx_wp_settings', 
			'nutshell_protocol',
			[
				'type'              => 'string',
				'sanitize_callback' => [ $this, 'sanitize_protocol' ],
			]
		);
		register_setting( 
			'mcfx_wp_settings', 
			'nutshell_subdomain',
			[
				'type'              => 'string',
				'sanitize_callback' => [ $this, 'sanitize_subdomain' ],
			]
		);
		register_setting( 
			'mcfx_wp_settings', 
			'nutshell_root_domain',
			[
				'type'              => 'string',
				'sanitize_callback' => [ $this, 'sanitize_root_domain' ],
			]
		);
		register_setting( 
			'mcfx_wp_settings', 
			'nutshell_tld',
			[
				'type'              => 'string',
				'sanitize_callback' => [ $this, 'sanitize_tld_required' ],
			]
		);
	}

	/**
	 * Nutshell Settings Page
	 */
	public function add_menu() {
		add_submenu_page(
			'options-general.php',
			'Nutshell Settings',
			'Nutshell Settings',
			'manage_options',
			'nutshell-analytics-settings',
			[ $this, 'settings_page' ]
		);
	}
	public function settings_page() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'nutshell' ) );
		}
		
		require NUTSHELL_ANALYTICS_ADMIN_TEMPLATES_DIR . DIRECTORY_SEPARATOR . 'nutshell-analytics-settings.php';
	}

	/**
	 * Output scripts in header
	 */
	public function header_scripts() {
		// used in require template
		$nutshell_instance_id = $this->get_nutshell_instance_id();

		// should we use new bootloader script?
		if( $this->use_bootloader_script() ) {

			// used in require template
			$nutshell_auth_token = $this->get_nutshell_auth_token();
			$nutshell_domain = $this->get_nutshell_domain();
			
			ob_start();
			require NUTSHELL_ANALYTICS_FRONTEND_TEMPLATES_DIR . DIRECTORY_SEPARATOR . 'scripts-head-bootloader.php';
			$output = ob_get_clean();
			// Remove blank lines
			$output = preg_replace( "/(^|\n)\s*($|\n)+/", '$1', $output );

			// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
			// All variables in the template are already properly escaped with esc_url(), esc_js(), etc.
			// wp_kses was causing issues on wp.org where script tags with src attributes were being stripped
			echo $output;
			// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped

		// otherwise, use legacy MCFX script
		} else {
			ob_start();
			require NUTSHELL_ANALYTICS_FRONTEND_TEMPLATES_DIR . DIRECTORY_SEPARATOR . 'scripts-head.php';
			$output = ob_get_clean();
			// Remove blank lines
			$output = preg_replace( "/(^|\n)\s*($|\n)+/", '$1', $output );

			// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
			// All variables in the template are already properly escaped
			echo $output;
			// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
		}
	}

	/**
	 * Output scripts in body
	 * - This outputs the target div element that Nutshell's bootstrap script needs to initialize
	 * - Must be in body, not head, for semantic HTML
	 */
	public function body_scripts() {
		// Only output if using new bootloader script
		if( ! $this->use_bootloader_script() ) {
			return;
		}

		// used in require template
		$nutshell_instance_id = $this->get_nutshell_instance_id();

		ob_start();
		require NUTSHELL_ANALYTICS_FRONTEND_TEMPLATES_DIR . DIRECTORY_SEPARATOR . 'scripts-body-bootloader.php';
		$output = ob_get_clean();
		// Remove blank lines
		$output = preg_replace( "/(^|\n)\s*($|\n)+/", '$1', $output );

		// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
		// All variables in the template are already properly escaped with esc_attr()
		echo $output;
		// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
	}

	/**
	 * Output scripts in footer
	 */
	public function footer_scripts() {

		ob_start();
		$integrations = $this->get_nutshell_integrations();
		if ( ! empty( $integrations ) ) {
			require NUTSHELL_ANALYTICS_FRONTEND_TEMPLATES_DIR . DIRECTORY_SEPARATOR . 'scripts-integrations.php';
		}

		$output = ob_get_clean();
		// Remove blank lines
		$output = preg_replace( "/(^|\n)\s*($|\n)+/", '$1', $output );

		// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
		// This is the contents of included files that are escaped within each file
		echo $output;
		// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
	}

	/**
	 * Exclude JS from WP Rocket optimizations
	 */
	public function wp_rocket_exclude_js( $exclude ) {
		if ( empty( $exclude ) ) {
			$exclude = [];
		}
		$exclude[] = 'marketingcloudfx';
		$exclude[] = 'mcfx';
		$exclude[] = 'nutshell';
		$exclude[] = 'nlcdn.com';
		$exclude[] = 'nutsheller';
		$exclude[] = '(.*)mcfx.js';
		return array_unique( $exclude );
	}

	/**
	 * Add link to Plugins page for admin to go directly to settings page
	 */
	public function add_action_links( $actions ) {
		$actions['settings'] = sprintf(
			'<a href="%s">%s</a>',
			admin_url( 'options-general.php?page=nutshell-analytics-settings' ),
			'Settings',
		);

		return $actions;
	}

	/**
	 * Get legacy MCFX ID from options table
	 * 
	 * Starting with 3.0.0, we load Nutshell's bootloader script. The instance ID matches the Nutshell ID (minus the 
	 * 'ns-' prefix). We want to use the Nutshell ID moving forward and update the correct option for future usage
	 */
	private function get_legacy_mcfx_id() {
		return get_option( 'mcfx_id' );
	}	

	/**
	 * Helper function to standardize Nutshell instance ID by removing legacy "ns-" prefix
	 */
	public function standardize_nutshell_instance_id( $nutshell_instance_id ) {
		if ( is_string( $nutshell_instance_id ) && stripos( $nutshell_instance_id, 'ns-' ) === 0 ) {
			$nutshell_instance_id = substr( $nutshell_instance_id, 3 );
		}

		return $nutshell_instance_id;
	}

	/**
	 * Helper function to standardize Nutshell domain URLs
	 */
	public function standardize_nutshell_domain( $nutshell_domain ) {
		if ( empty( $nutshell_domain ) || ! is_string( $nutshell_domain ) ) {
			return '';
		}
		
		return sanitize_url( $nutshell_domain, [ 'https', 'http' ] );
	}

	public function sanitize_protocol( $protocol ) {
		// Force HTTPS - always return https:// regardless of input
		return 'https://';
	}

	/**
	 * Sanitize subdomain (required field)
	 * Only allow alphanumeric, hyphens, and underscores
	 */
	public function sanitize_subdomain( $subdomain ) {
		$subdomain = preg_replace( '/[^a-zA-Z0-9\-_]/', '', $subdomain );
		$subdomain = strtolower( $subdomain );
		
		if ( empty( $subdomain ) ) {
			add_settings_error(
				'nutshell_subdomain',
				'nutshell_subdomain_required',
				__( 'Subdomain is required and cannot be empty.', 'nutshell' ),
				'error'
			);
			return get_option( 'nutshell_subdomain', 'loader' );
		}
		
		return $subdomain;
	}


	/**
	 * Sanitize root domain (required field)
	 * Only allow alphanumeric, hyphens, and underscores
	 * If input contains a dot (e.g., "domainname.com"), remove everything after the dot
	 */
	public function sanitize_root_domain( $root_domain ) {
		$root_domain = strtolower( $root_domain );
		
		// If input contains a dot, remove everything after the first dot
		$dot_position = strpos( $root_domain, '.' );
		if ( $dot_position !== false ) {
			$root_domain = substr( $root_domain, 0, $dot_position );
		}
		
		$common_tlds = [ '.com', '.net', '.org', '.io', '.co', '.us', '.uk', '.ca' ];
		foreach ( $common_tlds as $tld ) {
			if ( substr( $root_domain, -strlen( $tld ) ) === $tld ) {
				$root_domain = substr( $root_domain, 0, -strlen( $tld ) );
				break;
			}
		}
		
		$root_domain = preg_replace( '/[^a-zA-Z0-9\-_]/', '', $root_domain );
		
		if ( empty( $root_domain ) ) {
			add_settings_error(
				'nutshell_root_domain',
				'nutshell_root_domain_required',
				__( 'Root domain is required and cannot be empty.', 'nutshell' ),
				'error'
			);
			return get_option( 'nutshell_root_domain', 'nutshell' );
		}
		
		return $root_domain;
	}



	/**
	 * Sanitize TLD (top-level domain) - required field
	 * Only allow alphanumeric, dots, and hyphens (no leading dot)
	 * If input contains a slash (e.g., ".com/test"), remove everything after the slash
	 */
	public function sanitize_tld_required( $tld ) {
		$tld = ltrim( $tld, '.' );
		
		// If input contains a slash, remove everything after the slash
		$slash_position = strpos( $tld, '/' );
		if ( $slash_position !== false ) {
			$tld = substr( $tld, 0, $slash_position );
		}
		
		$tld = preg_replace( '/[^a-zA-Z0-9\.\-]/', '', $tld );
		
		$tld = strtolower( $tld );
		
		if ( empty( $tld ) ) {
			add_settings_error(
				'nutshell_tld',
				'nutshell_tld_required',
				__( 'TLD (top-level domain) is required and cannot be empty.', 'nutshell' ),
				'error'
			);
			return get_option( 'nutshell_tld', 'com' );
		}
		
		return $tld;
	}


	/**
	 * Should we use new bootloader script?
	 * 
	 * If either account ID or auth token are missing, do not use new bootloader script
	 */
	public function use_bootloader_script() {
		$nutshell_instance_id = $this->get_nutshell_instance_id();
		$nutshell_auth_token = $this->get_nutshell_auth_token();

		return ( ! empty( $nutshell_instance_id ) && ! empty( $nutshell_auth_token ) );
	}		
}

/**
 * Returns the main instance of Nutshell_Analytics to prevent the need to use globals.
 */
function nutshell_analytics() {
	// Only check for the version in the plugins folder. If the older mu-plugin version exists, we still want to run
    // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals
	// - we are not calling our own custom action, but rather an existing WP action
	if ( in_array( 'marketingcloudfx-wp/marketingcloudfx-wp.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ), true ) ) {
        // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals
		// Inform the user that the two plugins can't run simultaneously
		add_action(
			'admin_notices',
			function() {
				?>
				<div class="notice notice-warning update-nag">
					<?php echo esc_html_e( '"Nutshell Analytics" is superseded by "WebFX Core Services & RCFX - RevenueCloudFX" and will not run while it\'s active. You can safely deactivate the "Nutshell Analytics" plugin without impacting tracking to remove this message.', 'nutshell' ); ?>
				</div>
				<?php
			},
			3
		);
		// If requesting the settings page from the link in the plugin description, redirect to the superseding plugin's settings page
		add_action(
			'admin_init',
			function() {
				global $pagenow;
                // phpcs:disable WordPress.Security.NonceVerification.Recommended
				//  - This is from clicking a menu item, no nonce required
				if ( 'options-general.php' === $pagenow && 'nutshell-analytics-settings' === $_GET['page'] ) {
                    // phpcs:enable WordPress.Security.NonceVerification.Recommended
					header( 'Location: ' . admin_url( 'options-general.php?page=mcfx-wp-settings' ) );
					die();
				}
			}
		);
		// Add the settings page to avoid an error about the page not existing
		add_action(
			'admin_menu',
			function() {
				add_submenu_page(
					'options-general.php',
					'Nutshell Settings',
					'Nutshell Settings',
					'manage_options',
					'nutshell-analytics-settings',
					function() {}
				);
			}
		);
		// Hide the settings page from the menu to avoid clutter/confusion
		add_filter(
			'submenu_file',
			function( $submenu_file ) {
				remove_submenu_page( 'options-general.php', 'nutshell-analytics-settings' );
				return $submenu_file;
			}
		);
		return;
	}
	return Nutshell_Analytics::instance();
}
add_action( 'plugins_loaded', 'nutshell_analytics' );

// IMPORTANT: This plugin is dynamically updated - MODIFICATIONS WILL BE OVERWRITTEN
