/**
 * Centralized checkbox with hidden fallback handling
 * Provides reusable functionality across all templates
 *
 * CHECKBOX-HIDDEN FALLBACK PATTERN:
 * ----------------------------------
 * This module implements a pattern to ensure both checked and unchecked checkbox
 * states are properly submitted in HTML forms:
 *
 * 1. Each checkbox is paired with a hidden input via the data-hidden-fallback attribute
 * 2. When checkbox is CHECKED: hidden input is DISABLED (checkbox value is submitted)
 * 3. When checkbox is UNCHECKED: hidden input is ENABLED (hidden "false" value is submitted)
 *
 * This solves the HTML limitation where unchecked checkboxes don't submit any value
 * in traditional form POST submissions.
 *
 * IMPORTANT - Two Submission Modes:
 * ----------------------------------
 * 1. AJAX Mode (Primary): JavaScript reads checkbox.checked directly from DOM
 *    - Hidden inputs are managed but NOT used
 *    - Exists for code consistency and fallback support
 *
 * 2. Traditional POST Mode (Fallback): When JavaScript is disabled
 *    - Browser submits form data directly
 *    - Hidden inputs provide unchecked checkbox values
 *    - Critical for accessibility and no-JS environments
 *
 * Usage:
 * - Add data-hidden-fallback="hidden_input_id" to any checkbox
 * - Create a hidden input with the same name and value="false"
 * - This handler automatically manages the disabled state
 *
 * Features:
 * - Auto-initialization on DOM ready
 * - Form submission integration (for traditional POST)
 * - Cleanup method for dynamically created/removed checkboxes
 * - Mutation observer for dynamically added checkboxes
 * - Works in both AJAX and traditional POST modes
 */
(function() {
    'use strict';

    const CheckboxHandler = {
        _initialized: false,
        _observer: null,

        /**
         * Initialize all checkbox-hidden fallback pairs
         * @returns {void}
         */
        init: function() {
            if (this._initialized) {
                console.warn('CheckboxHandler already initialized, skipping duplicate initialization');
                return;
            }

            this.initializeCheckboxes();
            this.setupFormSubmissionHandler();
            this.setupMutationObserver();
            this._initialized = true;
            console.log('Checkbox handler initialized');
        },

        /**
         * Initialize all checkbox-hidden input pairs
         * @returns {void}
         * @private
         */
        initializeCheckboxes: function() {
            // Find all checkboxes with hidden fallback attribute
            document.querySelectorAll('input[type="checkbox"][data-hidden-fallback]').forEach(checkbox => {
                this.setupCheckbox(checkbox);
            });
        },

        /**
         * Setup individual checkbox with hidden input
         * @param {HTMLInputElement} checkbox - The checkbox element
         * @returns {void}
         * @private
         */
        setupCheckbox: function(checkbox) {
            const hiddenId = checkbox.dataset.hiddenFallback;

            if (!hiddenId) {
                console.warn('Checkbox has data-hidden-fallback attribute but no value', checkbox);
                return;
            }

            const hiddenInput = document.getElementById(hiddenId);

            if (!hiddenInput) {
                console.warn(`Hidden input not found: ${hiddenId}`);
                return;
            }

            try {
                // Set initial state: disable hidden when checkbox is checked
                hiddenInput.disabled = checkbox.checked;

                // Add change listener
                const changeHandler = () => {
                    try {
                        hiddenInput.disabled = checkbox.checked;
                    } catch (e) {
                        console.error('Failed to update hidden input:', e);
                    }
                };

                checkbox.addEventListener('change', changeHandler);

                // Store handler reference for potential cleanup
                checkbox._checkboxHandlerCleanup = () => {
                    checkbox.removeEventListener('change', changeHandler);
                };
            } catch (e) {
                console.error('Failed to setup checkbox:', e);
            }
        },

        /**
         * Cleanup event listeners for a specific checkbox
         * @param {HTMLInputElement} checkbox - The checkbox element to cleanup
         * @returns {void}
         * @public
         */
        cleanup: function(checkbox) {
            if (checkbox._checkboxHandlerCleanup) {
                checkbox._checkboxHandlerCleanup();
                delete checkbox._checkboxHandlerCleanup;
            }
        },

        /**
         * Set up document-level form submission handler
         * Ensures all checkbox-hidden pairs are synced before any form submits
         * @returns {void}
         * @private
         */
        setupFormSubmissionHandler: function() {
            document.addEventListener('submit', (event) => {
                this.prepareFormSubmission(event.target);
            });
        },

        /**
         * Prepare a specific form for submission by syncing all checkbox-hidden pairs
         * @param {HTMLFormElement} form - The form element to prepare
         * @returns {void}
         * @public
         */
        prepareFormSubmission: function(form) {
            form.querySelectorAll('input[type="checkbox"][data-hidden-fallback]').forEach(checkbox => {
                const hiddenId = checkbox.dataset.hiddenFallback;

                if (!hiddenId) {
                    console.warn('Checkbox has data-hidden-fallback attribute but no value during form submission', checkbox);
                    return;
                }

                const hiddenInput = document.getElementById(hiddenId);
                if (hiddenInput) {
                    try {
                        hiddenInput.disabled = checkbox.checked;
                    } catch (e) {
                        console.error('Failed to update hidden input during form submission:', e);
                    }
                } else {
                    console.warn(`Hidden input not found during form submission: ${hiddenId}`);
                }
            });
        },

        /**
         * Set up mutation observer to handle dynamically added checkboxes
         * @returns {void}
         * @private
         */
        setupMutationObserver: function() {
            this._observer = new MutationObserver((mutations) => {
                mutations.forEach((mutation) => {
                    mutation.addedNodes.forEach((node) => {
                        if (node.nodeType === 1) { // Element node
                            // Check if the node itself is a checkbox
                            if (node.matches && node.matches('input[type="checkbox"][data-hidden-fallback]')) {
                                this.setupCheckbox(node);
                            }
                            // Check for checkboxes within the added node
                            if (node.querySelectorAll) {
                                const checkboxes = node.querySelectorAll('input[type="checkbox"][data-hidden-fallback]');
                                checkboxes.forEach(checkbox => this.setupCheckbox(checkbox));
                            }
                        }
                    });
                });
            });

            this._observer.observe(document.body, { childList: true, subtree: true });
        },

        /**
         * Disconnect the mutation observer
         * @returns {void}
         * @public
         */
        disconnect: function() {
            if (this._observer) {
                this._observer.disconnect();
                this._observer = null;
            }
        }
    };

    // Export for global access
    window.checkboxHandler = CheckboxHandler;

    // Auto-initialize on DOM ready
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', () => CheckboxHandler.init());
    } else {
        CheckboxHandler.init();
    }
})();
