(function ($) {
    'use strict';

    window.App = {
        /**
         * Initialise the object
         */
        init: function () {
            this.html = $('html');
            this.body = $('body');
            this.window = $(window);
            this.wp = window.wp;
            this.build();
            this.notify();
            this.handleACFTabbedErrors();
        },

        /**
         * Build or update the page
         */
        build: function () {
            this.example();
        },

        /**
         * Notify about Vite
         */
        notify: function () {
            if (this.wp.data && import.meta.env.DEV && import.meta.env.MODE === 'development') {
                this.wp.data.dispatch('core/notices').createNotice('error', "Vite is running in dev mode. This can cause problems in the block editor. Consider using 'make watch' instead.");
            }
        },

        /**
         * Example function
         */
        example: function () {
            // Example function
        },

        /**
         * ACF in the admin doesn't handle tabbed errors correctly.
         * This makes sure you can see the errors even if they are on another tab.
         * Works in both classic admin and Gutenberg editor.
         */
        handleACFTabbedErrors: function () {
            if (typeof acf === 'undefined') return;
            const self = this;

            function updateTabErrorIndicators() {
                // Remove all existing error indicators
                document.querySelectorAll('.acf-tab-button .acf-error-indicator').forEach((indicator) => indicator.remove());

                // For each ACF block/fields group
                document.querySelectorAll('.acf-block-fields, .acf-fields').forEach((fieldsContainer) => {
                    // Find the tab group (if any)
                    const tabGroup = fieldsContainer.querySelector('.acf-tab-group');
                    if (!tabGroup) return;
                    // Map of tabKey => hasError
                    const tabErrors = {};
                    // Walk children in order, grouping by tab
                    let currentTabKey = null;
                    const children = Array.from(fieldsContainer.children);
                    children.forEach((child) => {
                        if (child.classList && child.classList.contains('acf-field-tab') && child.hasAttribute('data-key')) {
                            currentTabKey = child.getAttribute('data-key');
                            if (!(currentTabKey in tabErrors)) tabErrors[currentTabKey] = false;
                        } else if (currentTabKey) {
                            // Check if this field or any descendant has an error
                            if (
                                (child.classList && (child.classList.contains('-error') || child.classList.contains('acf-error'))) ||
                                (child.querySelector && child.querySelector('.acf-error-message, .acf-notice.-error, .components-notice.is-error, .block-editor-warning, .is-invalid, .acf-error'))
                            ) {
                                tabErrors[currentTabKey] = true;
                            }
                        }
                    });
                    // For each tab, add indicator if needed
                    Object.entries(tabErrors).forEach(([tabKey, hasError]) => {
                        const tabButton = tabGroup.querySelector('.acf-tab-button[data-key="' + tabKey + '"]');
                        if (!tabButton) return;
                        let label = tabButton.querySelector('span') || tabButton;
                        if (hasError) {
                            tabButton.classList.add('acf-tab-has-error');
                            if (!label.querySelector('.acf-error-indicator')) {
                                const icon = document.createElement('span');
                                icon.className = 'acf-error-indicator';
                                icon.textContent = '!'; // visually hidden, replaced by SVG in CSS
                                label.insertBefore(icon, label.firstChild);
                            }
                        } else {
                            tabButton.classList.remove('acf-tab-has-error');
                            const existing = label.querySelector('.acf-error-indicator');
                            if (existing) existing.remove();
                        }
                    });
                });
            }

            // Run on validation and save
            if (acf.addAction) {
                acf.addAction('validation_complete', updateTabErrorIndicators);
                acf.addAction('invalid_field', updateTabErrorIndicators);
                acf.addAction('valid_field', updateTabErrorIndicators);
                acf.addAction('show_field', updateTabErrorIndicators);
                acf.addAction('submit', updateTabErrorIndicators);
                acf.addAction('save_post', updateTabErrorIndicators);
            }
            // Gutenberg: also listen to block editor events
            const isGutenberg =
                document.body.classList.contains('block-editor-page') ||
                document.querySelector('.edit-post-visual-editor') !== null ||
                (typeof wp !== 'undefined' && wp.data && wp.data.select('core/editor'));
            if (isGutenberg && typeof wp !== 'undefined' && wp.data) {
                if (wp.data.subscribe) {
                    let previousValidationErrors = [];
                    wp.data.subscribe(() => {
                        const editor = wp.data.select('core/editor');
                        if (editor && editor.getBlockValidationErrors) {
                            const currentErrors = editor.getBlockValidationErrors();
                            if (JSON.stringify(currentErrors) !== JSON.stringify(previousValidationErrors)) {
                                previousValidationErrors = currentErrors;
                                setTimeout(updateTabErrorIndicators, 100);
                            }
                        }
                    });
                }
                if (wp.hooks && wp.hooks.addAction) {
                    wp.hooks.addAction('blocks.selectBlock', 'acf-tab-errors', updateTabErrorIndicators);
                    wp.hooks.addAction('blocks.updateBlockAttributes', 'acf-tab-errors', updateTabErrorIndicators);
                }
            }
            // Fallback: MutationObserver for dynamic changes
            if (window.MutationObserver) {
                const observer = new MutationObserver(function () {
                    clearTimeout(self.errorUpdateTimeout);
                    self.errorUpdateTimeout = setTimeout(updateTabErrorIndicators, 100);
                });
                observer.observe(document.body, {
                    childList: true,
                    subtree: true,
                    attributes: true,
                    attributeFilter: ['class', 'data-error']
                });
            }
            // Initial run
            setTimeout(updateTabErrorIndicators, 200);
        }
    };
})(jQuery);

App.init();
