/**
 * 2-Factor Authentication – AJAX login flow (no page reload for 2FA step)
 */
(function() {
	'use strict';

	const config = window.wpps2faConfig || {};
	if (!config.ajaxUrl || !config.loginNonce) return;

	var loginForm = null;
	var twoFaStep = null;
	var currentToken = '';
	var currentRedirectTo = '';

	function get2FAViewportWidthTarget(form) {
		return document.getElementById('login') || (form && form.parentElement) || null;
	}

	function set2FAStepWideViewport(form, on) {
		var c = get2FAViewportWidthTarget(form);
		if (c) {
			c.classList.toggle('wpps-2fa-step-active', !!on);
		}
	}

	/**
	 * Prefer the form that contains the 2FA step (WooCommerce), then core selectors.
	 */
	function findLoginForm(stepEl) {
		var byId = document.getElementById('loginform');
		if (byId) return byId;
		if (stepEl && typeof stepEl.closest === 'function') {
			var inner = stepEl.closest('form');
			if (inner) return inner;
		}
		return document.querySelector('form.woocommerce-form-login');
	}

	function formatCredentialErrorForDisplay(msg) {
		if (!msg) return msg;
		var prefix = config.strings && config.strings.credentialErrorPrefix
			? String(config.strings.credentialErrorPrefix).trim()
			: '';
		var isWpLoginShell = document.body.classList.contains('login')
			&& loginForm && loginForm.id === 'loginform';
		if (!isWpLoginShell || !prefix) return msg;
		if (msg.indexOf(prefix) === 0) return msg;
		return prefix + ' ' + msg;
	}

	function setHintAndPlaceholder(mode, codeHint, codeInput) {
		if (!codeHint) codeHint = document.getElementById('wpps-2fa-code-hint');
		if (!codeInput) codeInput = document.getElementById('wpps_2fa_code');
		var fullpageHint = document.getElementById('wpps-2fa-code-hint-fullpage');
		var hintEl = codeHint || fullpageHint;
		var msg = '';
		var placeholder = 'XXXXXX';
		if (mode === 'backup') {
			msg = config.strings?.backupCodeHint || 'Enter one of your 8-character backup codes.';
			placeholder = 'XXXXXXXX';
		} else if (mode === 'authenticator') {
			msg = config.strings?.authenticatorHint || 'Enter the 6-digit code from your authenticator app.';
			placeholder = 'XXXXXX';
		} else {
			msg = config.strings?.emailCodeHintAbove || 'Enter the 8-digit code we sent to your email below.';
			placeholder = 'XXXXXXXX';
		}
		if (hintEl) { hintEl.textContent = msg; hintEl.style.display = ''; }
		if (codeInput) {
			codeInput.placeholder = placeholder;
			codeInput.maxLength = mode === 'backup' ? 8 : (mode === 'authenticator' ? 6 : 8);
		}
	}

	/**
	 * Credential / lockout notices from Login ID Type, Limit Login Attempts, etc. are often
	 * rendered outside #loginform (siblings under #login). Hiding the form alone leaves them
	 * visible beside the 2FA step — hide every relevant node (not just querySelector's first).
	 */
	function hideLoginPageNotices() {
		document.querySelectorAll(
			'#login #login_error, #login #login-message, #login #login_message, #login > .message, #login .notice'
		).forEach(function(el) {
			if (el.closest('.wpps-2fa-step')) {
				return;
			}
			el.setAttribute('data-wpps-2fa-hidden-notice', '1');
			el.style.display = 'none';
		});
	}

	function restoreLoginPageNotices() {
		document.querySelectorAll('[data-wpps-2fa-hidden-notice="1"]').forEach(function(el) {
			el.removeAttribute('data-wpps-2fa-hidden-notice');
			el.style.display = '';
		});
	}

	function initAjaxLoginFlow() {
		twoFaStep = document.getElementById('wpps-2fa-step');
		if (!twoFaStep) return;

		loginForm = findLoginForm(twoFaStep);
		if (!loginForm) return;

		// WooCommerce storefront login: native POST → wp_loaded redirect (module.php). Do not rely only on localized isWoo.
		var isWooCommerceLoginForm =
			!!config.isWoo ||
			(loginForm.classList && loginForm.classList.contains('woocommerce-form-login'));
		if (isWooCommerceLoginForm) {
			twoFaStep.style.display = 'none';
			return;
		}

		try {
			if (loginForm.parentNode) {
				loginForm.parentNode.insertBefore(twoFaStep, loginForm.nextSibling);
			}
		} catch (err) {
			if (typeof console !== 'undefined' && console.warn) {
				console.warn('WP Powersuite 2FA: could not place 2FA step in DOM.', err);
			}
			return;
		}

		twoFaStep.style.display = 'none';

		loginForm.addEventListener('submit', function(e) {
			e.preventDefault();
			submitLogin();
			return false;
		});

		function submitLogin() {
			var logInput = loginForm.querySelector('input[name="log"]')
				|| loginForm.querySelector('input[name="username"]');
			var pwdInput = loginForm.querySelector('input[name="pwd"]')
				|| loginForm.querySelector('input[name="password"]');
			const log = (logInput && logInput.value) ? logInput.value : '';
			const pwd = (pwdInput && pwdInput.value) ? pwdInput.value : '';

			if (!log || !pwd) {
				showLoginError(config.strings?.emptyFields || 'Please enter username and password.');
				return;
			}

			setLoading(loginForm, true);
			hideError();

			// Include every field in the real login form (Turnstile, reCAPTCHA, Simple CAPTCHA,
			// testcookie, redirect_to) — do not only POST log/pwd to admin-ajax; captcha modules
			// validate tokens on the same authenticate hook as 2FA.
			const formData = new FormData(loginForm);
			formData.set('action', 'wpps_2fa_login');
			formData.set('_wpnonce', config.loginNonce);

			fetch(config.ajaxUrl, {
				method: 'POST',
				body: formData,
				credentials: 'same-origin'
			})
				.then(function(r) { return r.json(); })
				.then(function(data) {
					setLoading(loginForm, false);
					if (data.success && data.data) {
						if (data.data.requires_2fa && data.data.token) {
							currentToken = data.data.token;
							currentRedirectTo = data.data.redirect_to || '';
							show2FAStep(data.data);
						} else if (data.data.redirect) {
							window.location.href = data.data.redirect;
						}
					} else {
						showLoginError(
							data.data?.message || config.strings?.loginError || 'Invalid username or password.'
						);
					}
				})
				.catch(function() {
					setLoading(loginForm, false);
					showLoginError(config.strings?.requestError || 'Request failed. Please try again.');
				});
		}

		function show2FAStep(payload) {
			payload = payload || {};
			var token = payload.token || '';
			var redirectTo = payload.redirect_to || '';
			var method = payload.method || 'email';
			var canSwitch = payload.can_switch;
			var otherMethod = payload.other_method;
			hideLoginPageNotices();
			loginForm.style.display = 'none';
			twoFaStep.style.display = 'block';
			set2FAStepWideViewport(loginForm, true);
			update2FAStepUI(token, redirectTo, method, canSwitch, otherMethod);

			var verifyForm = document.getElementById('wpps-2fa-verify-form');
			if (verifyForm && !verifyForm.dataset.bound) {
				verifyForm.dataset.bound = '1';
				verifyForm.addEventListener('submit', handleVerifySubmit);
			}

			var resendBtn = document.getElementById('wpps-2fa-resend');
			if (resendBtn && !resendBtn.dataset.bound) {
				resendBtn.dataset.bound = '1';
				resendBtn.addEventListener('click', handleResend);
			}

			const backLink = document.getElementById('wpps-2fa-back');
			if (backLink && !backLink.dataset.bound) {
				backLink.dataset.bound = '1';
				backLink.addEventListener('click', function(e) {
					if (config.cancelUrl) {
						e.preventDefault();
						window.location.href = config.cancelUrl;
						return;
					}
					e.preventDefault();
					showLoginStep();
				});
			}

			var switchBtn = document.getElementById('wpps-2fa-switch-method-btn');
			if (switchBtn && !switchBtn.dataset.bound) {
				switchBtn.dataset.bound = '1';
				switchBtn.addEventListener('click', function(e) {
					e.preventDefault();
					handleSwitchLoginMethod();
				});
			}
		}

		function update2FAStepUI(token, redirectTo, method, canSwitch, otherMethod) {
			method = method || 'email';
			hideLoginPageNotices();
			document.querySelectorAll('.woocommerce-info, .woocommerce-message, .woocommerce-error').forEach(function(el) {
				el.setAttribute('data-wpps-2fa-hidden-notice', '1');
				el.style.display = 'none';
			});
			var codeHint = document.getElementById('wpps-2fa-code-hint');
			var codeLabel = document.getElementById('wpps_2fa_code_label');
			var codeInput = document.getElementById('wpps_2fa_code');
			var primaryActions = document.getElementById('wpps-2fa-primary-actions');
			if (primaryActions) {
				if (method === 'email') primaryActions.classList.add('wpps-2fa-primary-actions--email');
				else primaryActions.classList.remove('wpps-2fa-primary-actions--email');
			}
			var resendRow = primaryActions ? primaryActions.querySelector('.wpps-2fa-resend-wrap') : null;
			if (resendRow) resendRow.style.display = method === 'authenticator' ? 'none' : '';
			var backupBtnWrap = document.getElementById('wpps-2fa-backup-btn-wrap');
			var switchBtnWrap = document.getElementById('wpps-2fa-switch-btn-wrap');
			var switchBtn = document.getElementById('wpps-2fa-switch-method-btn');
			if (codeLabel) codeLabel.textContent = config.strings?.verificationCodeLabel || 'Verification Code';
			setHintAndPlaceholder(method, codeHint, codeInput);
			if (codeInput) {
				codeInput.value = '';
				codeInput.dataset.mode = method === 'authenticator' ? 'authenticator' : 'email';
			}
			var backupShown = method === 'authenticator';
			if (backupBtnWrap) backupBtnWrap.style.display = backupShown ? '' : 'none';
			var switchShown = !!(canSwitch && otherMethod);
			if (switchBtnWrap) switchBtnWrap.style.display = switchShown ? '' : 'none';
			var backupBtn = document.getElementById('wpps-2fa-use-backup');
			if (backupBtn) {
				backupBtn.textContent = config.strings?.recoveryCode
					|| config.strings?.useBackupCodeInstead || 'Recovery code';
			}
			if (switchBtn && otherMethod) {
				switchBtn.textContent = otherMethod === 'email'
					? (config.strings?.useEmailCodeInstead || 'Use email instead')
					: (config.strings?.useAuthenticatorCodeInstead || 'Use authenticator instead');
				switchBtn.dataset.otherMethod = otherMethod;
			}
			var verifyBtn = document.getElementById('wpps-2fa-verify-submit');
			if (verifyBtn) verifyBtn.textContent = config.strings?.verifyButton || 'Verify';
			document.getElementById('wpps_2fa_token').value = token || '';
			document.getElementById('wpps_2fa_redirect_to').value = redirectTo || '';
			if (codeInput) codeInput.focus();
			hideError();
		}

		function handleSwitchLoginMethod() {
			var switchBtn = document.getElementById('wpps-2fa-switch-method-btn');
			var tokenEl = document.getElementById('wpps_2fa_token');
			if (!switchBtn || !tokenEl || !config.verifyNonce) return;
			var token = tokenEl.value;
			if (!token) return;
			switchBtn.disabled = true;
			var formData = new FormData();
			formData.append('action', 'wpps_2fa_switch_method');
			formData.append('token', token);
			formData.append('_wpnonce', config.verifyNonce);
			fetch(config.ajaxUrl, {
				method: 'POST',
				body: formData,
				credentials: 'same-origin'
			})
				.then(function(r) { return r.json(); })
				.then(function(data) {
					switchBtn.disabled = false;
					if (data.success && data.data && data.data.token) {
						currentToken = data.data.token;
						var newMethod = data.data.method || 'authenticator';
						var newOther = newMethod === 'email' ? 'authenticator' : 'email';
						var redirectTo = (document.getElementById('wpps_2fa_redirect_to') || {}).value || '';
						update2FAStepUI(data.data.token, redirectTo, newMethod, true, newOther);
					}
				})
				.catch(function() { switchBtn.disabled = false; });
		}
	}

	// Backup code / authenticator toggle (AJAX step and full-page form)
	function setBackupToggleLabels(isBackupMode) {
		var recoveryLabel = config.strings?.recoveryCode
			|| config.strings?.useBackupCodeInstead || 'Recovery code';
		var backToAuth = config.strings?.useAuthenticatorCodeInstead || 'Use authenticator instead';
		[].forEach.call(document.querySelectorAll('.wpps-2fa-backup-toggle'), function(b) {
			b.textContent = isBackupMode ? backToAuth : recoveryLabel;
		});
	}

	function setupBackupToggle() {
		[].forEach.call(document.querySelectorAll('.wpps-2fa-backup-toggle'), function(btn) {
			if (btn.dataset.bound) return;
			btn.dataset.bound = '1';
			btn.addEventListener('click', function(e) {
				e.preventDefault();
				var label = document.getElementById('wpps_2fa_code_label');
				var input = document.getElementById('wpps_2fa_code');
				if (!label || !input) return;
				if (input.dataset.mode === 'backup') {
					label.textContent = config.strings?.verificationCodeLabel || 'Verification Code';
					input.dataset.mode = 'authenticator';
					setHintAndPlaceholder('authenticator', null, input);
					setBackupToggleLabels(false);
				} else {
					label.textContent = config.strings?.backupCodeLabel || 'Backup Code';
					input.dataset.mode = 'backup';
					setHintAndPlaceholder('backup', null, input);
					setBackupToggleLabels(true);
				}
				input.value = '';
				input.focus();
			});
		});
	}

	// Full-page 2FA form: switch method (redirect with new token)
	function setupSwitchMethodFullPage() {
		var form = document.getElementById('wpps_2fa_form');
		var link = document.getElementById('wpps-2fa-switch-method-fullpage');
		if (!form || !link || !config.verifyNonce || !config.ajaxUrl) return;
		if (link.dataset.bound) return;
		link.dataset.bound = '1';
		link.addEventListener('click', function(e) {
			e.preventDefault();
			var tokenInput = form.querySelector('input[name="wpps_2fa_token"]');
			var redirectInput = form.querySelector('input[name="redirect_to"]');
			var token = tokenInput ? tokenInput.value : '';
			if (!token) return;
			link.disabled = true;
			var formData = new FormData();
			formData.append('action', 'wpps_2fa_switch_method');
			formData.append('token', token);
			formData.append('_wpnonce', config.verifyNonce);
			fetch(config.ajaxUrl, {
				method: 'POST',
				body: formData,
				credentials: 'same-origin'
			})
				.then(function(r) { return r.json(); })
				.then(function(data) {
					link.disabled = false;
					if (data.success && data.data && data.data.token) {
						var baseUrl = form.getAttribute('data-base-2fa-url')
							|| (window.location.pathname + '?action=wpps_2fa');
						var redirectTo = redirectInput ? redirectInput.value : '';
						var url = baseUrl;
						if (redirectTo) {
							url += (baseUrl.indexOf('?') >= 0 ? '&' : '?')
								+ 'redirect_to=' + encodeURIComponent(redirectTo);
						}
						window.location.href = url;
					}
				})
				.catch(function() { link.disabled = false; });
		});
	}

	function initFullPageResend() {
		var resend = document.getElementById('wpps-2fa-resend-fullpage');
		if (!resend || resend.dataset.bound || !config.verifyNonce || !config.ajaxUrl) return;
		resend.dataset.bound = '1';
		resend.addEventListener('click', function(e) {
			e.preventDefault();
			if (resend.disabled) return;
			var tokenInput = document.querySelector('#wpps_2fa_form input[name="wpps_2fa_token"]');
			var token = tokenInput ? tokenInput.value : '';
			if (!token) return;
			setLoading(resend, true);
			var formData = new FormData();
			formData.append('action', 'wpps_2fa_resend');
			formData.append('token', token);
			formData.append('_wpnonce', config.verifyNonce);
			fetch(config.ajaxUrl, {
				method: 'POST',
				body: formData,
				credentials: 'same-origin'
			})
				.then(function(r) { return r.json(); })
				.then(function(data) {
					setLoading(resend, false);
					if (data.success) {
						var orig = resend.textContent;
						resend.textContent = config.strings?.codeSent || 'Code sent!';
						setTimeout(function() { resend.textContent = orig; }, 2000);
					} else {
						var fe = document.getElementById('wpps-2fa-fullpage-error');
						var msg = data.data?.message || config.strings?.resendError || 'Could not resend code.';
						if (fe) { fe.textContent = msg; fe.style.display = ''; }
						else { window.alert(msg); }
					}
				})
				.catch(function() { setLoading(resend, false); });
		});
	}

	function showLoginStep() {
		if (!loginForm || !twoFaStep) return;
		twoFaStep.style.display = 'none';
		set2FAStepWideViewport(loginForm, false);
		loginForm.style.display = '';
		restoreLoginPageNotices();
		hideError();
	}

	function handleVerifySubmit(e) {
		e.preventDefault();
		const form = e.currentTarget;
		const token = (form.querySelector('[name="wpps_2fa_token"]') || {}).value || '';
		var codeInput = form.querySelector('[name="wpps_2fa_code"]');
		var code = (codeInput && codeInput.value) ? codeInput.value.replace(/\s/g, '').toUpperCase() : '';
		var codeDigits = code.replace(/\D/g, '');
		const redirectTo = (form.querySelector('[name="redirect_to"]') || {}).value || '';

		var isValid = (codeDigits.length === 6) || (codeDigits.length === 8) || (code.length === 8);
		if (!isValid) {
			show2FAError(config.strings?.invalidCode
				|| 'Please enter a 6-digit authenticator code or 8-character backup code.');
			return;
		}

		setLoading(form, true);
		hideError();

		const formData = new FormData();
		formData.append('action', 'wpps_2fa_verify');
		formData.append('token', token);
		formData.append('code', codeDigits.length === 6 ? codeDigits : (code.length === 8 ? code : codeDigits));
		formData.append('redirect_to', redirectTo);
		formData.append('_wpnonce', config.verifyNonce);
		var trustCb = document.getElementById('wpps_2fa_trust_device');
		if (trustCb && trustCb.checked) {
			formData.append('trust_device', '1');
		}

		fetch(config.ajaxUrl, {
			method: 'POST',
			body: formData,
			credentials: 'same-origin'
		})
			.then(function(r) { return r.json(); })
			.then(function(data) {
				setLoading(form, false);
				if (data.success && data.data && data.data.redirect) {
					window.location.href = data.data.redirect;
				} else {
					if (data.data && data.data.code === 'locked') {
						var loginBase = config.loginUrl || '';
						var sep = loginBase.indexOf('?') >= 0 ? '&' : '?';
						show2FAError(data.data.message || config.strings?.tooManyAttempts
							|| 'Too many incorrect codes.');
						window.location.href = loginBase + sep + 'error=wpps_2fa_locked';
						return;
					}
					show2FAError(data.data?.message || config.strings?.invalidCode
						|| 'Invalid or expired code. Please try again.');
				}
			})
			.catch(function() {
				setLoading(form, false);
				show2FAError(config.strings?.requestError || 'Request failed. Please try again.');
			});
		return false;
	}

	function handleResend(e) {
		e.preventDefault();
		const btn = e.currentTarget;
		if (btn.disabled) return;

		var token = currentToken || ((document.getElementById('wpps_2fa_token') || {}).value || '');
		if (!token) return;

		setLoading(btn, true);

		const formData = new FormData();
		formData.append('action', 'wpps_2fa_resend');
		formData.append('token', token);
		formData.append('_wpnonce', config.verifyNonce);

		fetch(config.ajaxUrl, {
			method: 'POST',
			body: formData,
			credentials: 'same-origin'
		})
			.then(function(r) { return r.json(); })
			.then(function(data) {
				setLoading(btn, false);
				if (data.success) {
					const orig = btn.textContent;
					btn.textContent = config.strings?.codeSent || 'Code sent!';
					setTimeout(function() { btn.textContent = orig; }, 2000);
				} else {
					show2FAError(data.data?.message || config.strings?.resendError || 'Could not resend code.');
				}
			})
			.catch(function() {
				setLoading(btn, false);
				show2FAError(config.strings?.requestError || 'Request failed.');
			});
	}

	function setLoading(el, loading) {
		var controls = [];
		if (el.tagName === 'BUTTON' || (el.tagName === 'INPUT' && el.type === 'submit')) {
			controls = [el];
		} else {
			controls = [].slice.call(el.querySelectorAll('button, input[type="submit"]'));
		}
		if (loading) {
			el.classList.add('wpps-2fa-loading');
			controls.forEach(function(c) { c.disabled = true; });
		} else {
			el.classList.remove('wpps-2fa-loading');
			controls.forEach(function(c) { c.disabled = false; });
		}
	}

	function showLoginError(msg) {
		if (!loginForm) return;
		msg = formatCredentialErrorForDisplay(msg);
		const isWoo = loginForm.classList.contains('woocommerce-form-login');
		const isWpLoginShell = document.body.classList.contains('login') && loginForm.id === 'loginform';
		let err = document.getElementById('login_error');
		if (!err) {
			if (isWoo) {
				err = document.createElement('ul');
				err.className = 'woocommerce-error';
				err.setAttribute('role', 'alert');
				err.id = 'login_error';
				const li = document.createElement('li');
				li.textContent = msg;
				err.appendChild(li);
			} else {
				err = document.createElement('p');
				err.id = 'login_error';
				err.className = 'message';
				err.textContent = msg;
				err.style.borderLeftColor = '#d63638';
			}
			if (isWpLoginShell && loginForm.parentNode) {
				loginForm.parentNode.insertBefore(err, loginForm);
			} else {
				loginForm.insertBefore(err, loginForm.firstChild);
			}
		} else if (isWoo && err.tagName === 'UL' && err.querySelector('li')) {
			err.querySelector('li').textContent = msg;
		} else {
			err.textContent = msg;
		}
		err.style.display = 'block';
		if (!isWoo && err.style) {
			err.style.borderLeftColor = '#d63638';
		}
	}

	function show2FAError(msg) {
		let err = document.getElementById('wpps-2fa-error');
		if (err) {
			err.textContent = msg;
			err.style.display = 'block';
		}
	}

	function hideError() {
		const err = document.getElementById('login_error');
		if (err) err.style.display = 'none';
		const err2 = document.getElementById('wpps-2fa-error');
		if (err2) err2.style.display = 'none';
	}

	function boot() {
		initAjaxLoginFlow();
		setupBackupToggle();
		setupSwitchMethodFullPage();
		initFullPageResend();
	}

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', boot);
	} else {
		boot();
	}
})();
