/**
 * Table Reservation frontend form.
 */
(function () {
    'use strict';

    function setCaptchaToken(form, token) {
        form.querySelectorAll('.maca-booking-captcha-token').forEach(function (el) {
            el.value = token || '';
        });
    }

    function initBooking(root) {
        if (!root || root.dataset.macaBookingInit) {
            return;
        }

        var form = root.querySelector('.maca-table-booking-form');
        if (!form) {
            return;
        }

        root.dataset.macaBookingInit = '1';

        var config = window.macaMenulistTableBooking || {};
        var strings = config.strings || {};
        var captcha = config.captcha || {};
        var bestFitMode = config.assignmentMode === 'best_fit';
        var waitlistEnabled = !!config.waitlistEnabled;
        var trigger = root.querySelector('.maca-table-booking-trigger');
        var modal = root.querySelector('.maca-table-booking-modal');
        var backdrop = root.querySelector('.maca-table-booking-backdrop');
        var closeBtn = root.querySelector('.maca-table-booking-close');
        var dateInput = form.querySelector('[name="booking_date"]');
        var partyInput = form.querySelector('[name="party_size"]');
        var timeSelect = form.querySelector('[name="booking_time"]');
        var timesWrap = root.querySelector('.maca-booking-times-wrap');
        var tablesWrap = root.querySelector('.maca-booking-tables-wrap');
        var tablesContainer = root.querySelector('.maca-booking-tables');
        var submitBtn = root.querySelector('.maca-table-booking-submit');
        var waitlistWrap = root.querySelector('.maca-booking-waitlist-wrap');
        var waitlistBtn = root.querySelector('.maca-table-booking-waitlist-submit');
        var messageEl = root.querySelector('.maca-booking-message');
        var selectedTableId = 0;
        var waitlistOnlyDay = false;
        var slotHasTable = true;
        var recaptchaWidgetId = null;
        var turnstileWidgetId = null;

        if (!dateInput || !partyInput || !timeSelect || !submitBtn) {
            return;
        }

        function waitForRecaptcha(callback) {
            if (window.macaMenulistRecaptchaLoaded && typeof grecaptcha !== 'undefined') {
                callback();
                return;
            }

            var done = false;
            var timer = window.setTimeout(function () {
                if (!done) {
                    done = true;
                    callback();
                }
            }, 5000);

            document.addEventListener('macaMenulistRecaptchaReady', function onReady() {
                if (done) {
                    return;
                }
                done = true;
                window.clearTimeout(timer);
                callback();
            }, { once: true });
        }

        function waitForTurnstile(callback) {
            var attempts = 0;

            function check() {
                if (typeof turnstile !== 'undefined' && typeof turnstile.render === 'function') {
                    callback();
                    return;
                }

                attempts += 1;
                if (attempts < 50) {
                    window.setTimeout(check, 100);
                }
            }

            check();
        }

        function initCaptcha() {
            if (!captcha.enabled) {
                return;
            }

            if (captcha.provider === 'recaptcha_v2') {
                var recaptchaContainer = form.querySelector('.maca-recaptcha-v2-widget');
                if (!recaptchaContainer || recaptchaContainer.dataset.macaCaptchaReady === '1') {
                    return;
                }

                waitForRecaptcha(function () {
                    if (!recaptchaContainer || typeof grecaptcha === 'undefined' || typeof grecaptcha.render !== 'function') {
                        return;
                    }

                    if (recaptchaWidgetId !== null) {
                        try {
                            grecaptcha.reset(recaptchaWidgetId);
                        } catch (e) {
                            /* ignore */
                        }
                        recaptchaContainer.dataset.macaCaptchaReady = '1';
                        return;
                    }

                    recaptchaWidgetId = grecaptcha.render(recaptchaContainer, {
                        sitekey: captcha.siteKey
                    });
                    recaptchaContainer.dataset.macaCaptchaReady = '1';
                });
                return;
            }

            if (captcha.provider === 'turnstile') {
                var turnstileContainer = form.querySelector('.maca-turnstile-widget');
                if (!turnstileContainer || turnstileContainer.dataset.macaCaptchaReady === '1') {
                    return;
                }

                waitForTurnstile(function () {
                    if (!turnstileContainer || typeof turnstile === 'undefined' || typeof turnstile.render !== 'function') {
                        return;
                    }

                    turnstileWidgetId = turnstile.render(turnstileContainer, {
                        sitekey: captcha.siteKey,
                        callback: function (token) {
                            setCaptchaToken(form, token);
                        },
                        'expired-callback': function () {
                            setCaptchaToken(form, '');
                        },
                        'error-callback': function () {
                            setCaptchaToken(form, '');
                        }
                    });
                    turnstileContainer.dataset.macaCaptchaReady = '1';
                });
            }
        }

        function openModal() {
            if (modal) {
                modal.hidden = false;
            }
            document.body.classList.add('maca-booking-modal-open');
            window.requestAnimationFrame(function () {
                initCaptcha();
            });
        }

        function closeModal() {
            if (modal) {
                modal.hidden = true;
            }
            document.body.classList.remove('maca-booking-modal-open');
        }

        function showMessage(text, isError) {
            if (!messageEl) {
                return;
            }
            messageEl.textContent = text;
            messageEl.hidden = !text;
            messageEl.className = 'maca-booking-message' + (isError ? ' maca-booking-error' : ' maca-booking-success');
        }

        function isGuestFieldsComplete() {
            return Boolean(
                dateInput.value
                && partyInput.value
                && timeSelect.value
                && form.guest_name.value.trim()
                && form.guest_email.value.trim()
                && form.guest_phone.value.trim()
            );
        }

        function isFormComplete() {
            var hasTable = bestFitMode || selectedTableId > 0;

            return isGuestFieldsComplete() && hasTable;
        }

        function isWaitlistFormComplete() {
            return isGuestFieldsComplete();
        }

        function updateWaitlistUi() {
            if (!waitlistWrap || !waitlistEnabled) {
                return;
            }

            var show = isWaitlistFormComplete() && (waitlistOnlyDay || !slotHasTable);
            waitlistWrap.hidden = !show;
            if (waitlistBtn) {
                waitlistBtn.disabled = !isWaitlistFormComplete();
            }
        }

        function setSubmitEnabled() {
            submitBtn.disabled = !isFormComplete();
            updateWaitlistUi();
        }

        function selectTable(radio) {
            selectedTableId = parseInt(radio.value, 10);
            radio.checked = true;
            setSubmitEnabled();
        }

        function resetTables() {
            selectedTableId = 0;
            if (tablesWrap) {
                tablesWrap.hidden = true;
            }
            if (tablesContainer) {
                tablesContainer.innerHTML = '';
            }
        }

        function postAction(action, data) {
            var body = new FormData();
            body.append('action', action);
            body.append('nonce', config.nonce || '');
            Object.keys(data).forEach(function (key) {
                body.append(key, data[key]);
            });

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

        function getCaptchaToken() {
            return new Promise(function (resolve, reject) {
                if (!captcha.enabled) {
                    resolve('');
                    return;
                }

                if (captcha.provider === 'recaptcha_v2') {
                    if (typeof grecaptcha === 'undefined' || recaptchaWidgetId === null) {
                        reject(new Error('recaptcha'));
                        return;
                    }

                    grecaptcha.ready(function () {
                        var token = grecaptcha.getResponse(recaptchaWidgetId);
                        resolve(token || '');
                    });
                    return;
                }

                if (captcha.provider === 'recaptcha_v3') {
                    if (typeof grecaptcha === 'undefined' || !captcha.siteKey) {
                        reject(new Error('recaptcha'));
                        return;
                    }
                    grecaptcha.ready(function () {
                        grecaptcha.execute(captcha.siteKey, { action: 'table_booking' }).then(resolve).catch(reject);
                    });
                    return;
                }

                if (captcha.provider === 'turnstile') {
                    var tokenField = form.querySelector('.maca-booking-captcha-token');
                    resolve(tokenField && tokenField.value ? tokenField.value : '');
                    return;
                }

                resolve('');
            });
        }

        function resetCaptcha() {
            if (captcha.provider === 'recaptcha_v2' && typeof grecaptcha !== 'undefined' && recaptchaWidgetId !== null) {
                try {
                    grecaptcha.reset(recaptchaWidgetId);
                } catch (e) {
                    /* ignore */
                }
            }

            if (captcha.provider === 'turnstile' && typeof turnstile !== 'undefined' && turnstileWidgetId !== null) {
                try {
                    turnstile.reset(turnstileWidgetId);
                } catch (e) {
                    /* ignore */
                }
            }

            setCaptchaToken(form, '');
        }

        function loadTimeSlots() {
            var date = dateInput.value;
            var partySize = partyInput.value || 2;

            resetTables();
            waitlistOnlyDay = false;
            slotHasTable = true;
            timeSelect.innerHTML = '<option value="">' + (strings.loading || 'Loading…') + '</option>';
            timeSelect.disabled = true;
            setSubmitEnabled();

            if (!date) {
                if (timesWrap) {
                    timesWrap.hidden = true;
                }
                return;
            }

            postAction('maca_get_booking_slots', {
                booking_date: date,
                party_size: partySize
            }).then(function (result) {
                timeSelect.innerHTML = '';

                if (!result.success) {
                    timeSelect.innerHTML = '<option value="">' + (result.data && result.data.message ? result.data.message : strings.closed) + '</option>';
                    if (timesWrap) {
                        timesWrap.hidden = false;
                    }
                    return;
                }

                var slots = result.data.slots || [];

                waitlistOnlyDay = !!(result.data && result.data.waitlist_only);

                if (!slots.length) {
                    timeSelect.innerHTML = '<option value="">' + (result.data.message || strings.noSlots) + '</option>';
                    if (timesWrap) {
                        timesWrap.hidden = false;
                    }
                    updateWaitlistUi();
                    return;
                }

                timeSelect.appendChild(new Option(strings.selectTime, ''));
                slots.forEach(function (slot) {
                    timeSelect.appendChild(new Option(slot, slot));
                });

                timeSelect.disabled = false;
                if (timesWrap) {
                    timesWrap.hidden = false;
                }
            }).catch(function () {
                timeSelect.innerHTML = '<option value="">' + strings.error + '</option>';
            }).finally(function () {
                setSubmitEnabled();
            });
        }

        function checkSlotAvailability() {
            if (!bestFitMode || !waitlistEnabled) {
                return Promise.resolve();
            }

            var date = dateInput.value;
            var time = timeSelect.value;
            var partySize = partyInput.value || 2;

            if (!date || !time) {
                slotHasTable = true;
                setSubmitEnabled();
                return Promise.resolve();
            }

            return postAction('maca_get_booking_tables', {
                booking_date: date,
                booking_time: time,
                party_size: partySize
            }).then(function (result) {
                slotHasTable = !!(result.success && result.data.tables && result.data.tables.length);
                setSubmitEnabled();
            }).catch(function () {
                slotHasTable = true;
                setSubmitEnabled();
            });
        }

        function loadTables() {
            var date = dateInput.value;
            var time = timeSelect.value;
            var partySize = partyInput.value || 2;

            if (bestFitMode) {
                checkSlotAvailability();
                return;
            }

            selectedTableId = 0;
            if (tablesContainer) {
                tablesContainer.innerHTML = '';
            }
            setSubmitEnabled();

            if (!date || !time) {
                if (tablesWrap) {
                    tablesWrap.hidden = true;
                }
                slotHasTable = true;
                return;
            }

            if (tablesContainer) {
                tablesContainer.textContent = strings.loading || 'Loading…';
            }
            if (tablesWrap) {
                tablesWrap.hidden = false;
            }

            postAction('maca_get_booking_tables', {
                booking_date: date,
                booking_time: time,
                party_size: partySize
            }).then(function (result) {
                if (!tablesContainer) {
                    return;
                }

                tablesContainer.innerHTML = '';

                if (!result.success || !result.data.tables || !result.data.tables.length) {
                    slotHasTable = false;
                    tablesContainer.textContent = result.data && result.data.message ? result.data.message : strings.noTables;
                    setSubmitEnabled();
                    return;
                }

                slotHasTable = true;

                result.data.tables.forEach(function (table, index) {
                    var label = document.createElement('label');
                    label.className = 'maca-booking-table-option';

                    var radio = document.createElement('input');
                    radio.type = 'radio';
                    radio.name = 'table_id';
                    radio.value = String(table.id);
                    radio.addEventListener('change', function () {
                        selectTable(radio);
                    });

                    var text = document.createElement('span');
                    text.textContent = (strings.table || 'Table') + ' ' + table.table_number + ' (' + table.seats + ' ' + (strings.seats || 'seats') + ')';

                    label.appendChild(radio);
                    label.appendChild(text);
                    tablesContainer.appendChild(label);

                    if (index === 0) {
                        selectTable(radio);
                    }
                });
            }).catch(function () {
                if (tablesContainer) {
                    tablesContainer.textContent = strings.error;
                }
            }).finally(function () {
                setSubmitEnabled();
            });
        }

        setSubmitEnabled();

        if (trigger) {
            trigger.addEventListener('click', openModal);
        }
        if (backdrop) {
            backdrop.addEventListener('click', closeModal);
        }
        if (closeBtn) {
            closeBtn.addEventListener('click', closeModal);
        }

        dateInput.addEventListener('change', loadTimeSlots);
        partyInput.addEventListener('change', loadTimeSlots);
        timeSelect.addEventListener('change', loadTables);

        form.addEventListener('input', setSubmitEnabled);
        form.addEventListener('change', setSubmitEnabled);

        function submitWaitlist() {
            showMessage('', false);

            if (!isWaitlistFormComplete()) {
                showMessage(strings.requiredFields || strings.error, true);
                return;
            }

            if (waitlistBtn) {
                waitlistBtn.disabled = true;
            }
            submitBtn.disabled = true;

            if (captcha.enabled && (captcha.provider === 'recaptcha_v2' || captcha.provider === 'turnstile')) {
                initCaptcha();
            }

            getCaptchaToken().then(function (captchaToken) {
                if (captcha.enabled && !captchaToken) {
                    showMessage(strings.captchaRequired || strings.error, true);
                    setSubmitEnabled();
                    return;
                }

                var payload = {
                    booking_date: dateInput.value,
                    booking_time: timeSelect.value,
                    party_size: partyInput.value,
                    guest_name: form.guest_name.value,
                    guest_email: form.guest_email.value,
                    guest_phone: form.guest_phone.value,
                    guest_note: form.guest_note.value
                };

                if (captchaToken) {
                    payload.captcha_token = captchaToken;
                }

                return postAction('maca_submit_table_booking_waitlist', payload).then(function (result) {
                    if (result.success) {
                        showMessage(strings.waitlistSuccess || strings.success, false);
                        form.reset();
                        resetTables();
                        resetCaptcha();
                        waitlistOnlyDay = false;
                        slotHasTable = true;
                        if (timesWrap) {
                            timesWrap.hidden = true;
                        }
                        if (waitlistWrap) {
                            waitlistWrap.hidden = true;
                        }
                    } else {
                        showMessage(result.data && result.data.message ? result.data.message : strings.error, true);
                        resetCaptcha();
                        setSubmitEnabled();
                    }
                });
            }).catch(function () {
                showMessage(strings.captchaRequired || strings.error, true);
                resetCaptcha();
                setSubmitEnabled();
            });
        }

        form.addEventListener('submit', function (event) {
            event.preventDefault();
            showMessage('', false);

            if (!isFormComplete()) {
                showMessage(strings.requiredFields || strings.error, true);
                return;
            }

            submitBtn.disabled = true;

            if (captcha.enabled && (captcha.provider === 'recaptcha_v2' || captcha.provider === 'turnstile')) {
                initCaptcha();
            }

            getCaptchaToken().then(function (captchaToken) {
                if (captcha.enabled && !captchaToken) {
                    showMessage(strings.captchaRequired || strings.error, true);
                    setSubmitEnabled();
                    return;
                }

                var payload = {
                    booking_date: dateInput.value,
                    booking_time: timeSelect.value,
                    party_size: partyInput.value,
                    guest_name: form.guest_name.value,
                    guest_email: form.guest_email.value,
                    guest_phone: form.guest_phone.value,
                    guest_note: form.guest_note.value
                };

                if (!bestFitMode) {
                    payload.table_id = selectedTableId;
                }

                if (captchaToken) {
                    payload.captcha_token = captchaToken;
                }

                return postAction('maca_submit_table_booking', payload).then(function (result) {
                    if (result.success) {
                        showMessage(strings.success, false);
                        form.reset();
                        resetTables();
                        resetCaptcha();
                        if (timesWrap) {
                            timesWrap.hidden = true;
                        }
                    } else {
                        showMessage(result.data && result.data.message ? result.data.message : strings.error, true);
                        resetCaptcha();
                        setSubmitEnabled();
                    }
                });
            }).catch(function () {
                showMessage(strings.captchaRequired || strings.error, true);
                resetCaptcha();
                setSubmitEnabled();
            });
        });

        if (waitlistBtn) {
            waitlistBtn.addEventListener('click', submitWaitlist);
        }
    }

    document.addEventListener('DOMContentLoaded', function () {
        document.querySelectorAll('[data-maca-booking]').forEach(initBooking);
        tryAutoOpenFromUrl();
    });

    function tryAutoOpenFromUrl() {
        var shouldOpen = false;

        try {
            var params = new URLSearchParams(window.location.search);
            shouldOpen = params.get('maca_booking') === '1' || window.location.hash === '#maca-booking';
        } catch (error) {
            shouldOpen = window.location.hash === '#maca-booking';
        }

        if (!shouldOpen) {
            return;
        }

        var root = document.querySelector('[data-maca-booking]');

        if (!root) {
            return;
        }

        var trigger = root.querySelector('.maca-table-booking-trigger');

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

    window.macaMenulistInitTableBooking = function (root) {
        initBooking(root);
    };
})();
