/**
 * WP PowerSuite – number inputs with data-wpps-min, data-wpps-max, data-wpps-step.
 * Shows inline errors and red state when out of range; does not silently change values.
 */
(function () {
	'use strict';

	var ERR_CLASS = 'wpps-number-invalid';
	var ERR_SPAN_CLASS = 'wpps-number-field-error';
	var ERR_KIND = 'wppsNumErr';

	function hasClampAttrs(el) {
		return el.matches('input[type="number"]') && (
			el.hasAttribute('data-wpps-min') ||
			el.hasAttribute('data-wpps-max') ||
			el.hasAttribute('data-wpps-step')
		);
	}

	function getBounds(el) {
		var minS = el.getAttribute('data-wpps-min');
		var maxS = el.getAttribute('data-wpps-max');
		var stepS = el.getAttribute('data-wpps-step');
		return {
			min: (minS !== null && minS !== '') ? parseFloat(minS, 10) : null,
			max: (maxS !== null && maxS !== '') ? parseFloat(maxS, 10) : null,
			step: (stepS !== null && stepS !== '') ? parseFloat(stepS, 10) : null
		};
	}

	function formatBound(n) {
		if (Math.abs(n - Math.round(n)) < 1e-9) return String(Math.round(n));
		return String(Math.round(n * 1000) / 1000);
	}

	function snapToStep(n, min, step) {
		if (!(step > 0)) return n;
		if (min !== null && !isNaN(min)) {
			var k = (n - min) / step;
			return min + Math.round(k) * step;
		}
		return Math.round(n / step) * step;
	}

	function stepValid(n, min, step) {
		if (!(step > 0)) return true;
		var snapped = snapToStep(n, min, step);
		return Math.abs(n - snapped) < 1e-6;
	}

	function getErrorHost(input) {
		return input.closest('.wpps-input-unit-row')
			|| input.closest('.wpps-rm-form-group')
			|| input.closest('.wpps-cs-form-group')
			|| input.closest('label')
			|| input.parentElement;
	}

	function ensureErrorEl(input) {
		var host = getErrorHost(input);
		var err = host.querySelector('.' + ERR_SPAN_CLASS);
		if (!err) {
			err = document.createElement('span');
			err.className = ERR_SPAN_CLASS;
			err.setAttribute('role', 'alert');
			host.appendChild(err);
		}
		return err;
	}

	function setFieldError(input, kind, message) {
		input.dataset[ERR_KIND] = kind;
		input.classList.add(ERR_CLASS);
		input.setAttribute('aria-invalid', 'true');
		var err = ensureErrorEl(input);
		err.textContent = message;
		err.hidden = false;
	}

	function clearFieldError(input) {
		delete input.dataset[ERR_KIND];
		input.classList.remove(ERR_CLASS);
		input.removeAttribute('aria-invalid');
		var host = getErrorHost(input);
		if (!host) return;
		var err = host.querySelector('.' + ERR_SPAN_CLASS);
		if (err) {
			err.textContent = '';
			err.hidden = true;
		}
	}

	function getErrKind(input) {
		return input.dataset[ERR_KIND] || '';
	}

	/**
	 * @param {HTMLInputElement} el
	 * @param {'input'|'blur'} mode
	 */
	function validate(el, mode) {
		var v = String(el.value).trim();

		if (v === '') {
			clearFieldError(el);
			return;
		}

		if (v === '-' || v === '.' || v === '-.') {
			if (mode === 'blur') {
				el.value = '';
				clearFieldError(el);
			}
			return;
		}

		var n = parseFloat(v, 10);
		if (isNaN(n)) {
			if (mode === 'blur') {
				setFieldError(el, 'nan', 'Enter a valid number.');
			}
			return;
		}

		var b = getBounds(el);
		var kind = getErrKind(el);

		if (b.max !== null && n > b.max) {
			setFieldError(el, 'max', 'Maximum allowed is ' + formatBound(b.max) + '.');
			return;
		}

		if (mode === 'input' && kind === 'max') {
			clearFieldError(el);
			kind = '';
		}

		if (mode === 'blur' && b.min !== null && n < b.min) {
			setFieldError(el, 'min', 'Minimum allowed is ' + formatBound(b.min) + '.');
			return;
		}

		if (mode === 'input' && b.min !== null && n < b.min) {
			return;
		}

		if (mode === 'blur' && b.step !== null && b.step > 0 && !stepValid(n, b.min, b.step)) {
			setFieldError(el, 'step', 'Use increments of ' + formatBound(b.step) + '.');
			return;
		}

		if (mode === 'input' && b.step !== null && b.step > 0 && !stepValid(n, b.min, b.step)) {
			setFieldError(el, 'step', 'Use increments of ' + formatBound(b.step) + '.');
			return;
		}

		if (mode === 'input' && kind === 'min' && b.min !== null && n >= b.min) {
			clearFieldError(el);
			kind = '';
		}

		clearFieldError(el);
	}

	document.addEventListener('input', function (e) {
		var t = e.target;
		if (!t || !t.matches || !hasClampAttrs(t)) return;
		validate(t, 'input');
	});

	document.addEventListener('blur', function (e) {
		var t = e.target;
		if (!t || !t.matches || !hasClampAttrs(t)) return;
		validate(t, 'blur');
	}, true);
})();
