/**
 * Kramar – Order Delivery Date: client-side constraints.
 *
 * Enforces blocked weekdays and holidays on the native <input type="date">
 * field. No jQuery. Server-side validation is authoritative; this script is
 * a UX convenience that prevents obviously invalid picks before form submit.
 *
 * Data injected via wp_localize_script as `window.kramarDeliveryDate`:
 *   minDate         {string}   Y-m-d of the earliest selectable date.
 *   blockedWeekdays {number[]} 0=Sun … 6=Sat.
 *   holidays        {string[]} Array of blocked Y-m-d strings.
 *   required        {boolean}  Whether the field is required.
 *
 * @package Kramar
 * @since   1.0.0
 */

( function () {
	'use strict';

	var cfg = window.kramarDeliveryDate;
	if ( ! cfg ) {
		return;
	}

	/**
	 * Parse a Y-m-d string to a local-midnight Date object.
	 *
	 * @param {string} ymd
	 * @returns {Date|null}
	 */
	function parseYmd( ymd ) {
		if ( ! ymd || ! /^\d{4}-\d{2}-\d{2}$/.test( ymd ) ) {
			return null;
		}
		var parts = ymd.split( '-' );
		return new Date( +parts[ 0 ], +parts[ 1 ] - 1, +parts[ 2 ] );
	}

	/**
	 * Format a Date to Y-m-d string (local time).
	 *
	 * @param {Date} d
	 * @returns {string}
	 */
	function toYmd( d ) {
		var y = d.getFullYear();
		var m = String( d.getMonth() + 1 ).padStart( 2, '0' );
		var day = String( d.getDate() ).padStart( 2, '0' );
		return y + '-' + m + '-' + day;
	}

	/**
	 * Return true if the given Y-m-d string is blocked.
	 *
	 * @param {string} ymd
	 * @returns {boolean}
	 */
	function isBlocked( ymd ) {
		var d = parseYmd( ymd );
		if ( ! d ) {
			return false;
		}
		var dow = d.getDay();
		if ( cfg.blockedWeekdays.indexOf( dow ) !== -1 ) {
			return true;
		}
		if ( cfg.holidays.indexOf( ymd ) !== -1 ) {
			return true;
		}
		return false;
	}

	/**
	 * Walk forward from startYmd until a non-blocked date is found.
	 * Mirrors PHP compute_min_date() logic exactly.
	 *
	 * @param {string} startYmd
	 * @returns {string} First valid Y-m-d.
	 */
	function firstValidDate( startYmd ) {
		var d = parseYmd( startYmd );
		if ( ! d ) {
			return startYmd;
		}
		for ( var i = 0; i < 365; i++ ) {
			if ( ! isBlocked( toYmd( d ) ) ) {
				return toYmd( d );
			}
			d.setDate( d.getDate() + 1 );
		}
		return toYmd( d );
	}

	/**
	 * Initialise the delivery date input.
	 */
	function init() {
		var input = document.querySelector( 'input.kramar-delivery-date-input' );
		if ( ! input ) {
			return;
		}

		var effectiveMin = firstValidDate( cfg.minDate );

		// Enforce the computed min (server may also set it as an attribute).
		input.setAttribute( 'min', effectiveMin );

		/**
		 * Validate the currently selected value.
		 * Returns an error message string, or empty string if valid.
		 *
		 * @returns {string}
		 */
		function validate() {
			var val = input.value;

			if ( ! val ) {
				return cfg.required ? cfg.i18n.required : '';
			}

			var minD = parseYmd( effectiveMin );
			var selD = parseYmd( val );
			if ( ! selD ) {
				return cfg.i18n.blocked;
			}

			if ( minD && selD < minD ) {
				return cfg.i18n.tooSoon;
			}

			if ( isBlocked( val ) ) {
				return cfg.i18n.blocked;
			}

			return '';
		}

		/**
		 * Show or clear the inline error below the input.
		 *
		 * @param {string} message
		 */
		function showError( message ) {
			var existing = input.parentElement
				? input.parentElement.querySelector( '.kramar-delivery-date-error' )
				: null;

			if ( message ) {
				if ( ! existing ) {
					var span = document.createElement( 'span' );
					span.className = 'kramar-delivery-date-error';
					span.style.cssText = 'display:block;color:#b81c23;font-size:0.85em;margin-top:4px;';
					if ( input.parentElement ) {
						input.parentElement.appendChild( span );
					}
					existing = span;
				}
				existing.textContent = message;
				input.setCustomValidity( message );
			} else {
				if ( existing ) {
					existing.textContent = '';
				}
				input.setCustomValidity( '' );
			}
		}

		// Validate on change.
		input.addEventListener( 'change', function () {
			var msg = validate();
			showError( msg );

			// If the user picked a blocked date, advance to the next valid one.
			if ( msg === cfg.i18n.blocked && input.value ) {
				var selD = parseYmd( input.value );
				if ( selD ) {
					selD.setDate( selD.getDate() + 1 );
					var next = firstValidDate( toYmd( selD ) );
					// Only suggest if still within allowed range.
					var minD = parseYmd( effectiveMin );
					if ( ! minD || parseYmd( next ) >= minD ) {
						input.value = next;
						showError( validate() );
					}
				}
			}
		} );

		// Validate on form submit to catch unchanged invalid defaults.
		var form = input.closest( 'form' );
		if ( form ) {
			form.addEventListener(
				'submit',
				function ( e ) {
					var msg = validate();
					if ( msg ) {
						showError( msg );
						e.preventDefault();
						input.focus();
					}
				},
				true
			);
		}
	}

	// Run after DOM ready.
	if ( document.readyState === 'loading' ) {
		document.addEventListener( 'DOMContentLoaded', init );
	} else {
		init();
	}
} )();
