( function( $ ) {
	let $button,
		buttonTextElement,
		installingText,
		installedText,
		errorText,
		activateText;

	/**
	 * Handles the installation of a WordPress plugin triggered by a UI interaction.
	 * Prevents the default action, initiates the plugin installation, and updates
	 * the button state and text to reflect the installation status.
	 *
	 * @param {Event} e The event object representing the click or interaction event
	 *                  that triggers the plugin installation.
	 * @return {void} Does not return a value. All actions are handled through side effects,
	 *                such as UI updates and plugin installation.
	 */
	function executePluginInstallation( e ) {
		e.preventDefault();

		if ( !window.wp || !window.wp.updates || !window.wp.updates.installPlugin ) {
			window.location.href = e.currentTarget.href;
			return;
		}

		$button = $( e.currentTarget );
		buttonTextElement = $button.children( '.wtv-promo-notice-button__text' );
		installingText = $button.data( 'installing' ) || 'Installing';
		installedText = $button.data( 'installed' ) || 'Installed';
		errorText = $button.data( 'error' ) || 'Error';
		activateText = $button.data( 'activate' ) || 'Activate';

		if ( $button.hasClass( 'updating-message' ) ) {
			return;
		}

		$button
			.addClass( 'updating-message' )
			.attr( 'aria-busy', 'true' )
			.prop( 'disabled', true );

		buttonTextElement.text( installingText );

		$( document ).on( 'wp-plugin-install-success', onInstallSuccess );
		$( document ).on( 'wp-plugin-install-error', onInstallError );

		window.wp.updates.installPlugin( {
			slug: $button.data( 'pluginSlug' ),
		} );
	}

	/**
	 * Handles the plugin installation error event, updates the button state, and displays the error message to the user.
	 *
	 * @param {JQuery.Event} _event - The event object representing the installation error event.
	 * @param {Object} response - The response object containing details about the installation error.
	 * @param {string} response.slug - The slug of the plugin associated with the error.
	 * @param {string} response.errorMessage - The error message associated with the installation failure.
	 * @return {void} This function does not return any value.
	 */
	function onInstallError(_event, response ) {
		if ( response && response.slug !== $button.data( 'pluginSlug' ) ) {
			return;
		}

		$( document ).off( 'wp-plugin-install-success', onInstallSuccess );
		$( document ).off( 'wp-plugin-install-error', onInstallError );

		$button
			.removeClass( 'updating-message' )
			.removeClass( 'wtv-promo-notice-button--ready' )
			.removeAttr( 'aria-busy' );

		buttonTextElement.text( errorText );

		alert( response.errorMessage );
	}

	/**
	 * Handles a successful plugin installation event by updating the UI and preparing the button for further actions.
	 *
	 * @param {JQuery.Event} _event - The event object triggered by the plugin installation success.
	 * @param {Object} response - The response object containing data related to the plugin installation.
	 * @param {string} response.slug - The slug of the installed plugin.
	 * @param {string} response.activateUrl - Optional URL to activate the installed plugin.
	 * @return {void} No return value.
	 */
	function onInstallSuccess(_event, response) {
		if ( response && response.slug !== $button.data( 'pluginSlug' ) ) {
			return;
		}

		$( document ).off( 'wp-plugin-install-success', onInstallSuccess );
		$( document ).off( 'wp-plugin-install-error', onInstallError );

		$button
			.removeClass( 'updating-message' )
			.removeClass( 'wtv-promo-notice-button--ready' )
			.removeAttr( 'aria-busy' )
			.prop( 'disabled', false );

		buttonTextElement.text( installedText );

		if ( typeof response.activateUrl === 'string' ) {
			setTimeout( function() {
				$button.attr( 'href', response.activateUrl );
				buttonTextElement.text( activateText );
			}, 1000 );
		}
	}

	/**
	 * Dismisses the promotional notice banner by sending an AJAX request to the server.
	 * The location where the notice is dismissed is determined
	 * based on the banner's data attributes or class.
	 *
	 * @param {JQuery.ClickEvent} e - The click event object representing the user's interaction with the notice.
	 *
	 * @return {void} This method does not return any value.
	 */
	function dismissPromoNotice( e ) {
		const $notice = $( e.currentTarget ).closest( '.wtv-promo-notice-banner' );
		const location = $notice.data( 'location' ) || ( $notice.hasClass( 'wtv-promo-notice-dashboard' ) ? 'dashboard' : 'other' );

		$.post( window.ajaxurl, {
			action: 'wetail_dismiss_promo_notice',
			location: location,
			nonce: $notice.data( 'nonce' ),
		} );
	}

	/**
	 * Toggles the visibility of the promo banner on the fly based on the Screen Options state.
	 * This allows the "Wetail Shipping banner toggle" in Screen Options to act as a real-time switch.
	 *
	 * @return {void}
	 */
	function handleScreenOptionToggle( event ) {
		const $banner = $( '.wtv-promo-notice-banner' );
		if ( ! $banner.length ) {
			return;
		}
		const isChecked = $( event.currentTarget ).is( ':checked' );
		if ( isChecked ) {
			$banner.removeClass( 'wtv-promo-notice-banner--hidden' );
		} else {
			$banner.addClass( 'wtv-promo-notice-banner--hidden' );
		}

		$.post( window.ajaxurl, {
			action: 'wetail_toggle_dashboard_widget',
			checked: isChecked,
			nonce: $banner.data( 'nonce' ),
		} );
	}

	/**
	 * Initializes event listeners for specific UI elements to handle plugin installation and promo notice dismissal.
	 *
	 * @return {void} This method does not return any value.
	 */
	function assign() {
		$( document )
			.on( 'change', '#wetail_shipping_toggle_widget-hide', handleScreenOptionToggle )
			.on( 'click', '.wtv-promo-notice-button.wtv-promo-notice-button--ready', executePluginInstallation )
			.on( 'click', '.wtv-promo-notice-banner .notice-dismiss', dismissPromoNotice );
	}


	/**
	 * Initializes the necessary parts or configurations.
	 *
	 * @return {void} Does not return a value.
	 */
	function initialize() {
		assign();
	}


	return {
		/**
		 * Call to init ourselves
		 */
		init: function() {
			if ( document.readyState === 'complete' ) {
				initialize();
			} else {
				window.addEventListener( 'load', function() {
					initialize();
				} );
			}
		},
	};
} )( jQuery.noConflict() ).init();
