(function() {

    // --- GLOBAL FUNCTION ---
    window.attachGlobalValidation = function(formSelector, saveBtnSelector, options = {}) {
        const form = document.querySelector(formSelector);
        const saveBtn = document.querySelector(saveBtnSelector);
        if (!form || !saveBtn) return;

        const containerId = options.containerId || 'addContainer';
        const printTitleText = options.printTitle || 'Trade License';

        // Robust visibility check
        function isVisible(el) {
            if (!el) return false;
            if (el.hidden) return false;
            const style = window.getComputedStyle(el);
            if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') return false;
            // offsetParent covers many cases (excluded for fixed elements), also check clientRects
            if (el.offsetParent === null && el.getClientRects().length === 0) return false;
            return true;
        }

        // Get only visible required fields (at time of validation)
        function getVisibleRequiredFields() {
            return Array.from(form.querySelectorAll('[required]')).filter(f => {
                // if any ancestor is not visible, treat as hidden
                let node = f;
                while (node && node !== document) {
                    if (!isVisible(node)) return false;
                    node = node.parentElement;
                }
                return true;
            });
        }

        // function findOrCreateErrorSpan(field) {
        //     let el = field.nextElementSibling;
        //     if (el && el.classList && el.classList.contains('text-danger')) return el;
        //     const span = document.createElement('span');
        //     span.className = 'text-danger required-error';
        //     span.style.fontSize = '13px';
        //     field.insertAdjacentElement('afterend', span);
        //     return span;
        // }

         function findOrCreateErrorSpan(field) {
            // look for an existing .text-danger next to the field or inside the field's parent
            // avoid returning the label by checking classList.contains('text-danger')
            let el = field.nextElementSibling;
            while (el) {
                if (el.nodeType === 1 && el.classList && el.classList.contains('text-danger')) return el;
                el = el.nextElementSibling;
            }
            const parent = field.parentElement;
            if (parent) {
                const existing = parent.querySelector('.text-danger');
                if (existing) return existing;
            }
            // create and append the span to the parent so it appears below inputs/labels
            const span = document.createElement('span');
            span.className = 'text-danger required-error';
            span.style.fontSize = '13px';
            if (parent) parent.appendChild(span);
            else field.insertAdjacentElement('afterend', span);
            return span;
        }

        // Show all errors at once (only for visible required fields)
        function showAllErrors() {
            let allFilled = true;
            getVisibleRequiredFields().forEach(field => {
                const val = (field.value || '').toString().trim();
                const notFilled = (field.type === 'file' && field.files.length === 0) ||
                                  (field.type === 'checkbox' && !field.checked) ||
                                  (val === '');
                const errorSpan = findOrCreateErrorSpan(field);
                if (notFilled) {
                    errorSpan.textContent = 'This field is required';
                    errorSpan.style.display = 'block';
                    allFilled = false;
                } else {
                    errorSpan.textContent = '';
                    errorSpan.style.display = 'none';
                }
            });
            return allFilled;
        }

        // Clear error dynamically for visible fields only
        // function clearFieldError(e) {
        //     const field = e.target;
        //     if (!field.required) return;
        //     // ignore if not visible
        //     if (!isVisible(field)) return;
        //     const val = (field.value || '').toString().trim();
        //     const filled = (field.type === 'file' && field.files.length > 0) ||
        //                    (field.type === 'checkbox' && field.checked) ||
        //                    (val !== '');
        //     const errorSpan = field.nextElementSibling;
        //     if (errorSpan && filled) {
        //         errorSpan.textContent = '';
        //         errorSpan.style.display = 'none';
        //     }
        // }

         function clearFieldError(e) {
            const field = e.target;
            if (!field.required) return;
            // ignore if not visible
            if (!isVisible(field)) return;
            const val = (field.value || '').toString().trim();
            const filled = (field.type === 'file' && field.files && field.files.length > 0) ||
                           (field.type === 'checkbox' && field.checked) ||
                           (val !== '');
            // find the real error span (don't rely on nextElementSibling which may be a <label>)
            const errorSpan = (function() {
                // try to find existing without creating a new one
                let el = field.nextElementSibling;
                while (el) {
                    if (el.nodeType === 1 && el.classList && el.classList.contains('text-danger')) return el;
                    el = el.nextElementSibling;
                }
                const parent = field.parentElement;
                if (parent) {
                    const existing = parent.querySelector('.text-danger');
                    if (existing) return existing;
                }
                return null;
            })();

            // if (errorSpan && filled) {
            //     errorSpan.textContent = '';
            //     errorSpan.style.display = 'none';
            // }
        }

        form.addEventListener('input', clearFieldError, true);
        form.addEventListener('change', clearFieldError, true);

        // On Save & Print click
        saveBtn.addEventListener('click', function(e) {
            e.preventDefault();

            // Validate only currently visible required fields
            const allFilled = showAllErrors();
            if (!allFilled) {
                const firstErr = form.querySelector('.required-error:not(:empty)');
                if (firstErr) firstErr.scrollIntoView({ behavior: 'smooth', block: 'center' });
                return;
            }

            // After validation passes, reveal upload/footer and hide Save & Print
            const uploadSection = document.getElementById('upload_section');
            if (uploadSection) uploadSection.style.display = 'block';
            const cardFooter = document.getElementById('card-footer');
            if (cardFooter) cardFooter.style.display = 'block';
            saveBtn.style.display = 'none'; // hide Save & Print after making upload visible

            const addContainer = document.getElementById(containerId) || form.querySelector(`#${containerId}`);
            if (!addContainer) return;

            // --- PDF Generation ---
            const clone = addContainer.cloneNode(true);
            clone.style.cssText = `
                font-size:16px; line-height:1.4; padding:20px; margin:0 auto;
                background:#fff; width:210mm; min-height:297mm; box-sizing:border-box;
            `;

            Array.from(clone.querySelectorAll('*')).forEach(el => {
                el.style.fontSize = '16px';
                el.style.margin = '4px 0';
            });

            const printTitle = document.createElement('h2');
            printTitle.style.textAlign = 'center';
            printTitle.style.marginBottom = '18px';
            printTitle.style.fontSize = '18px';
            printTitle.textContent = printTitleText;
            clone.insertBefore(printTitle, clone.firstChild);

            Array.from(clone.querySelectorAll('button')).forEach(btn => btn.remove());
            Array.from(clone.querySelectorAll('.card')).forEach(card => {
                card.style.background = 'white';
                card.style.boxShadow = 'none';
                card.style.border = '1px solid #ccc';
                card.style.marginBottom = '12px';
                card.style.padding = '12px';
            });
            Array.from(clone.querySelectorAll('.selected-value')).forEach(div => div.classList.remove('d-none'));

            let printContainer = document.getElementById('printContainer');
            if (!printContainer) {
                printContainer = document.createElement('div');
                printContainer.id = 'printContainer';
                printContainer.style.position = 'fixed';
                printContainer.style.left = '-9999px';
                document.body.appendChild(printContainer);
            }
            printContainer.innerHTML = '';
            printContainer.appendChild(clone);

            html2canvas(clone, { scrollY: -window.scrollY, backgroundColor: '#fff', scale: 1, useCORS: true })
            .then(canvas => {
                const imgData = canvas.toDataURL('image/jpeg', 0.6);
                const { jsPDF } = window.jspdf;
                const pdf = new jsPDF('p', 'mm', 'a4');
                const margin = 10;
                pdf.addImage(
                    imgData,
                    'JPEG',
                    margin,
                    margin,
                    pdf.internal.pageSize.getWidth() - margin*2,
                    pdf.internal.pageSize.getHeight() - margin*2
                );
                pdf.save(`${printTitleText}.pdf`);
            })
            .catch(err => {
                console.error('PDF generation failed', err);
                alert('Unable to generate PDF. Please try again.');
            });
        });
    };

})();