tec.tickets_plus = tec.tickets_plus || {};

tec.tickets_plus.waitlist = tec.tickets_plus.waitlist || {};

(( $, obj ) => {
	obj.selectors = {
		waitlists: '.tec-tickets-plus-waitlist-container',
		submitBtn: '.tec-tickets-plus-waitlist-submit',
		nameField: '[name="tec-tickets-plus-waitlist[name]"',
		emailField: '[name="tec-tickets-plus-waitlist[email]"',
		innerWrap: '.tec-tickets-plus-waitlist-container__inner-wrap',
		successWrap: '.tec-tickets-plus-waitlist-container__success',
		whenEmpty: '[data-show-when="empty"]',
		whenInvalid: '[data-show-when="invalid"]',
		when: '[data-show-when]',
		waitlistId: '[name="tec-tickets-plus-waitlist[waitlist_id]"',
		nonce: '[name="tec-tickets-plus-waitlist[nonce]"',
		action: '[name="tec-tickets-plus-waitlist[action]"',
		hasError: 'tec-tickets-plus-waitlist-container--input--has-error',
	}

	obj.waitlistObjects = $( obj.selectors.waitlists );
	if ( ! obj.waitlistObjects.length ) {
		return;
	}

	/**
	 * Clear the URL from the unsubscribed query param.
	 *
	 * @since 6.2.0
	 * @returns {void}
	 */
	obj.clearUrl = () => {
		const url = new URL( window.location );
		url.searchParams.delete( 'unsubscribed' );
		history.replaceState( {}, '', url );
	};

	obj.clearUrl();

	obj.waitlistObjects.each( ( index ) => {
		const waitlist = $( obj.waitlistObjects[index] );
		const submit = waitlist.find( obj.selectors.submitBtn );

		const form = waitlist.closest( 'form' );
		if ( form.length ) {
			form.on( 'submit', ( e ) => {
				e.preventDefault();
			} );
		}

		// The name and email fields may or may not exists based on whether the user is logged in or not.
		// If they exists they are required though and should be validated in FE as well.
		const nameField = waitlist.find( obj.selectors.nameField );
		const emailField = waitlist.find( obj.selectors.emailField );

		const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

		/**
		 * Validate the fields in the form.
		 *
		 * @since 6.2.0
		 * @returns {boolean}
		 */
		const validateFields = () => {
			let hasErrors = false;

			if ( ! nameField.val() ) {
				nameField.nextAll( obj.selectors.whenEmpty ).show();
				nameField.addClass( obj.selectors.hasError );
				hasErrors = true;
			}

			const email = emailField.val();
			if ( ! email ) {
				emailField.nextAll( obj.selectors.whenEmpty ).show();
				emailField.addClass( obj.selectors.hasError );
				hasErrors = true;
			} else if ( ! emailRegex.test( email ) ) {
				emailField.nextAll( obj.selectors.whenInvalid ).show();
				emailField.addClass( obj.selectors.hasError );
				hasErrors = true;
			}

			submit.prop( 'disabled', hasErrors );

			return hasErrors;
		}

		/**
		 * Debounce function.
		 *
		 * @since 6.2.0
		 * @param {Function} func
		 * @param {number} delay
		 * @returns {Function}
		 */
		const debounce = (func, delay) => {
			let timer;
			return (...args) => {
				clearTimeout(timer);
				timer = setTimeout(() => func.apply(this, args), delay);
			};
		}

		submit.on( 'click', debounce( async ( e ) => {
			e.preventDefault();

			const waitlistId = waitlist.find( obj.selectors.waitlistId ).val();
			const nonce = waitlist.find( obj.selectors.nonce ).val();
			const action = waitlist.find( obj.selectors.action ).val();

			if ( ! ( waitlistId && nonce && action ) ) {
				// Serious issue, lets throw an exception.
				throw new Error( 'Missing required fields for waitlist submission.' );
			}

			const hasErrors = nameField.length ? validateFields() : false;

			if ( hasErrors ) {
				return;
			}

			// Disable before AJAX.
			submit.prop( 'disabled', true );

			const data = new FormData();
			data.append( 'action', action );
			data.append( 'waitlistId', waitlistId );
			data.append( 'nonce', nonce );
			data.append( 'name', nameField.length ? nameField.val() : '' );
			data.append( 'email', emailField.length ? emailField.val() : '' );

			try {
				const json = await tribe.ky.post( TribeTicketsPlus.ajaxurl, { body: data } ).json();

				if ( ! json?.success ) {
					console.error( 'Failed to submit waitlist form.', json );
					return false;
				}

				// Hide the form and show the success message.
				waitlist.find( obj.selectors.innerWrap ).hide();
				waitlist.find( obj.selectors.successWrap ).show();
			} catch( error ) {
				submit.prop( 'disabled', false );
				console.error( 'Failed to submit waitlist form.', error );
				return false;
			}
		}, 500 ) );

		if ( ! nameField.length ) {
			return;
		}

		nameField.on( 'input', () => {
			nameField.nextAll( obj.selectors.when ).hide();
			nameField.removeClass( obj.selectors.hasError );
		} );

		nameField.on( 'input', debounce( validateFields, 500 ) );

		// Validate when out of focus.
		nameField.on( 'blur', validateFields );

		emailField.on( 'input', () => {
			emailField.nextAll( obj.selectors.when ).hide();
			emailField.removeClass( obj.selectors.hasError );
		} );

		emailField.on( 'input', debounce( validateFields, 500 ) );

		// Validate when out of focus.
		emailField.on( 'blur', validateFields );
	} );
})(jQuery, tec.tickets_plus.waitlist);
