/* eslint-disable */
(function ($) {
	'use strict';

	var config = window.peachpayAuthnetConfig || {};
	var gatewayId = config.gatewayId || 'peachpay_authnet_card';
	var tokenCreatedAt = 0;
	var storedOpaqueData = null;
	var TOKEN_TTL_MS = 14 * 60 * 1000;
	var SCRIPT_STATUS_ATTR = 'data-peachpay-authnet-acceptui-status';

	function getElements() {
		return {
			form: document.querySelector('form.checkout'),
			button: document.querySelector('.pp-authnet-acceptui-button.AcceptUI'),
			dataDescriptor: document.getElementById('pp-authnet-data-descriptor'),
			dataValue: document.getElementById('pp-authnet-data-value'),
			status: document.querySelector('.pp-authnet-acceptui-status'),
			error: document.querySelector('.pp-authnet-error'),
		};
	}

	function ensureCheckoutHiddenField(form, id, name) {
		var field = document.getElementById(id);

		if (!field || !form.contains(field)) {
			field = document.createElement('input');
			field.type = 'hidden';
			field.id = id;
			field.name = name;
			form.appendChild(field);
		}

		field.disabled = false;
		if (!field.name) {
			field.name = name;
		}
		return field;
	}

	function showError(msg) {
		var els = getElements();
		if (els.error) {
			els.error.textContent = msg;
			els.error.style.display = 'block';
		}
	}

	function hideError() {
		var els = getElements();
		if (els.error) {
			els.error.textContent = '';
			els.error.style.display = 'none';
		}
	}

	function clearOpaqueData() {
		var els = getElements();
		if (els.dataDescriptor) els.dataDescriptor.value = '';
		if (els.dataValue) els.dataValue.value = '';
		tokenCreatedAt = 0;
		storedOpaqueData = null;
		if (els.status) {
			els.status.textContent = 'Your card details are collected securely by Authorize.net.';
		}
	}

	function isStoredTokenFresh() {
		return Boolean(
			storedOpaqueData &&
			storedOpaqueData.dataDescriptor &&
			storedOpaqueData.dataValue &&
			storedOpaqueData.createdAt &&
			Date.now() - storedOpaqueData.createdAt < TOKEN_TTL_MS
		);
	}

	function syncStoredTokenToCheckoutFields() {
		var els = getElements();

		if (!els.form || !isStoredTokenFresh()) {
			return false;
		}

		els.dataDescriptor = ensureCheckoutHiddenField(els.form, 'pp-authnet-data-descriptor', 'peachpay_authnet_data_descriptor');
		els.dataValue = ensureCheckoutHiddenField(els.form, 'pp-authnet-data-value', 'peachpay_authnet_data_value');

		els.dataDescriptor.value = storedOpaqueData.dataDescriptor;
		els.dataValue.value = storedOpaqueData.dataValue;
		els.dataDescriptor.disabled = false;
		els.dataValue.disabled = false;
		tokenCreatedAt = storedOpaqueData.createdAt;

		return true;
	}

	function storeOpaqueData(response) {
		var els = getElements();
		if (!response || !response.opaqueData) {
			showError('Card tokenization failed. Please try again.');
			return;
		}

		if (els.dataDescriptor) els.dataDescriptor.value = response.opaqueData.dataDescriptor;
		if (els.dataValue) els.dataValue.value = response.opaqueData.dataValue;
		tokenCreatedAt = Date.now();
		storedOpaqueData = {
			dataDescriptor: response.opaqueData.dataDescriptor,
			dataValue: response.opaqueData.dataValue,
			createdAt: tokenCreatedAt,
		};
		syncStoredTokenToCheckoutFields();
		if (els.status) {
			var last4 = response.encryptedCardData && response.encryptedCardData.cardNumber
				? ' ' + response.encryptedCardData.cardNumber
				: '';
			els.status.textContent = 'Card details entered.' + last4;
		}
		hideError();
	}

	function hasFreshToken() {
		var els = getElements();
		if (syncStoredTokenToCheckoutFields()) {
			return true;
		}

		return Boolean(
			els.dataDescriptor && els.dataDescriptor.value &&
			els.dataValue && els.dataValue.value &&
			tokenCreatedAt &&
			Date.now() - tokenCreatedAt < TOKEN_TTL_MS
		);
	}

	function hasCurrentCheckoutFieldToken() {
		var els = getElements();

		return Boolean(
			els.form &&
			els.dataDescriptor && els.form.contains(els.dataDescriptor) && els.dataDescriptor.value &&
			els.dataValue && els.form.contains(els.dataValue) && els.dataValue.value &&
			tokenCreatedAt &&
			Date.now() - tokenCreatedAt < TOKEN_TTL_MS
		);
	}

	function hasSubmissionToken() {
		return syncStoredTokenToCheckoutFields() || hasCurrentCheckoutFieldToken();
	}

	function showCheckoutError(message, wcCheckoutForm) {
		var $form = $('form.checkout');

		showError(message);

		if (wcCheckoutForm && typeof wcCheckoutForm.submit_error === 'function') {
			wcCheckoutForm.submit_error('<div class="woocommerce-error">' + message + '</div>');
		} else {
			$form.removeClass('processing');
			$form.unblock();
		}
	}

	function findAcceptUIScript(src) {
		var scripts = document.querySelectorAll('script.pp-authnet-acceptui-script');
		for (var i = 0; i < scripts.length; i++) {
			if (scripts[i].src === src || scripts[i].getAttribute('src') === src) {
				return scripts[i];
			}
		}
		return null;
	}

	function loadAcceptUIScript(forceReload) {
		var src = config.acceptSrc || '';
		var els = getElements();

		if (!els.button) {
			showError('Authorize.net payment button is missing. Please refresh the page.');
			return;
		}

		if (!src) {
			showError('Authorize.net hosted payment form URL is missing.');
			return;
		}

		var existingScript = findAcceptUIScript(src);
		if (existingScript && forceReload) {
			existingScript.parentNode.removeChild(existingScript);
			existingScript = null;
		}

		if (existingScript) {
			var status = existingScript.getAttribute(SCRIPT_STATUS_ATTR);
			if (status === 'loaded') {
				return;
			}

			if (status === 'error') {
				existingScript.parentNode.removeChild(existingScript);
			} else {
				existingScript.addEventListener('error', function () {
					showError('Authorize.net hosted payment form failed to load. Please refresh and try again.');
				}, { once: true });
				return;
			}
		}

		var script = document.createElement('script');
		script.type = 'text/javascript';
		script.src = src;
		script.async = true;
		script.className = 'pp-authnet-acceptui-script';
		script.setAttribute(SCRIPT_STATUS_ATTR, 'loading');
		script.onload = function () {
			script.setAttribute(SCRIPT_STATUS_ATTR, 'loaded');
			hideError();
		};
		script.onerror = function () {
			script.setAttribute(SCRIPT_STATUS_ATTR, 'error');
			showError('Authorize.net hosted payment form failed to load. Please refresh and try again.');
		};

		document.body.appendChild(script);
	}

	window.peachpayAuthnetClassicResponseHandler = function (response) {
		if (response.messages && response.messages.resultCode === 'Error') {
			clearOpaqueData();
			showError(
				response.messages.message && response.messages.message[0]
					? response.messages.message[0].text
					: 'Card tokenization failed. Please try again.'
			);
			return;
		}

		storeOpaqueData(response);
	};

	$('form.checkout').on('checkout_place_order_' + gatewayId, function (event, wcCheckoutForm) {
		hideError();

		var syncResult = syncStoredTokenToCheckoutFields();
		var fallbackResult = !syncResult && hasCurrentCheckoutFieldToken();
		var canSubmit = syncResult || fallbackResult;

		if (canSubmit) {
			return true;
		}

		var hadExpiredToken = Boolean(storedOpaqueData || tokenCreatedAt);
		clearOpaqueData();
		showCheckoutError(
			hadExpiredToken
				? 'Your card details expired. Please enter them again before placing the order.'
				: 'Please enter your card details before placing the order.',
			wcCheckoutForm
		);
		return false;
	});

	$(document.body).on('updated_checkout', function () {
		if (isStoredTokenFresh()) {
			syncStoredTokenToCheckoutFields();
		} else {
			clearOpaqueData();
		}
		hideError();
		loadAcceptUIScript(true);
	});

	$(document.body).on('checkout_error', function () {
		hideError();
	});

	$(document).on('change', 'input[name="payment_method"]', function () {
		if (this.value === gatewayId) {
			clearOpaqueData();
			hideError();
			loadAcceptUIScript();
		}
	});

	$(function () {
		loadAcceptUIScript();
	});
})(jQuery);
