/**
 * Checkout phone-verification widget behaviour.
 *
 * Runs on both classic and block checkout. Classic renders its own code field
 * and "Send code" button (see templates/frontend/checkout-otp-classic.php);
 * block checkout's code field comes from the Additional Checkout Fields API
 * instead, so this script locates it defensively rather than assuming a fixed
 * id — its rendered attributes come from compiled React this plugin does not
 * control. Either way, the phone number itself is read from checkout's own
 * phone field, never from a field this script owns.
 */
( function () {
	'use strict';

	var config = window.textTangoCheckoutOtp || {};
	var strings = config.i18n || {};
	var length = parseInt( config.length, 10 ) || 6;

	/**
	 * POST to admin-ajax and resolve with the parsed payload.
	 *
	 * @param {string} action Ajax action name.
	 * @param {Object} data   Extra fields to send.
	 * @return {Promise<Object>} Resolves on success, rejects with a message.
	 */
	function request( action, data ) {
		var body = new window.FormData();

		body.append( 'action', action );
		body.append( 'nonce', config.nonce || '' );

		Object.keys( data || {} ).forEach( function ( key ) {
			body.append( key, data[ key ] );
		} );

		return window
			.fetch( config.ajaxUrl, {
				method: 'POST',
				credentials: 'same-origin',
				body: body,
			} )
			.then( function ( response ) {
				return response.json().catch( function () {
					throw new Error( strings.genericError );
				} );
			} )
			.then( function ( payload ) {
				if ( ! payload || ! payload.success ) {
					throw new Error(
						( payload && payload.data && payload.data.message ) ||
							strings.genericError
					);
				}

				return payload.data || {};
			} );
	}

	/**
	 * The phone number checkout currently has entered.
	 *
	 * `autocomplete="tel"` is present on both classic's `#billing_phone` and
	 * block checkout's own phone field, so it is the one selector that works
	 * for both without knowing either field's generated id.
	 *
	 * @return {?HTMLInputElement}
	 */
	function findPhoneField() {
		var field = document.querySelector(
			'form.woocommerce-checkout input[autocomplete="tel"], .wc-block-checkout input[autocomplete="tel"]'
		);

		if ( ! field ) {
			// eslint-disable-next-line no-console
			console.warn(
				'TextTango: could not find the checkout phone field; phone verification is unavailable on this page.'
			);
		}

		return field;
	}

	/**
	 * The verification-code field, on whichever checkout rendered it.
	 *
	 * Classic checkout's copy carries `data-texttango-checkout-otp-code`
	 * (see the template). Block checkout's copy comes from the Additional
	 * Checkout Fields API and carries the field id as its `name`, but not
	 * necessarily as its `id` — matched by a `name*=` attribute selector
	 * rather than an exact id for that reason.
	 *
	 * @return {?HTMLInputElement}
	 */
	function findCodeField() {
		var field = document.querySelector( '[data-texttango-checkout-otp-code]' );

		if ( field ) {
			return field;
		}

		field = document.querySelector(
			'input[name*="checkout_otp_code"], input[id*="checkout_otp_code"]'
		);

		if ( ! field ) {
			// eslint-disable-next-line no-console
			console.warn(
				'TextTango: could not find the checkout verification-code field.'
			);
		}

		return field;
	}

	/**
	 * Show a status message near the code field, coloured by outcome.
	 *
	 * @param {string}  text    Message to show.
	 * @param {boolean} isError Whether it reports a failure.
	 */
	function say( text, isError ) {
		var messageEl = document.querySelector(
			'[data-texttango-checkout-otp-message]'
		);

		if ( ! messageEl ) {
			return;
		}

		messageEl.textContent = text;
		messageEl.classList.remove( 'tt-text-red-700', 'tt-text-emerald-700' );
		messageEl.classList.add(
			'tt-font-medium',
			isError ? 'tt-text-red-700' : 'tt-text-emerald-700'
		);
	}

	/**
	 * Ask for a code, sent to whatever the phone field currently holds.
	 *
	 * @param {HTMLElement} button Button that triggered the request.
	 */
	function requestCode( button ) {
		var phoneField = findPhoneField();
		var phone = phoneField ? phoneField.value.trim() : '';

		if ( ! phone ) {
			say( strings.needPhone, true );
			return;
		}

		var original = button ? button.textContent : '';

		if ( button ) {
			button.disabled = true;
			button.textContent = strings.sending;
		}

		request( 'texttango_checkout_otp_request', { phone: phone } )
			.then( function ( data ) {
				say( data.message, false );

				if ( button ) {
					button.textContent = strings.resend;
				}
			} )
			.catch( function ( error ) {
				say( error.message, true );

				if ( button ) {
					button.textContent = original;
				}
			} )
			.finally( function () {
				if ( button ) {
					button.disabled = false;
				}
			} );
	}

	/**
	 * Verify whatever code is currently in the code field.
	 */
	function verifyCode() {
		var phoneField = findPhoneField();
		var codeField = findCodeField();
		var phone = phoneField ? phoneField.value.trim() : '';
		var code = codeField ? codeField.value.trim() : '';

		if ( ! phone || ! code ) {
			return;
		}

		say( strings.verifying, false );

		request( 'texttango_checkout_otp_verify', { phone: phone, code: code } )
			.then( function ( data ) {
				say( data.message || strings.verified, false );
			} )
			.catch( function ( error ) {
				say( error.message, true );

				if ( codeField ) {
					codeField.value = '';
					codeField.focus();
				}
			} );
	}

	document.addEventListener( 'click', function ( event ) {
		var button = event.target.closest(
			'[data-texttango-checkout-otp-action="request"]'
		);

		if ( ! button ) {
			return;
		}

		event.preventDefault();
		requestCode( button );
	} );

	/*
	 * No separate "Verify" button: the code auto-submits once it reaches its
	 * full length, the same way most OTP inputs behave. This also sidesteps
	 * having to inject anything extra into block checkout's React-rendered
	 * code field, which only a click-triggered listener like this one can
	 * safely attach to from outside.
	 */
	document.addEventListener( 'input', function ( event ) {
		var codeField = findCodeField();

		if ( ! codeField || event.target !== codeField ) {
			return;
		}

		if ( codeField.value.trim().length >= length ) {
			verifyCode();
		}
	} );
} )();
