/**
 * Dish menu filters and image lightbox for maca Restu Pro.
 */
(function () {
    'use strict';

    function trackDishView(dishId, eventType) {
        if (!window.macaMenulistDish || !window.macaMenulistDish.trackingEnabled) {
            return;
        }

        dishId = parseInt(dishId, 10);
        if (!dishId) {
            return;
        }

        var formData = new FormData();
        formData.append('action', 'maca_track_dish_view');
        formData.append('nonce', window.macaMenulistDish.trackNonce);
        formData.append('dish_id', String(dishId));
        formData.append('event_type', eventType || 'click_card');

        if (navigator.sendBeacon && window.Blob) {
            try {
                navigator.sendBeacon(window.macaMenulistDish.ajaxUrl, formData);
                return;
            } catch (e) {
                // Fall through to fetch.
            }
        }

        fetch(window.macaMenulistDish.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: formData,
            keepalive: true,
        }).catch(function () {
            // Non-blocking analytics.
        });
    }

    function getStickyScrollOffset(stickyElement) {
        var offset = stickyElement ? stickyElement.offsetHeight : 0;
        var stickyTop = stickyElement
            ? parseFloat(window.getComputedStyle(stickyElement).top) || 0
            : 0;

        return stickyTop + offset + 8;
    }

    function measureStickyTopOffset() {
        var top = 0;
        var adminBar = document.getElementById('wpadminbar');

        if (adminBar) {
            top += adminBar.offsetHeight;
        }

        document.querySelectorAll('header, #masthead, .site-header, .elementor-location-header').forEach(function (header) {
            var style = window.getComputedStyle(header);

            if (style.position !== 'fixed' && style.position !== 'sticky') {
                return;
            }

            if (style.display === 'none' || style.visibility === 'hidden') {
                return;
            }

            var rect = header.getBoundingClientRect();

            if (rect.height <= 0) {
                return;
            }

            if (rect.top <= 1 && rect.bottom > 0) {
                top = Math.max(top, rect.bottom);
            }
        });

        return top;
    }

    function applyStickyTopOffset(filters) {
        var top = measureStickyTopOffset();
        var menu = filters.closest('.maca-dish-menu');

        filters.style.setProperty('--maca-dm-sticky-offset', top + 'px');

        if (menu) {
            menu.style.setProperty('--maca-dm-sticky-offset', top + 'px');
        }
    }

    function scrollToWithStickyOffset(element, stickyElement) {
        if (!element) {
            return;
        }

        var top = element.getBoundingClientRect().top + window.pageYOffset - getStickyScrollOffset(stickyElement);

        window.scrollTo({
            top: Math.max(0, top),
            behavior: 'smooth',
        });
    }

    function getFirstVisibleCategorySection(menu) {
        var sections = menu.querySelectorAll('.maca-dish-category');
        var index;

        for (index = 0; index < sections.length; index += 1) {
            if (sections[index].style.display !== 'none') {
                return sections[index];
            }
        }

        return null;
    }

    function initDishFilterNavigation(filters) {
        if (filters.dataset.macaNavBound === '1') {
            return;
        }

        filters.dataset.macaNavBound = '1';

        applyStickyTopOffset(filters);

        var sentinel = document.createElement('div');
        sentinel.className = 'maca-dish-filters-sticky-sentinel';
        sentinel.setAttribute('aria-hidden', 'true');
        filters.parentNode.insertBefore(sentinel, filters);

        var stuckObserver = null;

        function bindStuckObserver() {
            if (!('IntersectionObserver' in window)) {
                return;
            }

            if (stuckObserver) {
                stuckObserver.disconnect();
            }

            stuckObserver = new IntersectionObserver(function (entries) {
                filters.classList.toggle('is-stuck', !entries[0].isIntersecting);
            }, {
                threshold: 0,
                rootMargin: '-' + measureStickyTopOffset() + 'px 0px 0px 0px',
            });
            stuckObserver.observe(sentinel);
        }

        bindStuckObserver();

        var resizeTimer;
        window.addEventListener('resize', function () {
            window.clearTimeout(resizeTimer);
            resizeTimer = window.setTimeout(function () {
                applyStickyTopOffset(filters);
                bindStuckObserver();
            }, 120);
        });

        window.addEventListener('scroll', function () {
            applyStickyTopOffset(filters);
        }, { passive: true });
    }

    function applyDishCategoryFilter(menu, filters, categoryId, campaignId) {
        menu.querySelectorAll('.maca-dish-category').forEach(function (section) {
            if (categoryId === 'all' && !campaignId) {
                section.style.display = '';
                return;
            }

            if (campaignId) {
                section.style.display = section.getAttribute('data-dish-campaign-id') === campaignId ? '' : 'none';
                return;
            }

            section.style.display = section.getAttribute('data-dish-category-id') === categoryId ? '' : 'none';
        });

        if (categoryId !== 'all' || campaignId) {
            window.requestAnimationFrame(function () {
                scrollToWithStickyOffset(getFirstVisibleCategorySection(menu), filters);
            });
        }
    }

    function parseDishCategorySelectValue(value) {
        if (!value || value === 'all') {
            return { categoryId: 'all', campaignId: '' };
        }

        if (value.indexOf('campaign:') === 0) {
            return { categoryId: '', campaignId: value.slice('campaign:'.length) };
        }

        if (value.indexOf('category:') === 0) {
            return { categoryId: value.slice('category:'.length), campaignId: '' };
        }

        return { categoryId: 'all', campaignId: '' };
    }

    function initDishFilters(root) {
        var scope = root || document;

        scope.querySelectorAll('.maca-dish-menu').forEach(function (menu) {
            var filters = menu.querySelector('.maca-dish-filters');
            if (!filters || filters.dataset.macaBound === '1') {
                return;
            }

            filters.dataset.macaBound = '1';
            initDishFilterNavigation(filters);

            var select = filters.querySelector('.maca-dish-category-select');
            if (select) {
                select.addEventListener('change', function () {
                    var parsed = parseDishCategorySelectValue(select.value);
                    applyDishCategoryFilter(menu, filters, parsed.categoryId, parsed.campaignId);
                });
                return;
            }

            filters.addEventListener('click', function (event) {
                var button = event.target.closest('.maca-dish-filter');
                if (!button || !filters.contains(button)) {
                    return;
                }

                var categoryId = button.getAttribute('data-category-id');
                var campaignId = button.getAttribute('data-campaign-id');

                filters.querySelectorAll('.maca-dish-filter').forEach(function (filterButton) {
                    var isActive = filterButton === button;
                    filterButton.classList.toggle('active', isActive);
                    filterButton.setAttribute('aria-selected', isActive ? 'true' : 'false');
                });

                applyDishCategoryFilter(menu, filters, categoryId, campaignId);
            });
        });
    }

    function getLightbox() {
        return document.getElementById('maca-dish-lightbox');
    }

    function closeLightbox() {
        var lightbox = getLightbox();
        if (!lightbox) {
            return;
        }

        lightbox.hidden = true;
        lightbox.setAttribute('aria-hidden', 'true');
        document.body.classList.remove('maca-dish-lightbox-open');

        var image = lightbox.querySelector('.maca-dish-lightbox-image');
        if (image) {
            image.src = '';
            image.alt = '';
        }
    }

    function openLightbox(imageUrl, imageAlt) {
        var lightbox = getLightbox();
        if (!lightbox || !imageUrl) {
            return;
        }

        var image = lightbox.querySelector('.maca-dish-lightbox-image');
        if (!image) {
            return;
        }

        image.src = imageUrl;
        image.alt = imageAlt || '';
        lightbox.hidden = false;
        lightbox.setAttribute('aria-hidden', 'false');
        document.body.classList.add('maca-dish-lightbox-open');

        var closeButton = lightbox.querySelector('.maca-dish-lightbox-close');
        if (closeButton) {
            closeButton.focus();
        }
    }

    function initDishImageLightbox(root) {
        var scope = root || document;

        if (scope.documentElement && scope !== document) {
            scope = document;
        }

        if (document.body.dataset.macaDishLightboxBound === '1') {
            return;
        }

        document.body.dataset.macaDishLightboxBound = '1';

        document.addEventListener('click', function (event) {
            var trigger = event.target.closest('.maca-dish-image-button');
            if (trigger) {
                event.preventDefault();
                var image = trigger.querySelector('img');
                trackDishView(
                    trigger.getAttribute('data-dish-id'),
                    'click_image'
                );
                openLightbox(
                    trigger.getAttribute('data-full-image-url'),
                    image ? image.getAttribute('alt') : ''
                );
                return;
            }

            var dishItem = event.target.closest('.maca-dish-item');
            if (
                dishItem
                && !event.target.closest('.maca-dish-rating, .maca-dish-add-to-order, .maca-dish-order-actions, .maca-dish-image-button, button, a, input, select, textarea')
            ) {
                trackDishView(dishItem.getAttribute('data-dish-id'), 'click_card');
            }

            if (event.target.closest('[data-maca-lightbox-close="1"]')) {
                closeLightbox();
            }
        });

        document.addEventListener('keydown', function (event) {
            if (event.key === 'Escape') {
                closeLightbox();
            }
        });
    }

    function initDishRatings(root) {
        if (!window.macaMenulistDish || !window.macaMenulistDish.ratingsEnabled) {
            return;
        }

        var scope = root || document;

        scope.querySelectorAll('.maca-dish-rating').forEach(function (container) {
            if (container.dataset.macaRatingBound === '1') {
                return;
            }

            container.dataset.macaRatingBound = '1';

            var stars = container.querySelector('.maca-dish-rating-stars');
            if (!stars) {
                return;
            }

            function updateRatingMeta(average, count) {
                var meta = container.querySelector('.maca-dish-rating-meta');
                if (!meta) {
                    return;
                }

                var averageEl = meta.querySelector('.maca-dish-rating-average');
                var countEl = meta.querySelector('.maca-dish-rating-count');

                if (count <= 0) {
                    meta.classList.add('maca-dish-rating-meta--empty');
                    if (averageEl) {
                        averageEl.textContent = '';
                    }
                    if (countEl) {
                        countEl.textContent = '';
                    }
                    return;
                }

                meta.classList.remove('maca-dish-rating-meta--empty');
                if (averageEl) {
                    averageEl.textContent = Number(average).toFixed(1).replace('.', ',');
                }
                if (countEl) {
                    var i18n = window.macaMenulistDish.i18n || {};
                    var countLabel = count === 1
                        ? (i18n.ratingCountSingular || '(%d rating)')
                        : (i18n.ratingCountPlural || '(%d ratings)');
                    countEl.textContent = countLabel.replace('%d', String(count));
                }
            }

            function setStarState(userRating) {
                container.setAttribute('data-user-rating', String(userRating));
                stars.querySelectorAll('.maca-dish-rating-star').forEach(function (star) {
                    var value = parseInt(star.getAttribute('data-value'), 10);
                    var isActive = value <= userRating;
                    star.classList.toggle('is-active', isActive);
                    star.setAttribute('aria-pressed', isActive ? 'true' : 'false');
                });
            }

            stars.addEventListener('click', function (event) {
                var button = event.target.closest('.maca-dish-rating-star');
                if (!button || !stars.contains(button)) {
                    return;
                }

                var dishId = container.getAttribute('data-dish-id');
                var rating = parseInt(button.getAttribute('data-value'), 10);

                if (!dishId || rating < 1 || rating > 5 || container.classList.contains('is-saving')) {
                    return;
                }

                container.classList.add('is-saving');

                var formData = new FormData();
                formData.append('action', 'maca_rate_dish');
                formData.append('nonce', window.macaMenulistDish.nonce);
                formData.append('dish_id', dishId);
                formData.append('rating', String(rating));

                fetch(window.macaMenulistDish.ajaxUrl, {
                    method: 'POST',
                    credentials: 'same-origin',
                    body: formData,
                })
                    .then(function (response) {
                        return response.json();
                    })
                    .then(function (payload) {
                        if (!payload || !payload.success || !payload.data) {
                            throw new Error('rating failed');
                        }

                        setStarState(payload.data.user_rating);
                        updateRatingMeta(payload.data.average, payload.data.count);
                        container.classList.add('is-rated');
                    })
                    .catch(function () {
                        window.alert(window.macaMenulistDish.i18n.ratingError);
                    })
                    .finally(function () {
                        container.classList.remove('is-saving');
                    });
            });

            stars.querySelectorAll('.maca-dish-rating-star').forEach(function (star) {
                star.addEventListener('mouseenter', function () {
                    var hoverValue = parseInt(star.getAttribute('data-value'), 10);
                    stars.querySelectorAll('.maca-dish-rating-star').forEach(function (item) {
                        var value = parseInt(item.getAttribute('data-value'), 10);
                        item.classList.toggle('is-hover', value <= hoverValue);
                    });
                });

                star.addEventListener('mouseleave', function () {
                    stars.querySelectorAll('.maca-dish-rating-star').forEach(function (item) {
                        item.classList.remove('is-hover');
                    });
                });
            });
        });
    }

    function init(scope) {
        initDishFilters(scope);
        initDishImageLightbox(scope);
        initDishRatings(scope);
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', function () {
            init();
        });
    } else {
        init();
    }

    window.MacaMenulistDishMenu = {
        init: init,
        trackDishView: trackDishView,
    };
})();
