/**
 * quick-add.js — Generic inline-form quick-add modal.
 *
 * Usage: add these attributes to any <select>:
 *   data-quick-add-url="/Controller/Create"   — GET loads the inline partial; POST saves
 *   data-quick-add-title="Add New Vendor"     — optional modal title override
 *
 * Add a sentinel option at the top:
 *   <option value="__new__">+ Add New Vendor…</option>
 *
 * When the user picks "__new__", the modal opens, loads the Create partial (GET ?inline=true),
 * intercepts the form submit (POST ?inline=true → JSON {success, id, name}), adds the new option
 * to the originating select, selects it, and closes the modal.
 */
(function () {
    'use strict';

    const modalEl       = document.getElementById('quickAddModal');
    const modalBody     = document.getElementById('quickAddModalBody');
    const modalErrors   = document.getElementById('quickAddModalErrors');
    const modalErrorList = document.getElementById('quickAddModalErrorList');
    const modalTitle    = document.getElementById('quickAddModalLabel');

    if (!modalEl) return;

    const bsModal = new bootstrap.Modal(modalEl, { backdrop: 'static' });

    let _originSelect = null;  // the <select> that triggered the modal
    let _submitBtn    = null;  // the submit button inside the loaded form
    let _saving       = false;

    // ── Wire every matching select ────────────────────────────────────────────

    function wireSelect(sel) {
        sel.addEventListener('change', function () {
            if (this.value !== '__new__') return;
            // Reset to blank so the select isn't stuck on __new__ if user cancels
            this.value = '';
            openQuickAdd(this);
        });
    }

    document.querySelectorAll('select[data-quick-add-url]').forEach(wireSelect);

    // Support selects injected after DOMContentLoaded (e.g. in modals)
    window.quickAddWire = wireSelect;

    // ── Open ─────────────────────────────────────────────────────────────────

    function openQuickAdd(selectEl) {
        _originSelect = selectEl;
        _saving = false;

        const url   = selectEl.dataset.quickAddUrl;
        const title = selectEl.dataset.quickAddTitle || 'Add New';

        modalTitle.textContent = title;
        modalBody.innerHTML = `
            <div class="d-flex align-items-center justify-content-center py-5">
                <div class="spinner-border text-primary me-3" role="status"></div>
                <span class="text-muted">Loading\u2026</span>
            </div>`;
        modalErrors.classList.add('d-none');
        modalErrorList.innerHTML = '';

        bsModal.show();

        const inlineUrl = url.includes('?') ? url + '&inline=true' : url + '?inline=true';
        fetch(inlineUrl, { headers: { 'X-Requested-With': 'XMLHttpRequest' } })
            .then(r => r.text())
            .then(html => {
                modalBody.innerHTML = html;
                // Execute any <script> tags in the injected HTML — innerHTML assignment doesn't run them
                modalBody.querySelectorAll('script').forEach(old => {
                    const s = document.createElement('script');
                    Array.from(old.attributes).forEach(a => s.setAttribute(a.name, a.value));
                    s.textContent = old.textContent;
                    old.replaceWith(s);
                });
                // Re-initialise Bootstrap popovers and validation inside the loaded fragment
                modalBody.querySelectorAll('[data-bs-toggle="popover"]').forEach(el => {
                    new bootstrap.Popover(el, { html: true, trigger: 'focus' });
                });
                if (window.jQuery && $.validator) {
                    const form = modalBody.querySelector('form');
                    if (form) $.validator.unobtrusive.parse(form);
                }
                // Hide the Back/Cancel navigation inside the partial — not needed in a modal
                modalBody.querySelectorAll('.d-flex.justify-content-end a.btn-outline-secondary').forEach(a => {
                    if (a.textContent.trim().startsWith('Back') || a.textContent.trim() === 'Cancel') {
                        a.style.display = 'none';
                    }
                });
                wireFormSubmit();
            })
            .catch(() => {
                modalBody.innerHTML = '<div class="alert alert-danger alert-permanent m-3">Failed to load form. Please try again.</div>';
            });
    }

    // ── Intercept the form inside the loaded partial ──────────────────────────

    function wireFormSubmit() {
        const form = modalBody.querySelector('form');
        if (!form) return;

        // Replace the form's action to include ?inline=true
        const action = form.getAttribute('action') || '';
        if (!action.includes('inline=true')) {
            const sep = action.includes('?') ? '&' : '?';
            form.setAttribute('action', action + sep + 'inline=true');
        }

        // Add a footer Save button to the modal (keeps modal-footer pattern consistent)
        _submitBtn = document.createElement('button');
        _submitBtn.type = 'button';
        _submitBtn.className = 'btn btn-primary px-4';
        _submitBtn.innerHTML = '<i class="bi bi-check-circle me-2"></i>Save';
        _submitBtn.addEventListener('click', () => form.requestSubmit());

        // Also hide the form's own submit button to avoid duplication
        form.querySelectorAll('[type="submit"]').forEach(b => b.style.display = 'none');

        // Inject footer
        const footer = document.createElement('div');
        footer.className = 'modal-footer border-top';
        footer.innerHTML = '<button type="button" class="btn btn-outline-secondary px-4" data-bs-dismiss="modal">Cancel</button>';
        footer.appendChild(_submitBtn);
        modalEl.querySelector('.modal-content').appendChild(footer);

        form.addEventListener('submit', handleSubmit);
    }

    // ── Submit handler ────────────────────────────────────────────────────────

    async function handleSubmit(e) {
        e.preventDefault();
        if (_saving) return;

        const form = e.target;

        // jQuery unobtrusive validation
        if (window.jQuery && $(form).valid && !$(form).valid()) return;

        _saving = true;
        if (_submitBtn) {
            _submitBtn.disabled = true;
            _submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Saving\u2026';
        }
        modalErrors.classList.add('d-none');

        try {
            const data = new FormData(form);
            const resp = await fetch(form.action, { method: 'POST', body: data });
            const json = await resp.json();

            if (json.success) {
                addOptionAndSelect(json.id, json.name);
                // Remove the injected footer before hiding so it doesn't stack on re-open
                const injectedFooter = modalEl.querySelector('.modal-footer.border-top');
                if (injectedFooter) injectedFooter.remove();
                bsModal.hide();
            } else {
                const msgs = (json.errors || ['An unknown error occurred.']).join('<br>');
                modalErrorList.innerHTML = msgs;
                modalErrors.classList.remove('d-none');
            }
        } catch {
            modalErrorList.innerHTML = 'A network error occurred. Please try again.';
            modalErrors.classList.remove('d-none');
        } finally {
            _saving = false;
            if (_submitBtn) {
                _submitBtn.disabled = false;
                _submitBtn.innerHTML = '<i class="bi bi-check-circle me-2"></i>Save';
            }
        }
    }

    // ── Add the new option to the originating select and select it ────────────

    function addOptionAndSelect(id, name) {
        if (!_originSelect) return;

        // Remove sentinel option temporarily so we can check for duplicates
        const existing = _originSelect.querySelector(`option[value="${id}"]`);
        if (!existing) {
            const opt = document.createElement('option');
            opt.value = id;
            opt.textContent = name;

            // Insert in alphabetical order before the sentinel (value="__new__")
            const sentinel = _originSelect.querySelector('option[value="__new__"]');
            const options  = Array.from(_originSelect.options).filter(o => o.value && o.value !== '__new__');
            const after    = options.find(o => o.textContent.toLowerCase() > name.toLowerCase());
            if (after) {
                _originSelect.insertBefore(opt, after);
            } else if (sentinel) {
                _originSelect.insertBefore(opt, sentinel);
            } else {
                _originSelect.appendChild(opt);
            }
        }

        _originSelect.value = id;
        _originSelect.dispatchEvent(new Event('change'));
    }

    // ── Clean up injected footer on modal close ───────────────────────────────

    modalEl.addEventListener('hidden.bs.modal', function () {
        const injectedFooter = modalEl.querySelector('.modal-footer.border-top');
        if (injectedFooter) injectedFooter.remove();
        _saving = false;
        _submitBtn = null;
    });

})();
