/* MerchantKits Attendance Manager — frontend scripts */
( function () {
	'use strict';

	document.addEventListener( 'DOMContentLoaded', function () {
		initLiveClock();
		initWorkedCounter();
		initClockActions();
		initLeaveForm();
		initLeaveBalance();
		initCancelLeave();
	} );

	/**
	 * POST helper to admin-ajax with the frontend nonce.
	 *
	 * @param {string} action AJAX action.
	 * @param {Object} fields Extra fields.
	 * @return {Promise<Object>} Parsed JSON response.
	 */
	function ajax( action, fields ) {
		var body = new FormData();
		body.append( 'action', action );
		body.append( 'nonce', mkamFrontend.nonce );
		Object.keys( fields || {} ).forEach( function ( key ) {
			body.append( key, fields[ key ] );
		} );

		return fetch( mkamFrontend.ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			body: body
		} ).then( function ( r ) { return r.json(); } );
	}

	/**
	 * Current time in the WordPress site's timezone, as milliseconds that can be
	 * read with the getUTC* accessors. Falls back to the browser clock if the
	 * server values are unavailable.
	 *
	 * @return {number} Shifted epoch milliseconds.
	 */
	function siteNowMs() {
		if ( typeof mkamFrontend === 'undefined' || typeof mkamFrontend.serverNow === 'undefined' ) {
			return Date.now();
		}
		if ( typeof siteNowMs._base === 'undefined' ) {
			siteNowMs._base = mkamFrontend.serverNow * 1000; // UTC ms at page load.
			siteNowMs._loadedAt = Date.now();
		}
		var utcMs = siteNowMs._base + ( Date.now() - siteNowMs._loadedAt );
		return utcMs + ( ( mkamFrontend.gmtOffset || 0 ) * 1000 );
	}

	/**
	 * Update the live clock display every second, using the site timezone.
	 */
	function initLiveClock() {
		var el = document.getElementById( 'mkam-live-clock' );
		if ( ! el ) {
			return;
		}
		function two( n ) { return ( n < 10 ? '0' : '' ) + n; }
		function tick() {
			var d = new Date( siteNowMs() );
			var h = d.getUTCHours();
			var m = d.getUTCMinutes();
			var s = d.getUTCSeconds();
			var ampm = h >= 12 ? 'PM' : 'AM';
			var h12 = h % 12;
			if ( 0 === h12 ) {
				h12 = 12;
			}
			el.textContent = h12 + ':' + two( m ) + ':' + two( s ) + ' ' + ampm;
		}
		tick();
		window.setInterval( tick, 1000 );
	}

	/**
	 * Show a live "X hours Y minutes" worked counter when clocked in.
	 */
	function initWorkedCounter() {
		var widget = document.querySelector( '.mkam-clock' );
		var counter = document.getElementById( 'mkam-worked-counter' );
		if ( ! widget || ! counter ) {
			return;
		}
		var clockIn = widget.getAttribute( 'data-clock-in' );
		if ( ! clockIn ) {
			return;
		}
		// clock_in is stored in the site timezone; convert to a UTC instant using
		// the site offset so elapsed time is correct regardless of browser timezone.
		var offsetMs = ( typeof mkamFrontend !== 'undefined' && mkamFrontend.gmtOffset ) ? mkamFrontend.gmtOffset * 1000 : 0;
		var startUtc = Date.parse( clockIn.replace( ' ', 'T' ) + 'Z' ) - offsetMs;
		function tick() {
			var nowUtc = siteNowMs() - offsetMs; // Convert shifted site-ms back to true UTC ms.
			var diff = Math.max( 0, Math.floor( ( nowUtc - startUtc ) / 60000 ) );
			var h = Math.floor( diff / 60 );
			var m = diff % 60;
			counter.textContent = h + 'h ' + m + 'm';
		}
		tick();
		window.setInterval( tick, 60000 );
	}

	/**
	 * Wire the clock in/out button, including optional geolocation.
	 */
	function initClockActions() {
		var button = document.getElementById( 'mkam-clock-action' );
		if ( ! button ) {
			return;
		}

		button.addEventListener( 'click', function () {
			var action = button.getAttribute( 'data-action' );
			var noteEl = document.getElementById( 'mkam-clock-note' );
			var fields = { note: noteEl ? noteEl.value : '' };

			button.disabled = true;

			captureLocation().then( function ( loc ) {
				if ( loc ) {
					fields.location = loc;
				}
				return ajax( action === 'clock-out' ? 'mkam_clock_out' : 'mkam_clock_in', fields );
			} ).then( function ( res ) {
				showMessage( 'mkam-clock-message', res );
				if ( res.success ) {
					window.setTimeout( function () { window.location.reload(); }, 800 );
				} else {
					button.disabled = false;
				}
			} ).catch( function () {
				button.disabled = false;
			} );
		} );
	}

	/**
	 * Resolve the browser geolocation as "lat,lng" if enabled.
	 *
	 * @return {Promise<string>} Location string or empty.
	 */
	function captureLocation() {
		return new Promise( function ( resolve ) {
			if ( ! mkamFrontend.enableGeo || ! navigator.geolocation ) {
				resolve( '' );
				return;
			}
			navigator.geolocation.getCurrentPosition(
				function ( pos ) {
					resolve( pos.coords.latitude + ',' + pos.coords.longitude );
				},
				function () { resolve( '' ); },
				{ timeout: 5000 }
			);
		} );
	}

	/**
	 * Wire the leave request form submission.
	 */
	function initLeaveForm() {
		var form = document.getElementById( 'mkam-leave-form' );
		if ( ! form ) {
			return;
		}

		var halfDay = document.getElementById( 'mkam-half-day' );
		var periodWrap = document.getElementById( 'mkam-half-day-period-wrap' );
		if ( halfDay && periodWrap ) {
			halfDay.addEventListener( 'change', function () {
				periodWrap.style.display = halfDay.checked ? 'block' : 'none';
			} );
		}

		form.addEventListener( 'submit', function ( e ) {
			e.preventDefault();
			var fields = {
				leave_type: value( 'mkam-leave-type' ),
				start_date: value( 'mkam-start-date' ),
				end_date: value( 'mkam-end-date' ),
				is_half_day: halfDay && halfDay.checked ? 1 : 0,
				half_day_period: value( 'mkam-half-day-period' ),
				reason: value( 'mkam-reason' )
			};

			ajax( 'mkam_submit_leave', fields ).then( function ( res ) {
				showMessage( 'mkam-leave-message', res );
				if ( res.success ) {
					form.reset();
				}
			} );
		} );
	}

	/**
	 * Fetch and display the leave balance when a leave type is chosen.
	 */
	function initLeaveBalance() {
		var select = document.getElementById( 'mkam-leave-type' );
		var display = document.getElementById( 'mkam-leave-balance' );
		if ( ! select || ! display ) {
			return;
		}
		select.addEventListener( 'change', function () {
			if ( ! select.value ) {
				display.textContent = '';
				return;
			}
			ajax( 'mkam_leave_balance', { leave_type: select.value } ).then( function ( res ) {
				if ( res.success && res.data ) {
					display.textContent = 'Available balance: ' + res.data.balance;
				}
			} );
		} );
	}

	/**
	 * Wire cancel buttons on the my-leaves table.
	 */
	function initCancelLeave() {
		var buttons = document.querySelectorAll( '.mkam-cancel-leave' );
		Array.prototype.forEach.call( buttons, function ( button ) {
			button.addEventListener( 'click', function () {
				if ( ! window.confirm( 'Cancel this request?' ) ) {
					return;
				}
				ajax( 'mkam_cancel_leave', { leave_id: button.getAttribute( 'data-leave-id' ) } ).then( function ( res ) {
					if ( res.success ) {
						window.location.reload();
					}
				} );
			} );
		} );
	}

	/**
	 * Read a form field value safely by element ID.
	 *
	 * @param {string} id Element ID.
	 * @return {string} Value or empty string.
	 */
	function value( id ) {
		var el = document.getElementById( id );
		return el ? el.value : '';
	}

	/**
	 * Render an AJAX response message into a container.
	 *
	 * @param {string} id  Container ID.
	 * @param {Object} res Response object.
	 */
	function showMessage( id, res ) {
		var el = document.getElementById( id );
		if ( ! el ) {
			return;
		}
		var msg = res.data && res.data.message ? res.data.message : '';
		el.textContent = msg;
		el.style.color = res.success ? '#16a34a' : '#dc2626';
	}
} )();
