(function () {
	'use strict';

	const config = window.FoodordTableReservationsAdmin || {};
	const i18n = config.i18n || {};
	const ajaxUrl = config.ajaxUrl || window.ajaxurl || '';
	const tableFilterNonce = config.tableFilterNonce || '';
	const managementPaginationNonce = config.managementPaginationNonce || '';
	const managementPageSelectors = {
		reservation_floor_page: '[data-foodord-reservation-floors-list]',
		reservation_table_page: '[data-foodord-reservation-tables-list]'
	};
	const managementPageKeys = Object.keys(managementPageSelectors);
	const managementFilterKeys = [
		'reservation_table_floor',
		'reservation_table_search'
	];
	const managementQueryKeys = [...managementPageKeys, ...managementFilterKeys];

	const getFloorPanel = () => document.querySelector('[data-foodord-reservations-floor-panel]');
	const getFloorToggle = () => document.querySelector('[data-foodord-reservations-floor-toggle]');
	const getFloorForm = () => document.querySelector('.foodord-reservations-form--floor');

	const getTablePanel = () => document.querySelector('[data-foodord-reservations-table-panel]');
	const getTableToggle = () => document.querySelector('[data-foodord-reservations-table-toggle]');

	const getTableForm = () => document.querySelector('#foodord-reservation-table-form');
	const getManualReservationModal = () => document.querySelector('[data-foodord-manual-reservation-modal]');
	const getManualReservationOpenButton = () => document.querySelector('[data-foodord-manual-reservation-open]');
	const getCancellationModal = () => document.querySelector('[data-foodord-reservation-cancellation-modal]');
	const manualReservationModalTransitionMs = 180;
	let manualReservationModalCloseTimer = 0;
	let activeCancellationForm = null;
	let cancellationModalCloseTimer = 0;

	const formatDateKey = (date) => {
		const month = String(date.getMonth() + 1).padStart(2, '0');
		const day = String(date.getDate()).padStart(2, '0');

		return String(date.getFullYear()) + '-' + month + '-' + day;
	};

	const isDateDisabledByBookingRules = (date) => {
		const disabled = config.dateDisabled || {};
		const weekdays = Array.isArray(disabled.weekdays) ? disabled.weekdays.map((weekday) => Number(weekday)) : [];

		if (weekdays.includes(date.getDay())) {
			return true;
		}

		const dateKey = formatDateKey(date);
		const ranges = Array.isArray(disabled.ranges) ? disabled.ranges : [];

		return ranges.some((range) => {
			const from = range && typeof range.from === 'string' ? range.from : '';
			const to = range && typeof range.to === 'string' ? range.to : from;

			return !!from && dateKey >= from && dateKey <= to;
		});
	};

	const getDatepickerAvailability = (date) => {
		return isDateDisabledByBookingRules(date)
			? [false, 'foodord-reservations-datepicker-unavailable', '']
			: [true, '', ''];
	};

	const initDatePickers = (scope) => {
		const root = scope || document;

		if (!window.jQuery || typeof window.jQuery.fn.datepicker !== 'function') {
			return;
		}

		root.querySelectorAll('[data-foodord-reservation-admin-date]:not([data-foodord-reservation-datepicker-ready])').forEach((field) => {
			field.dataset.foodordReservationDatepickerReady = '1';

			const datePickerOptions = {
				beforeShow: (_input, instance) => {
					window.setTimeout(() => {
						instance.dpDiv
							.addClass('foodord-reservations-datepicker')
							.css('z-index', '100002');
					}, 0);
				},
				dateFormat: config.dateFormat || 'yy-mm-dd',
				onSelect: () => {
					field.dispatchEvent(new Event('change', { bubbles: true }));
				}
			};

			if (field.hasAttribute('data-foodord-reservation-min-today')) {
				datePickerOptions.beforeShowDay = getDatepickerAvailability;
				datePickerOptions.minDate = 0;
			}

			window.jQuery(field).datepicker(datePickerOptions);
			window.jQuery(field).datepicker('widget')
				.addClass('foodord-reservations-datepicker')
				.css('z-index', '100002');
		});
	};

	const hideDatePicker = () => {
		if (!window.jQuery || typeof window.jQuery.fn.datepicker !== 'function') {
			return;
		}

		window.jQuery('#ui-datepicker-div').hide();
	};

	const initEmailContentSettings = () => {
		document.querySelectorAll('[data-foodord-reservation-email-content]').forEach((root) => {
			const templateSelect = root.querySelector('[data-foodord-reservation-email-template]');
			const templatePanels = root.querySelectorAll('[data-foodord-reservation-email-template-panel]');
			const resetButton = root.querySelector('[data-foodord-reservation-email-reset]');

			if (!templateSelect || !templatePanels.length) {
				return;
			}

			const showSelectedTemplate = () => {
				const selectedTemplate = templateSelect.value || 'pending';

				templatePanels.forEach((panel) => {
					panel.hidden = panel.dataset.foodordReservationEmailTemplatePanel !== selectedTemplate;
				});
			};

			templateSelect.addEventListener('change', showSelectedTemplate);

			if (resetButton) {
				resetButton.addEventListener('click', () => {
					root.querySelectorAll('input[type="text"], textarea').forEach((field) => {
						field.value = '';
					});
				});
			}

			showSelectedTemplate();
		});
	};

	const initPrivacySettings = () => {
		document.querySelectorAll('[data-foodord-reservation-privacy-settings]').forEach((root) => {
			const enabled = root.querySelector('[data-foodord-reservation-privacy-enabled]');
			const storeIp = root.querySelector('[data-foodord-reservation-privacy-store-ip]');

			if (!enabled || !storeIp) {
				return;
			}

			const syncState = () => {
				const storeIpRow = storeIp.closest('.foodord-reservations-privacy__ip');

				storeIp.disabled = !enabled.checked;
				if (storeIpRow) {
					storeIpRow.classList.toggle('is-disabled', !enabled.checked);
				}
			};

			enabled.addEventListener('change', syncState);
			syncState();
		});
	};

	const initDepositSettings = () => {
		document.querySelectorAll('[data-foodord-reservation-deposit-settings]').forEach((root) => {
			const applicable = root.querySelector('[data-foodord-reservation-deposit-applicable]');
			const partySize = root.querySelector('[data-foodord-reservation-deposit-party-size-field]');
			const schedule = root.querySelector('[data-foodord-reservation-deposit-schedule]');

			if (!applicable) {
				return;
			}

			const syncState = () => {
				const value = applicable.value || 'all_times';

				if (partySize) {
					partySize.hidden = value !== 'party_size';
				}

				if (schedule) {
					schedule.hidden = value !== 'specific_times';
				}
			};

			applicable.addEventListener('change', syncState);
			syncState();
		});
	};

	const initPreorderSettings = () => {
		document.querySelectorAll('[data-foodord-reservation-preorder-settings]').forEach((root) => {
			const applicable = root.querySelector('[data-foodord-reservation-preorder-applicable]');
			const schedule = root.querySelector('[data-foodord-reservation-preorder-schedule]');

			if (!applicable || !schedule) {
				return;
			}

			const syncState = () => {
				schedule.hidden = applicable.value !== 'specific_times';
			};

			applicable.addEventListener('change', syncState);
			syncState();
		});
	};

	const initCapacityLimitSettings = () => {
		document.querySelectorAll('[data-foodord-reservation-capacity-limits]').forEach((root) => {
			const enabled = root.querySelector('[data-foodord-reservation-capacity-limits-enabled]');
			const fields = root.querySelectorAll('[data-foodord-reservation-capacity-limits-fields]');

			if (!enabled || !fields.length) {
				return;
			}

			const syncState = () => {
				root.classList.toggle('is-enabled', enabled.checked);

				fields.forEach((field) => {
					field.hidden = !enabled.checked;
				});
			};

			enabled.addEventListener('change', syncState);
			syncState();
		});
	};

	const parseJsonObject = (value, fallback) => {
		try {
			const parsed = JSON.parse(value || '');

			if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
				return parsed;
			}
		} catch {
			// Use the supplied fallback when stored state is unavailable.
		}

		return JSON.parse(JSON.stringify(fallback || {}));
	};

	const initTableSelectionSettings = (scope) => {
		const root = scope && scope.matches('[data-foodord-reservation-table-selection]')
			? scope
			: document.querySelector('[data-foodord-reservation-table-selection]');
		const enabled = root ? root.querySelector('[data-foodord-reservation-table-selection-enabled]') : null;
		const floorPlans = root ? root.querySelector('[data-foodord-reservation-floor-plans]') : null;
		const layoutsField = root ? root.querySelector('[data-foodord-reservation-table-selection-layouts]') : null;
		let mediaFrame = null;
		let activePlan = null;
		let gridBuilder = null;
		let imageMarkerEditor = null;

		if (!root || !enabled || !floorPlans || !layoutsField) {
			return;
		}

		const fallbackLayouts = config.tableSelection && config.tableSelection.layouts ? config.tableSelection.layouts : {};
		const layouts = parseJsonObject(layoutsField.value, fallbackLayouts);
		const createLayoutsSnapshot = () => Object.fromEntries(
			Object.entries(layouts).map(([floorId, layout]) => [
				floorId,
				{
					...layout,
					tables: { ...(layout.tables || {}) },
					grid_tables: Object.fromEntries(
						Object.entries(layout.grid_tables || {}).map(([tableId, geometry]) => [tableId, { ...geometry }])
					),
					objects: Object.fromEntries(
						Object.entries(layout.objects || {}).map(([objectId, object]) => [objectId, { ...object }])
					)
				}
			])
		);

		const getLayout = (floorId) => {
			const key = String(floorId);
			if (!layouts[key] || typeof layouts[key] !== 'object') {
				layouts[key] = {
					mode: 'image',
					image_id: 0,
					tables: {},
					grid_tables: {},
					objects: {},
					snap_to_grid: true,
					grid_density: 'coarse'
				};
			}
			layouts[key].mode = layouts[key].mode === 'grid' ? 'grid' : 'image';
			if (!layouts[key].tables || typeof layouts[key].tables !== 'object') {
				layouts[key].tables = {};
			}
			if (!layouts[key].grid_tables || typeof layouts[key].grid_tables !== 'object') {
				layouts[key].grid_tables = {};
			}
			if (!layouts[key].objects || typeof layouts[key].objects !== 'object') {
				layouts[key].objects = {};
			}
			layouts[key].grid_density = layouts[key].grid_density === 'fine' ? 'fine' : 'coarse';

			return layouts[key];
		};

		const syncLayouts = () => {
			const snapshot = createLayoutsSnapshot();
			layoutsField.value = JSON.stringify(snapshot);
		};

		const showPlan = (floorId) => {
			root.querySelectorAll('[data-foodord-reservation-floor-plan]').forEach((plan) => {
				const isActive = plan.dataset.foodordReservationFloorPlan === String(floorId);
				plan.hidden = !isActive;
				if (isActive) {
					if (imageMarkerEditor) {
						imageMarkerEditor.refreshPlan(floorId);
					}
					if (gridBuilder) {
						gridBuilder.refreshPlan(floorId);
					}
				}
			});

			root.querySelectorAll('[data-foodord-reservation-floor-plan-tab]').forEach((tab) => {
				const isActive = tab.dataset.foodordReservationFloorPlanTab === String(floorId);
				tab.classList.toggle('is-active', isActive);
				tab.setAttribute('aria-selected', String(isActive));
			});
		};

		const syncEnabledState = () => {
			root.classList.toggle('is-enabled', enabled.checked);
			floorPlans.hidden = !enabled.checked;
		};

		const updatePlanImage = (plan, imageId, imageUrl) => {
			const floorId = plan.dataset.foodordReservationFloorPlan || '';
			const layout = getLayout(floorId);
			const canvas = plan.querySelector('[data-foodord-reservation-floor-plan-canvas]');
			const image = plan.querySelector('[data-foodord-reservation-floor-plan-image]');
			const empty = plan.querySelector('[data-foodord-reservation-floor-plan-empty]');

			layout.image_id = Number(imageId) || 0;
			if (image && imageUrl) {
				image.src = imageUrl;
				image.hidden = false;
			}
			if (image && !imageUrl) {
				image.removeAttribute('src');
				image.hidden = true;
			}
			if (canvas) {
				canvas.classList.toggle('is-empty', !imageUrl);
			}
			if (empty) {
				empty.hidden = !!imageUrl;
			}
			if (imageMarkerEditor) {
				imageMarkerEditor.refreshPlan(floorId);
			}
			syncLayouts();
		};

		const openImagePicker = (plan) => {
			if (!window.wp || !window.wp.media) {
				return;
			}

			activePlan = plan;
			if (!mediaFrame) {
				mediaFrame = window.wp.media({
					title: 'Select floor plan',
					button: {
						text: 'Use this image'
					},
					library: {
						type: 'image'
					},
					multiple: false
				});

				mediaFrame.on('select', () => {
					if (!activePlan) {
						return;
					}

					const attachment = mediaFrame.state().get('selection').first();
					if (!attachment) {
						return;
					}

					const data = attachment.toJSON();
					const sizes = data.sizes || {};
					const imageUrl = sizes.large && sizes.large.url ? sizes.large.url : data.url;

					updatePlanImage(activePlan, data.id || 0, imageUrl || '');
				});
			}

			mediaFrame.open();
		};

		if (window.FoodordReservationImagePlanMarkerEditor) {
			imageMarkerEditor = window.FoodordReservationImagePlanMarkerEditor.init({
				root,
				getLayout,
				syncLayouts
			});
		}

		if (window.FoodordReservationFloorPlanBuilder) {
			gridBuilder = window.FoodordReservationFloorPlanBuilder.init({
				root,
				getLayout,
				syncLayouts
			});
		}

		root.addEventListener('click', (event) => {
			const target = event.target instanceof Element ? event.target : null;
			const plan = target ? target.closest('[data-foodord-reservation-floor-plan]') : null;
			const tab = target ? target.closest('[data-foodord-reservation-floor-plan-tab]') : null;

			if (tab) {
				showPlan(tab.dataset.foodordReservationFloorPlanTab || '');
				return;
			}

			if (!plan) {
				return;
			}

			if (target && target.closest('[data-foodord-reservation-floor-plan-select]')) {
				openImagePicker(plan);
				return;
			}

			if (target && target.closest('[data-foodord-reservation-floor-plan-canvas].is-empty')) {
				openImagePicker(plan);
				return;
			}

			if (target && target.closest('[data-foodord-reservation-floor-plan-remove]')) {
				updatePlanImage(plan, 0, '');
			}
		});

		enabled.addEventListener('change', syncEnabledState);
		syncEnabledState();
		syncLayouts();

		root.foodordTableSelectionDestroy = () => {
			if (imageMarkerEditor) {
				imageMarkerEditor.destroy();
			}
			if (gridBuilder) {
				gridBuilder.destroy();
			}
			if (mediaFrame) {
				mediaFrame.off('select');
				mediaFrame.close();
			}
			activePlan = null;
		};
	};

	const captureTableSelectionState = (root) => {
		const enabled = root.querySelector('[data-foodord-reservation-table-selection-enabled]');
		const frontendEnabled = root.querySelector('[data-foodord-reservation-table-selection-frontend-enabled]');
		const layoutsField = root.querySelector('[data-foodord-reservation-table-selection-layouts]');
		const activeTab = root.querySelector('[data-foodord-reservation-floor-plan-tab].is-active');
		const imageUrls = {};

		root.querySelectorAll('[data-foodord-reservation-floor-plan]').forEach((plan) => {
			const floorId = plan.dataset.foodordReservationFloorPlan || '';
			const image = plan.querySelector('[data-foodord-reservation-floor-plan-image]');

			if (floorId && image && !image.hidden && (image.currentSrc || image.src)) {
				imageUrls[floorId] = image.currentSrc || image.src;
			}
		});

		return {
			enabled: enabled ? enabled.checked : false,
			frontendEnabled: frontendEnabled ? frontendEnabled.checked : false,
			layouts: parseJsonObject(layoutsField ? layoutsField.value : '', {}),
			activeFloorId: activeTab ? activeTab.dataset.foodordReservationFloorPlanTab || '' : '',
			imageUrls
		};
	};

	const mergeTableSelectionLayouts = (root, serverLayouts, currentLayouts) => {
		const mergedLayouts = {};

		root.querySelectorAll('[data-foodord-reservation-floor-plan]').forEach((plan) => {
			const floorId = plan.dataset.foodordReservationFloorPlan || '';
			const serverLayout = serverLayouts[floorId] && typeof serverLayouts[floorId] === 'object' ? serverLayouts[floorId] : {};
			const hasCurrentLayout = Object.prototype.hasOwnProperty.call(currentLayouts, floorId);
			const currentLayout = hasCurrentLayout && typeof currentLayouts[floorId] === 'object' ? currentLayouts[floorId] : {};
			const serverTables = serverLayout.tables && typeof serverLayout.tables === 'object' ? serverLayout.tables : {};
			const currentTables = currentLayout.tables && typeof currentLayout.tables === 'object' ? currentLayout.tables : {};
			const serverGridTables = serverLayout.grid_tables && typeof serverLayout.grid_tables === 'object' ? serverLayout.grid_tables : {};
			const currentGridTables = currentLayout.grid_tables && typeof currentLayout.grid_tables === 'object' ? currentLayout.grid_tables : {};
			const tables = {};
			const gridTables = {};

			plan.querySelectorAll('[data-foodord-reservation-floor-plan-marker]').forEach((marker) => {
				const tableId = marker.dataset.foodordReservationFloorPlanMarker || '';
				const position = currentTables[tableId] || serverTables[tableId];

				if (!position || !Number.isFinite(Number(position.x)) || !Number.isFinite(Number(position.y))) {
					return;
				}

				tables[tableId] = {
					x: Number(position.x),
					y: Number(position.y),
					width: Number(position.width) || 9,
					height: Number(position.height) || 7,
					rotation: Number(position.rotation) || 0,
					shape: ['rectangle', 'square', 'round'].includes(String(position.shape || ''))
						? String(position.shape)
						: 'rectangle',
					fill: String(position.fill || ''),
					text_color: String(position.text_color || '')
				};
			});

			plan.querySelectorAll('[data-foodord-reservation-grid-add-table]').forEach((option) => {
				const tableId = option.dataset.foodordReservationGridAddTable || '';
				const geometry = currentGridTables[tableId] || serverGridTables[tableId];

				if (!geometry || typeof geometry !== 'object') {
					return;
				}

				gridTables[tableId] = {
					x: Number(geometry.x),
					y: Number(geometry.y),
					width: Number(geometry.width),
					height: Number(geometry.height),
					rotation: Number(geometry.rotation) || 0,
					shape: String(geometry.shape || 'rectangle')
				};
			});

			const imageId = Number(hasCurrentLayout ? currentLayout.image_id : serverLayout.image_id) || 0;
			const mode = (hasCurrentLayout ? currentLayout.mode : serverLayout.mode) === 'grid' ? 'grid' : 'image';
			const objects = hasCurrentLayout && currentLayout.objects && typeof currentLayout.objects === 'object'
				? currentLayout.objects
				: serverLayout.objects && typeof serverLayout.objects === 'object'
					? serverLayout.objects
					: {};
			const snapToGrid = hasCurrentLayout
				? currentLayout.snap_to_grid !== false
				: serverLayout.snap_to_grid !== false;
			const gridDensity = (hasCurrentLayout ? currentLayout.grid_density : serverLayout.grid_density) === 'fine'
				? 'fine'
				: 'coarse';
			if (imageId > 0 || Object.keys(tables).length || Object.keys(gridTables).length || Object.keys(objects).length || mode === 'grid') {
				mergedLayouts[floorId] = {
					mode,
					image_id: imageId,
					tables,
					grid_tables: gridTables,
					objects,
					snap_to_grid: snapToGrid,
					grid_density: gridDensity
				};
			}
		});

		return mergedLayouts;
	};

	const restoreTableSelectionImages = (root, state) => {
		root.querySelectorAll('[data-foodord-reservation-floor-plan]').forEach((plan) => {
			const floorId = plan.dataset.foodordReservationFloorPlan || '';
			if (!Object.prototype.hasOwnProperty.call(state.layouts, floorId)) {
				return;
			}

			const layout = state.layouts[floorId] || {};
			const imageUrl = state.imageUrls[floorId] || '';
			const image = plan.querySelector('[data-foodord-reservation-floor-plan-image]');
			const canvas = plan.querySelector('[data-foodord-reservation-floor-plan-canvas]');
			const empty = plan.querySelector('[data-foodord-reservation-floor-plan-empty]');
			const imageId = Number(layout.image_id) || 0;

			if (imageId <= 0) {
				if (image) {
					image.removeAttribute('src');
					image.hidden = true;
				}
				if (canvas) {
					canvas.classList.add('is-empty');
				}
				if (empty) {
					empty.hidden = false;
				}
				return;
			}

			if (imageUrl) {
				if (image) {
					image.src = imageUrl;
					image.hidden = false;
				}
				if (canvas) {
					canvas.classList.remove('is-empty');
				}
				if (empty) {
					empty.hidden = true;
				}
			}
		});
	};

	const refreshTableSelectionSettings = (html) => {
		const currentRoot = document.querySelector('[data-foodord-reservation-table-selection]');
		if (!currentRoot || !html) {
			return;
		}

		const state = captureTableSelectionState(currentRoot);
		const template = document.createElement('template');
		template.innerHTML = String(html).trim();

		const nextRoot = template.content.querySelector('[data-foodord-reservation-table-selection]');
		if (!nextRoot) {
			return;
		}

		const nextLayoutsField = nextRoot.querySelector('[data-foodord-reservation-table-selection-layouts]');
		const nextEnabled = nextRoot.querySelector('[data-foodord-reservation-table-selection-enabled]');
		const nextFrontendEnabled = nextRoot.querySelector('[data-foodord-reservation-table-selection-frontend-enabled]');
		const serverLayouts = parseJsonObject(nextLayoutsField ? nextLayoutsField.value : '', {});
		const mergedLayouts = mergeTableSelectionLayouts(nextRoot, serverLayouts, state.layouts);

		if (nextLayoutsField) {
			nextLayoutsField.value = JSON.stringify(mergedLayouts);
		}
		if (nextEnabled) {
			nextEnabled.checked = state.enabled;
		}
		if (nextFrontendEnabled) {
			nextFrontendEnabled.checked = state.frontendEnabled;
		}

		restoreTableSelectionImages(nextRoot, state);

		if (typeof currentRoot.foodordTableSelectionDestroy === 'function') {
			currentRoot.foodordTableSelectionDestroy();
		}
		currentRoot.replaceWith(nextRoot);
		initTableSelectionSettings(nextRoot);

		if (state.activeFloorId) {
			const activeTab = Array.from(nextRoot.querySelectorAll('[data-foodord-reservation-floor-plan-tab]')).find((tab) => {
				return tab.dataset.foodordReservationFloorPlanTab === state.activeFloorId;
			});

			if (activeTab) {
				activeTab.click();
			}
		}
	};

	const syncManualReservationActualDate = (field) => {
		const form = field ? field.closest('.foodord-reservations-manual-form') : null;
		const actualDate = form ? form.querySelector('[data-foodord-manual-reservation-actual-date]') : null;
		const selectedOption = field && field.selectedIndex >= 0 ? field.options[field.selectedIndex] : null;

		if (actualDate) {
			actualDate.value = selectedOption ? selectedOption.dataset.reservationDate || '' : '';
		}
	};

	const setManualReservationTimeOptions = (field, times, placeholder, slots = []) => {
		if (!field) {
			return;
		}

		field.textContent = '';

		const placeholderOption = document.createElement('option');
		placeholderOption.value = '';
		placeholderOption.textContent = placeholder || i18n.selectTime || 'Select time';
		field.appendChild(placeholderOption);

		const normalizedSlots = Array.isArray(slots) && slots.length
			? slots
			: (times || []).map((time) => ({ time }));

		normalizedSlots.forEach((slot) => {
			const time = String(slot && slot.time ? slot.time : '');
			if (!time) {
				return;
			}
			const option = document.createElement('option');
			option.value = time;
			option.textContent = time;
			option.dataset.reservationDate = String(slot && slot.date ? slot.date : '');
			field.appendChild(option);
		});

		field.disabled = normalizedSlots.length < 1;
		syncManualReservationActualDate(field);
	};

	const setManualReservationDurationOptions = (field, options, defaultDuration, placeholder) => {
		if (!field) {
			return;
		}

		field.textContent = '';
		const placeholderOption = document.createElement('option');
		placeholderOption.value = '';
		placeholderOption.textContent = placeholder || i18n.selectDuration || 'Select duration';
		field.appendChild(placeholderOption);

		const normalizedOptions = Array.isArray(options)
			? options.filter((option) => {
				return option && Number.parseInt(option.value, 10) > 0 && String(option.label || '').trim();
			})
			: [];
		const defaultValue = String(Number.parseInt(defaultDuration, 10) || '');
		if (!normalizedOptions.some((option) => String(option.value) === defaultValue)) {
			field.disabled = true;
			return;
		}

		normalizedOptions.forEach((optionData) => {
			const option = document.createElement('option');
			option.value = String(optionData.value);
			option.textContent = String(optionData.label);
			field.appendChild(option);
		});
		field.value = defaultValue;
		field.disabled = false;
	};

	let manualReservationTableOptions = new Map();

	const setManualReservationTableOptions = (field, tables, placeholder) => {
		manualReservationTableOptions = new Map();
		if (!field) {
			return;
		}

		field.textContent = '';
		const placeholderOption = document.createElement('option');
		placeholderOption.value = '';
		placeholderOption.textContent = placeholder || i18n.selectTable || 'Select table';
		field.appendChild(placeholderOption);

		const groupedTables = new Map();
		const ungroupedTables = [];
		const compareLabels = (first, second) =>
			first.localeCompare(second, undefined, {
				numeric: true,
				sensitivity: 'base',
			});

		(Array.isArray(tables) ? tables : []).forEach((table) => {
			const tableId = Number.parseInt(table && table.id, 10);
			const label = String(
				table && table.table_label ? table.table_label : table && table.label ? table.label : ''
			).trim();
			const floorLabel = String(table && table.floor_label ? table.floor_label : '').trim();
			if (tableId < 1 || !label || !Array.isArray(table.duration_options)) {
				return;
			}

			const key = String(tableId);
			manualReservationTableOptions.set(key, table);
			const optionData = { key, label };

			if (!floorLabel) {
				ungroupedTables.push(optionData);
				return;
			}

			if (!groupedTables.has(floorLabel)) {
				groupedTables.set(floorLabel, []);
			}
			groupedTables.get(floorLabel).push(optionData);
		});

		const appendOption = (parent, optionData) => {
			const option = document.createElement('option');
			option.value = optionData.key;
			option.textContent = optionData.label;
			parent.appendChild(option);
		};

		Array.from(groupedTables.entries())
			.sort(([firstFloor], [secondFloor]) => compareLabels(firstFloor, secondFloor))
			.forEach(([floorLabel, floorTables]) => {
				const group = document.createElement('optgroup');
				group.label = floorLabel;
				floorTables
					.sort((firstTable, secondTable) => compareLabels(firstTable.label, secondTable.label))
					.forEach((optionData) => appendOption(group, optionData));
				field.appendChild(group);
			});

		ungroupedTables
			.sort((firstTable, secondTable) => compareLabels(firstTable.label, secondTable.label))
			.forEach((optionData) => appendOption(field, optionData));

		if (manualReservationTableOptions.size < 1) {
			placeholderOption.textContent = placeholder || i18n.noTablesAvailable || 'No tables available';
		}
		field.disabled = manualReservationTableOptions.size < 1;
	};

	const syncManualReservationDurationOptions = (modal) => {
		const table = modal ? modal.querySelector('[data-foodord-manual-reservation-table]') : null;
		const duration = modal ? modal.querySelector('[data-foodord-manual-reservation-duration]') : null;
		const selectedTable = table ? manualReservationTableOptions.get(table.value) : null;
		setManualReservationDurationOptions(
			duration,
			selectedTable ? selectedTable.duration_options : [],
			selectedTable ? selectedTable.default_duration_minutes : 0,
			i18n.selectDuration || 'Select duration'
		);
	};

	let manualReservationTimeRequestId = 0;
	let manualReservationTableRequestId = 0;

	const loadManualReservationTimes = (modal) => {
		const form = modal ? modal.querySelector('.foodord-reservations-manual-form') : null;
		const date = form ? form.querySelector('[name="reservation_date"]') : null;
		const partySize = form ? form.querySelector('[name="party_size"]') : null;
		const time = form ? form.querySelector('[data-foodord-manual-reservation-time]') : null;
		const table = form ? form.querySelector('[data-foodord-manual-reservation-table]') : null;
		const duration = form ? form.querySelector('[data-foodord-manual-reservation-duration]') : null;
		const nonce = form ? form.querySelector('[name="_wpnonce"]') : null;

		manualReservationTableRequestId += 1;
		setManualReservationTableOptions(table, [], i18n.selectTable || 'Select table');
		setManualReservationDurationOptions(duration, [], 0, i18n.selectDuration || 'Select duration');

		if (!ajaxUrl || !form || !date || !time || !nonce || !date.value) {
			setManualReservationTimeOptions(time, [], i18n.selectTime || 'Select time');
			return;
		}

		const requestId = manualReservationTimeRequestId + 1;
		manualReservationTimeRequestId = requestId;

		setManualReservationTimeOptions(time, [], i18n.selectTime || 'Select time');

		const payload = new FormData();
		payload.append('action', 'foodord_get_manual_reservation_times');
		payload.append('_wpnonce', nonce.value || '');
		payload.append('reservation_date', date.value || '');
		payload.append('party_size', partySize ? partySize.value || '0' : '0');

		fetch(ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			body: payload
		})
			.then((response) => response.json())
			.then((result) => {
				if (requestId !== manualReservationTimeRequestId) {
					return;
				}

				const times = result && result.success && result.data && Array.isArray(result.data.times) ? result.data.times : [];
				const slots = result && result.success && result.data && Array.isArray(result.data.slots) ? result.data.slots : [];
				setManualReservationTimeOptions(time, times, times.length ? i18n.selectTime || 'Select time' : i18n.noTimesAvailable || 'No times available', slots);
			})
			.catch(() => {
				if (requestId === manualReservationTimeRequestId) {
					setManualReservationTimeOptions(time, [], i18n.noTimesAvailable || 'No times available');
				}
			});
	};

	const loadManualReservationTables = (modal) => {
		const form = modal ? modal.querySelector('.foodord-reservations-manual-form') : null;
		const actualDate = form ? form.querySelector('[data-foodord-manual-reservation-actual-date]') : null;
		const time = form ? form.querySelector('[data-foodord-manual-reservation-time]') : null;
		const partySize = form ? form.querySelector('[name="party_size"]') : null;
		const table = form ? form.querySelector('[data-foodord-manual-reservation-table]') : null;
		const duration = form ? form.querySelector('[data-foodord-manual-reservation-duration]') : null;
		const nonce = form ? form.querySelector('[name="_wpnonce"]') : null;
		const requestId = manualReservationTableRequestId + 1;
		manualReservationTableRequestId = requestId;

		setManualReservationTableOptions(table, [], i18n.selectTable || 'Select table');
		setManualReservationDurationOptions(duration, [], 0, i18n.selectDuration || 'Select duration');
		if (!ajaxUrl || !form || !actualDate || !time || !partySize || !nonce || !actualDate.value || !time.value) {
			return;
		}

		const payload = new FormData();
		payload.append('action', 'foodord_get_manual_reservation_tables');
		payload.append('_wpnonce', nonce.value || '');
		payload.append('reservation_date', actualDate.value);
		payload.append('reservation_time', time.value);
		payload.append('party_size', partySize.value || '0');

		fetch(ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			body: payload
		})
			.then((response) => response.json())
			.then((result) => {
				if (requestId !== manualReservationTableRequestId) {
					return;
				}

				const tables = result && result.success && result.data && Array.isArray(result.data.tables) ? result.data.tables : [];
				setManualReservationTableOptions(
					table,
					tables,
					tables.length ? i18n.selectTable || 'Select table' : i18n.noTablesAvailable || 'No tables available'
				);
			})
			.catch(() => {
				if (requestId === manualReservationTableRequestId) {
					setManualReservationTableOptions(table, [], i18n.noTablesAvailable || 'No tables available');
				}
			});
	};

	const setFloorPanelOpen = (isOpen, shouldFocus) => {
		const toggle = getFloorToggle();
		const panel = getFloorPanel();

		if (!panel) {
			return;
		}

		if (toggle) {
			toggle.setAttribute('aria-expanded', String(isOpen));
		}

		panel.hidden = !isOpen;

		if (!shouldFocus) {
			return;
		}

		if (isOpen) {
			const firstInput = panel.querySelector('input:not([type="hidden"]), select, textarea, button');

			if (firstInput) {
				firstInput.focus({ preventScroll: true });
			}

			return;
		}

		if (toggle) {
			toggle.focus({ preventScroll: true });
		}
	};

	const scrollToEditorPanel = (panel) => {
		if (!panel || panel.hidden) {
			return;
		}

		window.requestAnimationFrame(() => {
			const adminBar = document.getElementById('wpadminbar');
			const adminBarHeight = adminBar ? adminBar.getBoundingClientRect().height : 0;
			const panelTop = window.scrollY + panel.getBoundingClientRect().top;
			const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

			window.scrollTo({
				top: Math.max(0, panelTop - adminBarHeight - 16),
				behavior: reduceMotion ? 'auto' : 'smooth'
			});
		});
	};

	const setFloorPanelTitle = (mode) => {
		const panel = getFloorPanel();
		const title = panel ? panel.querySelector('.foodord-reservations-floor-panel__title') : null;

		if (!panel || !title) {
			return;
		}

		title.textContent = mode === 'edit' ? panel.dataset.editTitle || title.textContent : panel.dataset.addTitle || title.textContent;
	};

	const setTablePanelOpen = (isOpen, shouldFocus) => {
		const toggle = getTableToggle();
		const panel = getTablePanel();

		if (!panel) {
			return;
		}

		if (toggle) {
			toggle.setAttribute('aria-expanded', String(isOpen));
		}

		panel.hidden = !isOpen;

		if (!shouldFocus) {
			return;
		}

		if (isOpen) {
			const firstInput = panel.querySelector('input:not([type="hidden"]), select, textarea, button');

			if (firstInput) {
				firstInput.focus({ preventScroll: true });
			}

			return;
		}

		if (toggle) {
			toggle.focus({ preventScroll: true });
		}
	};

	const setTablePanelTitle = (mode) => {
		const panel = getTablePanel();
		const title = panel ? panel.querySelector('.foodord-reservations-table-panel__title') : null;

		if (!panel || !title) {
			return;
		}

		title.textContent = mode === 'edit' ? panel.dataset.editTitle || title.textContent : panel.dataset.addTitle || title.textContent;
	};

	const resetTableForm = () => {
		const form = getTableForm();
		const cancel = document.querySelector('[data-foodord-reservations-table-cancel]');

		if (!form) {
			return;
		}

		form.reset();
		const tableId = form.querySelector('[name="table_id"]');
		if (tableId) {
			tableId.value = '0';
		}

		if (cancel) {
			delete cancel.dataset.cancelUrl;
		}

		setTablePanelTitle('add');
		setFormSubmitMode(form, 'add');
	};

	const initTableFormToggle = () => {
		const toggle = getTableToggle();
		const panel = getTablePanel();

		if (!panel) {
			return;
		}

		const cancel = panel.querySelector('[data-foodord-reservations-table-cancel]');
		const form = panel.querySelector('#foodord-reservation-table-form');

		if (toggle) {
			toggle.addEventListener('click', () => {
				const isOpen = toggle.getAttribute('aria-expanded') === 'true';

				if (!isOpen) {
					resetTableForm();
				}

				setTablePanelOpen(!isOpen, true);
			});
		}

		if (cancel) {
			cancel.addEventListener('click', () => {
				if (cancel.dataset.cancelUrl) {
					window.location.href = cancel.dataset.cancelUrl;
					return;
				}

				if (form) {
					resetTableForm();
				}

				setTablePanelOpen(false, true);
			});
		}
	};

	const initTableDeleteConfirm = () => {
		document.addEventListener('submit', (event) => {
			const form = event.target instanceof HTMLFormElement ? event.target : null;

			if (!form || !form.matches('[data-foodord-reservation-table-delete-form]')) {
				return;
			}

			const message = form.dataset.confirmMessage || '';

			if (window.confirm(message)) {
				return;
			}

			event.preventDefault();
		});
	};

	const initReservationBulkActions = () => {
		document.querySelectorAll('[data-foodord-reservation-bulk-form]').forEach((form) => {
			const selectAll = document.querySelector('[data-foodord-reservation-select-all]');
			const action = form.querySelector('[data-foodord-reservation-bulk-action]');
			const applyButton = form.querySelector('[type="submit"]');
			const checkboxes = Array.from(document.querySelectorAll(`[data-foodord-reservation-select][form="${form.id}"]`));
			const availableCheckboxes = checkboxes.filter((checkbox) => !checkbox.disabled);

			const syncState = () => {
				const selectedCount = availableCheckboxes.filter((checkbox) => checkbox.checked).length;

				if (selectAll) {
					selectAll.checked = availableCheckboxes.length > 0 && selectedCount === availableCheckboxes.length;
					selectAll.indeterminate = selectedCount > 0 && selectedCount < availableCheckboxes.length;
					selectAll.disabled = availableCheckboxes.length < 1;
				}
				if (applyButton) {
					applyButton.disabled = selectedCount < 1;
				}
			};

			if (selectAll) {
				selectAll.addEventListener('change', () => {
					availableCheckboxes.forEach((checkbox) => {
						checkbox.checked = selectAll.checked;
					});
					syncState();
				});
			}

			availableCheckboxes.forEach((checkbox) => {
				checkbox.addEventListener('change', syncState);
			});

			form.addEventListener('submit', (event) => {
				const hasSelection = availableCheckboxes.some((checkbox) => checkbox.checked);
				if (!hasSelection) {
					event.preventDefault();
					return;
				}

				if (!action || action.value !== 'delete') {
					return;
				}

				if (!window.confirm(form.dataset.deleteConfirmMessage || '')) {
					event.preventDefault();
				}
			});

			syncState();
		});
	};

	const setCancellationModalOpen = (isOpen) => {
		const modal = getCancellationModal();

		if (!modal) {
			return;
		}

		window.clearTimeout(cancellationModalCloseTimer);

		if (isOpen) {
			modal.hidden = false;
			document.body.classList.add('foodord-reservations-modal-open');
			window.requestAnimationFrame(() => {
				modal.classList.add('is-open');
			});
			return;
		}

		modal.classList.remove('is-open');
		cancellationModalCloseTimer = window.setTimeout(() => {
			modal.hidden = true;
			document.body.classList.remove('foodord-reservations-modal-open');
		}, manualReservationModalTransitionMs);
	};

	const openCancellationModal = (form) => {
		const modal = getCancellationModal();
		const field = modal ? modal.querySelector('[data-foodord-reservation-cancellation-modal-reason]') : null;
		const refundWarning = modal ? modal.querySelector('[data-foodord-reservation-cancellation-refund]') : null;
		const hiddenReason = form.querySelector('[data-foodord-reservation-cancellation-reason-value]');

		if (!modal || !field || !hiddenReason) {
			return;
		}

		activeCancellationForm = form;
		field.value = hiddenReason.value || '';
		if (refundWarning) {
			refundWarning.hidden = form.dataset.foodordReservationRefundWarning !== '1';
		}
		setCancellationModalOpen(true);
		field.focus({ preventScroll: true });
	};

	const closeCancellationModal = (shouldRestoreStatus) => {
		const form = activeCancellationForm;

		if (form && shouldRestoreStatus) {
			const select = form.querySelector('[data-foodord-reservation-status-select]');

			if (select) {
				select.value = select.dataset.foodordReservationPreviousStatus || select.value;
			}
		}

		activeCancellationForm = null;
		setCancellationModalOpen(false);
	};

	const initCancellationReasonFields = () => {
		document.querySelectorAll('[data-foodord-reservation-status-form]').forEach((form) => {
			const select = form.querySelector('[data-foodord-reservation-status-select]');

			if (!select) {
				return;
			}

			select.dataset.foodordReservationPreviousStatus = select.value;

			select.addEventListener('change', () => {
				if (select.value === 'cancelled') {
					openCancellationModal(form);
					return;
				}

				select.dataset.foodordReservationPreviousStatus = select.value;
			});

			form.addEventListener('submit', (event) => {
				if (form.dataset.foodordReservationCancellationConfirmed === '1') {
					delete form.dataset.foodordReservationCancellationConfirmed;
					return;
				}

				if (select.value !== 'cancelled') {
					return;
				}

				event.preventDefault();
				openCancellationModal(form);
			});
		});

		const modal = getCancellationModal();
		const reason = modal ? modal.querySelector('[data-foodord-reservation-cancellation-modal-reason]') : null;
		const confirm = modal ? modal.querySelector('[data-foodord-reservation-cancellation-modal-confirm]') : null;

		if (!modal || !reason || !confirm) {
			return;
		}

		modal.querySelectorAll('[data-foodord-reservation-cancellation-modal-close]').forEach((button) => {
			button.addEventListener('click', () => {
				closeCancellationModal(true);
			});
		});

		confirm.addEventListener('click', () => {
			if (!activeCancellationForm) {
				closeCancellationModal(false);
				return;
			}

			const hiddenReason = activeCancellationForm.querySelector('[data-foodord-reservation-cancellation-reason-value]');

			if (hiddenReason) {
				hiddenReason.value = reason.value;
			}

			activeCancellationForm.dataset.foodordReservationCancellationConfirmed = '1';
			if (typeof activeCancellationForm.requestSubmit === 'function') {
				activeCancellationForm.requestSubmit();
			} else {
				HTMLFormElement.prototype.submit.call(activeCancellationForm);
			}
			closeCancellationModal(false);
		});
	};

	const setManualReservationNoteOpen = (modal, isOpen, shouldFocus) => {
		const toggle = modal ? modal.querySelector('[data-foodord-manual-reservation-note-toggle]') : null;
		const panel = modal ? modal.querySelector('[data-foodord-manual-reservation-note-panel]') : null;
		const note = modal ? modal.querySelector('#foodord-manual-reservation-note') : null;

		if (!toggle || !panel) {
			return;
		}

		toggle.setAttribute('aria-expanded', String(isOpen));
		panel.hidden = !isOpen;

		if (isOpen && shouldFocus && note) {
			note.focus({ preventScroll: true });
		}
	};

	const setManualReservationModalOpen = (isOpen, shouldFocus) => {
		const modal = getManualReservationModal();
		const openButton = getManualReservationOpenButton();
		const form = modal ? modal.querySelector('.foodord-reservations-manual-form') : null;

		if (!modal) {
			return;
		}

		if (manualReservationModalCloseTimer) {
			window.clearTimeout(manualReservationModalCloseTimer);
			manualReservationModalCloseTimer = 0;
		}

		if (isOpen) {
			modal.hidden = false;
			document.body.classList.add('foodord-reservations-modal-open');
			window.requestAnimationFrame(() => {
				modal.classList.add('is-open');
			});
		} else {
			manualReservationTimeRequestId += 1;
			manualReservationTableRequestId += 1;
			hideDatePicker();
			modal.classList.remove('is-open');

			manualReservationModalCloseTimer = window.setTimeout(() => {
				modal.hidden = true;
				document.body.classList.remove('foodord-reservations-modal-open');
				manualReservationModalCloseTimer = 0;

				if (form) {
					form.reset();
				}
				setManualReservationNoteOpen(modal, false, false);
				setManualReservationTimeOptions(modal.querySelector('[data-foodord-manual-reservation-time]'), [], i18n.selectTime || 'Select time');
				setManualReservationTableOptions(modal.querySelector('[data-foodord-manual-reservation-table]'), [], i18n.selectTable || 'Select table');
				setManualReservationDurationOptions(modal.querySelector('[data-foodord-manual-reservation-duration]'), [], 0, i18n.selectDuration || 'Select duration');

				if (shouldFocus && openButton) {
					openButton.focus({ preventScroll: true });
				}
			}, manualReservationModalTransitionMs);
		}

		if (!shouldFocus) {
			return;
		}

		if (isOpen) {
			initDatePickers(modal);
			loadManualReservationTimes(modal);
			const firstField = modal.querySelector('.foodord-reservations-modal__dialog');

			if (firstField) {
				firstField.focus({ preventScroll: true });
			}

			return;
		}
	};

	const initManualReservationModal = () => {
		const modal = getManualReservationModal();
		const openButton = getManualReservationOpenButton();

		if (!modal || !openButton) {
			return;
		}

		openButton.addEventListener('click', () => {
			setManualReservationModalOpen(true, true);
		});

		modal.querySelectorAll('[data-foodord-manual-reservation-close]').forEach((button) => {
			button.addEventListener('click', () => {
				setManualReservationModalOpen(false, true);
			});
		});

		const noteToggle = modal.querySelector('[data-foodord-manual-reservation-note-toggle]');
		const notePanel = modal.querySelector('[data-foodord-manual-reservation-note-panel]');
		if (noteToggle && notePanel) {
			noteToggle.addEventListener('click', () => {
				setManualReservationNoteOpen(modal, notePanel.hidden, true);
			});
		}

		const date = modal.querySelector('[name="reservation_date"]');
		const partySize = modal.querySelector('[name="party_size"]');
		const time = modal.querySelector('[data-foodord-manual-reservation-time]');
		const table = modal.querySelector('[data-foodord-manual-reservation-table]');
		[date, partySize].forEach((field) => {
			if (!field) {
				return;
			}

			field.addEventListener('change', () => {
				loadManualReservationTimes(modal);
			});
		});
		if (time) {
			time.addEventListener('change', () => {
				syncManualReservationActualDate(time);
				loadManualReservationTables(modal);
			});
		}
		if (table) {
			table.addEventListener('change', () => {
				syncManualReservationDurationOptions(modal);
			});
		}

		const form = modal.querySelector('.foodord-reservations-manual-form');
		const submitButton = modal.querySelector('[data-foodord-manual-reservation-submit]');
		if (form && submitButton) {
			form.addEventListener('submit', (event) => {
				if (submitButton.classList.contains('is-loading')) {
					event.preventDefault();
					return;
				}

				submitButton.disabled = true;
				submitButton.classList.add('is-loading');
				submitButton.setAttribute('aria-busy', 'true');
			});
		}

		document.addEventListener('keydown', (event) => {
			if (event.key !== 'Escape' || modal.hidden) {
				return;
			}

			setManualReservationModalOpen(false, true);
		});
	};

	const initBannerPicker = () => {
		const root = document.querySelector('[data-foodord-reservation-banner-picker]');

		if (!root || !window.wp || !window.wp.media) {
			return;
		}

		const imageId = root.querySelector('[data-foodord-reservation-banner-image-id]');
		const disabled = root.querySelector('[data-foodord-reservation-banner-disabled]');
		const previewWrap = root.querySelector('.foodord-reservations-banner-form__preview');
		const preview = root.querySelector('[data-foodord-reservation-banner-preview]');
		const selectButton = root.querySelector('[data-foodord-reservation-banner-select]');
		const removeButton = root.querySelector('[data-foodord-reservation-banner-remove]');
		const defaultUrl = root.dataset.defaultUrl || '';
		let mediaFrame = null;

		if (!imageId || !disabled || !previewWrap || !preview || !selectButton || !removeButton) {
			return;
		}

		const openMediaFrame = () => {
			if (mediaFrame) {
				mediaFrame.open();
				return;
			}

			mediaFrame = window.wp.media({
				title: root.dataset.title || '',
				button: {
					text: root.dataset.button || ''
				},
				library: {
					type: 'image'
				},
				multiple: false
			});

			mediaFrame.on('select', () => {
				const attachment = mediaFrame.state().get('selection').first();

				if (!attachment) {
					return;
				}

				const data = attachment.toJSON();
				const sizes = data.sizes || {};
				const selectedUrl = sizes.large && sizes.large.url ? sizes.large.url : data.url;

				imageId.value = data.id || '';
				disabled.value = '0';
				preview.src = selectedUrl || defaultUrl;
				preview.hidden = false;
				previewWrap.classList.remove('is-empty');
			});

			mediaFrame.open();
		};

		selectButton.addEventListener('click', openMediaFrame);
		removeButton.addEventListener('click', () => {
			imageId.value = '0';
			disabled.value = '1';
			preview.src = defaultUrl;
			preview.hidden = true;
			previewWrap.classList.add('is-empty');
		});
	};

	const showAjaxNotice = (message, type) => {
		const notice = document.querySelector('[data-foodord-reservations-ajax-notice]');
		const messageTarget = notice ? notice.querySelector('[data-foodord-reservations-ajax-notice-message]') : null;

		if (!notice || !messageTarget) {
			return;
		}

		notice.classList.remove('notice-success', 'notice-error');
		notice.classList.add(type === 'error' ? 'notice-error' : 'notice-success');
		messageTarget.textContent = message || '';
		notice.hidden = !message;
	};

	const getSubmitButton = (form, submitter) => {
		if (submitter instanceof HTMLButtonElement || submitter instanceof HTMLInputElement) {
			return submitter;
		}

		if (form.id) {
			return document.querySelector(`[form="${form.id}"][type="submit"]`);
		}

		return form.querySelector('[type="submit"]');
	};

	const setFormSubmitMode = (form, mode) => {
		const button = form ? getSubmitButton(form, null) : null;
		if (!button) {
			return;
		}

		const label = mode === 'edit' ? button.dataset.foodordSaveLabel : button.dataset.foodordAddLabel;
		if (!label) {
			return;
		}

		if (button instanceof HTMLInputElement) {
			button.value = label;
			return;
		}

		button.textContent = label;
	};

	const setSubmitBusy = (button, isBusy) => {
		if (!button) {
			return;
		}

		button.disabled = isBusy;
		button.classList.toggle('is-loading', isBusy);
	};

	const getCurrentManagementPage = (pageKey) => {
		const selector = managementPageSelectors[pageKey] || '';
		const current = selector ? document.querySelector(`${selector} .page-numbers.current`) : null;
		const page = current ? Number.parseInt(current.textContent || '', 10) : 1;

		return Number.isInteger(page) && page > 0 ? page : 1;
	};

	const setCurrentManagementPage = (formData, pageKey) => {
		const page = getCurrentManagementPage(pageKey);

		if (page > 1) {
			formData.set(pageKey, String(page));
			return;
		}

		formData.delete(pageKey);
	};

	const postForm = (form) => {
		if (!ajaxUrl) {
			return Promise.reject(new Error(i18n.saveError || ''));
		}

		const formData = new FormData(form);
		const currentQuery = new URLSearchParams(window.location.search);

		managementFilterKeys.forEach((key) => {
			const value = currentQuery.get(key);
			if (value) {
				formData.set(key, value);
			}
		});
		managementPageKeys.forEach((key) => setCurrentManagementPage(formData, key));

		return fetch(ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			body: formData
		}).then((response) => response.json());
	};

	const postTableFilters = (form) => {
		if (!ajaxUrl || !tableFilterNonce) {
			return Promise.reject(new Error(i18n.filterError || ''));
		}

		const formData = new FormData(form);
		formData.set('action', 'foodord_filter_reservation_tables');
		formData.set('_wpnonce', tableFilterNonce);
		setCurrentManagementPage(formData, 'reservation_floor_page');

		return fetch(ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			body: formData
		}).then((response) => response.json());
	};

	const postManagementPage = (url, listType) => {
		if (!ajaxUrl || !managementPaginationNonce) {
			return Promise.reject(new Error(i18n.paginationError || ''));
		}

		const formData = new FormData();
		formData.set('action', 'foodord_paginate_reservation_management');
		formData.set('_wpnonce', managementPaginationNonce);
		formData.set('list_type', listType);

		managementQueryKeys.forEach((key) => {
			const value = url.searchParams.get(key);
			if (value) {
				formData.set(key, value);
			}
		});

		const preservePageKey = listType === 'floors' ? 'reservation_table_page' : 'reservation_floor_page';
		setCurrentManagementPage(formData, preservePageKey);

		return fetch(ajaxUrl, {
			method: 'POST',
			credentials: 'same-origin',
			body: formData
		}).then((response) => response.json());
	};

	const updateTableFilterUrl = (form) => {
		const url = new URL(window.location.href);
		const floorField = form.querySelector('[name="reservation_table_floor"]');
		const searchField = form.querySelector('[name="reservation_table_search"]');
		const floorId = floorField ? floorField.value : '0';
		const search = searchField ? searchField.value.trim() : '';

		if (floorId && floorId !== '0') {
			url.searchParams.set('reservation_table_floor', floorId);
		} else {
			url.searchParams.delete('reservation_table_floor');
		}

		if (search) {
			url.searchParams.set('reservation_table_search', search);
		} else {
			url.searchParams.delete('reservation_table_search');
		}

		managementPageKeys.forEach((key) => url.searchParams.delete(key));
		window.history.replaceState(window.history.state, '', url.toString());
	};

	const replaceListHtml = (selector, html) => {
		const target = document.querySelector(selector);

		if (!target || typeof html !== 'string') {
			return;
		}

		target.innerHTML = html;
	};

	const updateFloorOptions = (floors) => {
		const tableForm = getTableForm();
		const floorSelect = tableForm ? tableForm.querySelector('[name="floor_id"]') : null;
		const tableToggle = getTableToggle();

		if (!Array.isArray(floors)) {
			return;
		}

		const hasFloors = floors.length > 0;

		if (tableToggle) {
			tableToggle.disabled = !hasFloors;
		}

		if (!hasFloors) {
			setTablePanelOpen(false, false);
		}

		if (!floorSelect) {
			return;
		}

		const currentValue = floorSelect.value;
		floorSelect.textContent = '';

		floors.forEach((floor) => {
			const option = document.createElement('option');
			option.value = String(floor.id || '');
			option.textContent = String(floor.name || '');
			floorSelect.appendChild(option);
		});

		if (floors.some((floor) => String(floor.id || '') === currentValue)) {
			floorSelect.value = currentValue;
		}
	};

	const resetFloorForm = () => {
		const form = getFloorForm();

		if (!form) {
			return;
		}

		form.reset();
		const floorId = form.querySelector('[name="floor_id"]');
		if (floorId) {
			floorId.value = '0';
		}

		setFloorPanelTitle('add');
		setFormSubmitMode(form, 'add');
	};

	const initFloorFormToggle = () => {
		const toggle = getFloorToggle();
		const panel = getFloorPanel();

		if (!panel) {
			return;
		}

		const cancel = panel.querySelector('[data-foodord-reservation-floor-cancel]');

		if (toggle) {
			toggle.addEventListener('click', () => {
				const isOpen = toggle.getAttribute('aria-expanded') === 'true';

				if (!isOpen) {
					resetFloorForm();
				}

				setFloorPanelOpen(!isOpen, true);
			});
		}

		if (cancel) {
			cancel.addEventListener('click', () => {
				resetFloorForm();
				setFloorPanelOpen(false, true);
			});
		}
	};

	const fillFloorForm = (row) => {
		const form = getFloorForm();

		if (!form || !row) {
			return;
		}

		resetFloorForm();

		const fields = {
			floor_id: row.dataset.floorId || '0',
			floor_name: row.dataset.floorName || ''
		};

		Object.keys(fields).forEach((name) => {
			const field = form.querySelector(`[name="${name}"]`);
			if (field) {
				field.value = fields[name];
			}
		});

		setFloorPanelTitle('edit');
		setFormSubmitMode(form, 'edit');
		setFloorPanelOpen(true, true);
		scrollToEditorPanel(getFloorPanel());
	};

	const fillTableForm = (row) => {
		const form = getTableForm();

		if (!form || !row) {
			return;
		}

		resetTableForm();

		const fields = {
			table_id: row.dataset.tableId || '0',
			floor_id: row.dataset.tableFloorId || '',
			table_name: row.dataset.tableName || '',
			table_capacity: row.dataset.tableCapacity || '2',
			reservation_duration_minutes: row.dataset.tableDuration || '90'
		};

		Object.keys(fields).forEach((name) => {
			const field = form.querySelector(`[name="${name}"]`);
			if (field) {
				field.value = fields[name];
			}
		});

		setTablePanelTitle('edit');
		setFormSubmitMode(form, 'edit');
		setTablePanelOpen(true, true);
		scrollToEditorPanel(getTablePanel());
	};

	const handleAjaxSave = (form, submitter, onSuccess) => {
		const button = getSubmitButton(form, submitter);

		setSubmitBusy(button, true);
		showAjaxNotice('', 'success');

		postForm(form)
			.then((result) => {
				if (!result || !result.success) {
					throw new Error(result && result.data && result.data.message ? result.data.message : i18n.saveError || '');
				}

				onSuccess(result.data || {});
				showAjaxNotice(result.data && result.data.message ? result.data.message : '', 'success');
			})
			.catch((error) => {
				showAjaxNotice(error.message || i18n.saveError || '', 'error');
			})
			.finally(() => {
				setSubmitBusy(button, false);
			});
	};

	const handleTableFilter = (form, submitter) => {
		const button = getSubmitButton(form, submitter);
		const list = document.querySelector('[data-foodord-reservation-tables-list]');

		setSubmitBusy(button, true);
		showAjaxNotice('', 'success');
		if (list) {
			list.setAttribute('aria-busy', 'true');
		}

		postTableFilters(form)
			.then((result) => {
				if (!result || !result.success) {
					throw new Error(result && result.data && result.data.message ? result.data.message : i18n.filterError || '');
				}

				replaceListHtml('[data-foodord-reservation-tables-list]', result.data ? result.data.tablesHtml : '');
				updateTableFilterUrl(form);
			})
			.catch((error) => {
				showAjaxNotice(error.message || i18n.filterError || '', 'error');
			})
			.finally(() => {
				setSubmitBusy(button, false);
				if (list) {
					list.removeAttribute('aria-busy');
				}
			});
	};

	const initAjaxEditors = () => {
		document.addEventListener('submit', (event) => {
			const form = event.target instanceof HTMLFormElement ? event.target : null;

			if (!form) {
				return;
			}

			if (form.matches('.foodord-reservations-filter--tables')) {
				event.preventDefault();
				handleTableFilter(form, event.submitter);
				return;
			}

			const action = form.querySelector('[name="reservation_action"]');
			const actionValue = action ? action.value : '';

			if (actionValue === 'edit_floor') {
				event.preventDefault();
				fillFloorForm(form.closest('[data-foodord-reservation-floor-row]'));
				return;
			}

			if (actionValue === 'edit_table') {
				event.preventDefault();
				fillTableForm(form.closest('[data-foodord-reservation-table-row]'));
				return;
			}

			if (form.matches('.foodord-reservations-form--floor')) {
				event.preventDefault();
					handleAjaxSave(form, event.submitter, (data) => {
						replaceListHtml('[data-foodord-reservation-floors-list]', data.floorsHtml);
						replaceListHtml('[data-foodord-reservation-tables-list]', data.tablesHtml);
						replaceListHtml('[data-foodord-reservation-table-filters]', data.tableFiltersHtml);
						updateFloorOptions(data.floors);
					refreshTableSelectionSettings(data.tableSelectionHtml);
					resetFloorForm();
					setFloorPanelOpen(false, false);
				});
				return;
			}

			if (form.id === 'foodord-reservation-table-form') {
				event.preventDefault();
				handleAjaxSave(form, event.submitter, (data) => {
					replaceListHtml('[data-foodord-reservation-floors-list]', data.floorsHtml);
					replaceListHtml('[data-foodord-reservation-tables-list]', data.tablesHtml);
					replaceListHtml('[data-foodord-reservation-table-filters]', data.tableFiltersHtml);
					refreshTableSelectionSettings(data.tableSelectionHtml);
					resetTableForm();
					setTablePanelOpen(false, false);
				});
			}
		});

	};

	const initTableFilterSearchReset = () => {
		document.addEventListener('search', (event) => {
			const input = event.target instanceof HTMLInputElement ? event.target : null;

			if (!input || !input.matches('[name="reservation_table_search"]') || input.value !== '') {
				return;
			}

			const form = input.closest('.foodord-reservations-filter--tables');
			if (form instanceof HTMLFormElement) {
				form.requestSubmit();
			}
		}, true);
	};

	const initReservationFilterReset = () => {
		document.addEventListener('click', (event) => {
			const target = event.target instanceof Element ? event.target : null;
			const button = target ? target.closest('[data-foodord-reservation-filter-reset]') : null;

			if (!(button instanceof HTMLButtonElement)) {
				return;
			}

			const form = button.closest('.foodord-reservations-filter:not(.foodord-reservations-filter--tables)');
			if (!(form instanceof HTMLFormElement)) {
				return;
			}

			['reservation_status', 'reservation_date', 'reservation_search'].forEach((fieldName) => {
				const field = form.elements.namedItem(fieldName);
				if (field instanceof HTMLInputElement || field instanceof HTMLSelectElement) {
					field.value = '';
				}
			});

			form.requestSubmit();
		});
	};

	const initManagementPagination = () => {
		document.addEventListener('click', (event) => {
			if (!(event instanceof MouseEvent) || event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
				return;
			}

			const target = event.target instanceof Element ? event.target : null;
			const link = target ? target.closest('.foodord-reservations-pagination a.page-numbers') : null;
			const list = link
				? link.closest('[data-foodord-reservation-floors-list], [data-foodord-reservation-tables-list]')
				: null;

			if (!(link instanceof HTMLAnchorElement) || !(list instanceof HTMLElement)) {
				return;
			}

			event.preventDefault();
			if (list.getAttribute('aria-busy') === 'true') {
				return;
			}

			const listType = list.hasAttribute('data-foodord-reservation-floors-list') ? 'floors' : 'tables';
			const url = new URL(link.href);
			list.setAttribute('aria-busy', 'true');
			showAjaxNotice('', 'success');

			postManagementPage(url, listType)
				.then((result) => {
					if (!result || !result.success) {
						throw new Error(result && result.data && result.data.message ? result.data.message : i18n.paginationError || '');
					}

					list.innerHTML = result.data ? result.data.html : '';
					managementPageKeys.forEach((key) => url.searchParams.delete(key));
					window.history.replaceState(window.history.state, '', url.toString());
				})
				.catch((error) => {
					showAjaxNotice(error.message || i18n.paginationError || '', 'error');
				})
				.finally(() => {
					list.removeAttribute('aria-busy');
				});
		}, true);
	};

	const initScheduleRoot = (root) => {
		if (!root || root.dataset.foodordReservationBookingReady === '1') {
			return;
		}
		root.dataset.foodordReservationBookingReady = '1';

		root.querySelectorAll('[data-foodord-reservation-schedule-day]').forEach((day) => {
			const rows = day.querySelector('[data-foodord-reservation-time-range-rows]');
			const template = day.querySelector('[data-foodord-reservation-time-range-template]');
			const addButton = day.querySelector('[data-foodord-reservation-time-range-add]');
			let nextIndex = rows ? rows.querySelectorAll('[data-foodord-reservation-time-range-row]').length : 0;

			if (!rows || !template || !addButton) {
				return;
			}

			const updateDaySummary = () => {
				const enabled = day.querySelector('[data-foodord-reservation-day-enabled]');
				const status = day.querySelector('[data-foodord-reservation-day-status]');
				const summary = day.querySelector('[data-foodord-reservation-day-summary]');
				const isOpen = enabled ? enabled.checked : false;
				const labels = {
					open: day.dataset.openLabel || 'Open',
					closed: day.dataset.closedLabel || 'Closed',
					empty: day.dataset.emptyLabel || ''
				};

				if (status) {
					status.textContent = isOpen ? labels.open : labels.closed;
					status.classList.toggle('is-open', isOpen);
					status.classList.toggle('is-closed', !isOpen);
				}

				if (!summary) {
					return;
				}

				if (!isOpen) {
					summary.textContent = labels.closed;
					return;
				}

				const ranges = Array.from(rows.querySelectorAll('[data-foodord-reservation-time-range-row]')).map((row) => {
					const from = row.querySelector('[name$="[from]"]');
					const to = row.querySelector('[name$="[to]"]');

					return from && to && from.value && to.value ? `${from.value}-${to.value}` : '';
				}).filter(Boolean);

				summary.textContent = ranges.length ? ranges.join(', ') : labels.empty;
			};

			addButton.addEventListener('click', () => {
				const wrapper = document.createElement('div');

				wrapper.innerHTML = template.innerHTML.replace(/__INDEX__/g, String(nextIndex));
				nextIndex += 1;

				const row = wrapper.querySelector('[data-foodord-reservation-time-range-row]');
				if (!row) {
					return;
				}

				rows.appendChild(row);
				const firstInput = row.querySelector('input, select');
				if (firstInput) {
					firstInput.focus({ preventScroll: true });
				}

				updateDaySummary();
			});

			day.addEventListener('change', updateDaySummary);
			day.addEventListener('input', updateDaySummary);
			updateDaySummary();
		});

		const holidays = root.querySelector('[data-foodord-reservation-holidays]');
		if (holidays) {
			const panel = holidays.querySelector('[data-foodord-reservation-holiday-panel]');
			const rows = holidays.querySelector('[data-foodord-reservation-holiday-rows]');
			const template = holidays.querySelector('[data-foodord-reservation-holiday-template]');
			const addButton = holidays.querySelector('[data-foodord-reservation-holiday-add]');
			let nextIndex = rows ? rows.querySelectorAll('[data-foodord-reservation-holiday-row]').length : 0;

			const openHolidayPanel = () => {
				if (addButton) {
					addButton.setAttribute('aria-expanded', 'true');
				}

				if (panel) {
					panel.hidden = false;
				}
			};

			if (rows && template && addButton) {
				addButton.addEventListener('click', () => {
					if (panel && panel.hidden && rows.querySelector('[data-foodord-reservation-holiday-row]')) {
						openHolidayPanel();
						const firstInput = rows.querySelector('input');
						if (firstInput) {
							firstInput.focus({ preventScroll: true });
						}
						return;
					}

					const wrapper = document.createElement('div');

					openHolidayPanel();
					wrapper.innerHTML = template.innerHTML.replace(/__INDEX__/g, String(nextIndex));
					nextIndex += 1;

					const row = wrapper.querySelector('[data-foodord-reservation-holiday-row]');
					if (!row) {
						return;
					}

					rows.appendChild(row);
					initDatePickers(row);
					const firstInput = row.querySelector('input');
					if (firstInput) {
						firstInput.focus({ preventScroll: true });
					}
				});
			}
		}

		root.addEventListener('click', (event) => {
			const target = event.target instanceof Element ? event.target : null;

			if (!target) {
				return;
			}

			const removeButton = target.closest('[data-foodord-reservation-time-range-remove], [data-foodord-reservation-holiday-remove]');
			if (!removeButton) {
				return;
			}

			const row = removeButton.closest('[data-foodord-reservation-time-range-row], [data-foodord-reservation-holiday-row]');
			if (row) {
				const holidayBlock = row.matches('[data-foodord-reservation-holiday-row]')
					? row.closest('[data-foodord-reservation-holidays]')
					: null;
				const holidayPanel = holidayBlock ? holidayBlock.querySelector('[data-foodord-reservation-holiday-panel]') : null;
				const holidayRows = holidayBlock ? holidayBlock.querySelector('[data-foodord-reservation-holiday-rows]') : null;
				const holidayAddButton = holidayBlock ? holidayBlock.querySelector('[data-foodord-reservation-holiday-add]') : null;

				row.remove();
				const day = removeButton.closest('[data-foodord-reservation-schedule-day]');
				if (day) {
					day.dispatchEvent(new Event('change', { bubbles: true }));
				}

				if (holidayRows && !holidayRows.querySelector('[data-foodord-reservation-holiday-row]')) {
					holidayRows.textContent = '';
					if (holidayPanel) {
						holidayPanel.hidden = true;
					}
					if (holidayAddButton) {
						holidayAddButton.setAttribute('aria-expanded', 'false');
					}
				}
			}
		});

		const closeOtherDayDetails = (activeToggle) => {
			root.querySelectorAll('[data-foodord-reservation-day-details-toggle][aria-expanded="true"]').forEach((openToggle) => {
				if (openToggle === activeToggle) {
					return;
				}

				const openDay = openToggle.closest('[data-foodord-reservation-schedule-day]');
				const openDetails = openDay ? openDay.querySelector('[data-foodord-reservation-day-details]') : null;

				openToggle.setAttribute('aria-expanded', 'false');
				if (openDetails) {
					openDetails.hidden = true;
				}
			});
		};

		root.addEventListener('click', (event) => {
			const target = event.target instanceof Element ? event.target : null;
			const toggle = target ? target.closest('[data-foodord-reservation-day-details-toggle]') : null;

			if (!toggle) {
				return;
			}

			const day = toggle.closest('[data-foodord-reservation-schedule-day]');
			const details = day ? day.querySelector('[data-foodord-reservation-day-details]') : null;
			if (!details) {
				return;
			}

			const isOpen = toggle.getAttribute('aria-expanded') === 'true';

			if (!isOpen) {
				closeOtherDayDetails(toggle);
			}

			toggle.setAttribute('aria-expanded', String(!isOpen));
			details.hidden = isOpen;
		});
	};

	const initBookingSettings = () => {
		document
			.querySelectorAll('[data-foodord-reservation-booking-settings], [data-foodord-reservation-schedule-settings]')
			.forEach((root) => {
				initScheduleRoot(root);
			});
	};

	const initReservationDashboardBilling = () => {
		document.querySelectorAll('[data-foodord-reservation-dashboard]').forEach((dashboard) => {
			const cycleButtons = Array.from(
				dashboard.querySelectorAll('[data-foodord-reservation-billing-cycle]')
			);
			const prices = Array.from(
				dashboard.querySelectorAll('[data-foodord-reservation-billing-price]')
			);
			const pricingButton = dashboard.querySelector('[data-foodord-reservation-pricing-url]');

			if (pricingButton) {
				pricingButton.addEventListener('click', () => {
					const pricingUrl = pricingButton.dataset.foodordReservationPricingUrl;

					if (pricingUrl) {
						window.open(pricingUrl, '_blank', 'noopener,noreferrer');
					}
				});
			}

			if (!cycleButtons.length || !prices.length) {
				return;
			}

			const setBillingCycle = (cycle) => {
				cycleButtons.forEach((button) => {
					const isActive = button.dataset.foodordReservationBillingCycle === cycle;

					button.classList.toggle('is-active', isActive);
					button.setAttribute('aria-pressed', String(isActive));
				});

				prices.forEach((price) => {
					price.hidden = price.dataset.foodordReservationBillingPrice !== cycle;
				});
			};

			cycleButtons.forEach((button) => {
				button.addEventListener('click', () => {
					setBillingCycle(button.dataset.foodordReservationBillingCycle || 'monthly');
				});
			});

			setBillingCycle('monthly');
		});
	};

	const initReservationsAdmin = () => {
		initReservationDashboardBilling();
		initDatePickers(document);
		initFloorFormToggle();
		initTableFormToggle();
		initTableDeleteConfirm();
		initReservationBulkActions();
		initCancellationReasonFields();
		initManualReservationModal();
		initBannerPicker();
		initEmailContentSettings();
		initPrivacySettings();
		initDepositSettings();
		initPreorderSettings();
		initCapacityLimitSettings();
		initTableSelectionSettings();
		initAjaxEditors();
		initReservationFilterReset();
		initTableFilterSearchReset();
		initManagementPagination();
		initBookingSettings();
	};

	if (document.readyState === 'loading') {
		document.addEventListener('DOMContentLoaded', initReservationsAdmin);
		return;
	}

	initReservationsAdmin();
}());
