// Shared skeleton for the three #id_bud_btn slide-out panels:
//   • _bud_panel.html        — post-share        (POSTs to billboard:share_post)
//   • _bud_invite_panel.html — gatekeeper invite (POSTs to epic:invite_gamer)
//   • _bud_add_panel.html    — My Buds add       (POSTs to billboard:add_bud)
//
// Owns: csrf cookie read, open/close + .bud-open html-class, button click,
// Escape, click-outside, Enter-in-input, OK POST + JSON routing, and the
// `data.already_present` duplicate-guard branch (error Brief instead of
// the normal onSuccess append).
//
// Each caller drives it with:
//   bindBudBtn({
//     submitUrl,
//     autocompleteUrl?,
//     onSuccess(data),                    // success path: line/chip/entry/Brief
//     duplicateTargetSelector?(data),     // selector for .bud-duplicate-flash
//   })
//
// `onSuccess(data)` does the panel-specific DOM updates on the new-row path.
// `duplicateTargetSelector(data)` returns a CSS selector for the existing
// element to highlight when the FYI button on the error Brief is clicked
// (.bud-name / .post-recipient / .gate-slot.filled — varies by page).
// _close({clear: true}) fires automatically on every successful response.
//
// `autocompleteUrl` enables bud-autocomplete on the input (post-share +
// gatekeeper panels) by binding bud-autocomplete.js to #id_bud_suggestions.
// My Buds omits it — the autocomplete pool is request.user.buds, which is
// the set you can't usefully re-add.

(function () {
    'use strict';

    window.bindBudBtn = function (opts) {
        opts = opts || {};
        var btn   = document.getElementById('id_bud_btn');
        var panel = document.getElementById('id_bud_panel');
        var input = document.getElementById('id_recipient');
        var ok    = document.getElementById('id_bud_ok');
        var html  = document.documentElement;
        if (!btn || !panel || !input || !ok) return;

        var suggestions = opts.autocompleteUrl
            ? document.getElementById('id_bud_suggestions')
            : null;

        function _csrf() {
            var m = document.cookie.match(/csrftoken=([^;]+)/);
            return m ? m[1] : '';
        }

        function _open() {
            html.classList.add('bud-open');
            btn.classList.add('active');
            setTimeout(function () { input.focus(); }, 60);
        }

        function _close(o) {
            o = o || {};
            html.classList.remove('bud-open');
            btn.classList.remove('active');
            if (o.clear !== false) input.value = '';
        }

        btn.addEventListener('click', function () {
            if (html.classList.contains('bud-open')) _close();
            else _open();
        });

        document.addEventListener('keydown', function (e) {
            if (e.key === 'Escape' && html.classList.contains('bud-open')) _close();
        });

        document.addEventListener('click', function (e) {
            if (!html.classList.contains('bud-open')) return;
            if (panel.contains(e.target)) return;
            if (e.target === btn || btn.contains(e.target)) return;
            // Suggestions live outside the panel (panel has overflow:hidden
            // for its scaleX slide); a click inside them must NOT close+clear.
            if (suggestions && suggestions.contains(e.target)) return;
            _close();
        });

        ok.addEventListener('click', function () {
            var recipient = input.value.trim();
            if (!recipient) return;

            var fd = new FormData();
            fd.set('recipient', recipient);

            fetch(opts.submitUrl, {
                method: 'POST',
                credentials: 'same-origin',
                headers: {
                    'Accept': 'application/json',
                    'X-CSRFToken': _csrf(),
                },
                body: fd,
            })
                .then(function (r) { return r.ok ? r.json() : Promise.reject(r.status); })
                .then(function (data) {
                    if (data && data.already_present) {
                        // Skip onSuccess — there's nothing to append. Show the
                        // error Brief instead. target_selector resolves at call
                        // time from the caller's per-page callback.
                        if (window.Brief) {
                            var sel = (typeof opts.duplicateTargetSelector === 'function')
                                ? opts.duplicateTargetSelector(data) : null;
                            Brief.showDuplicateBanner({
                                display_name:    data.recipient_display,
                                target_selector: sel,
                            });
                        }
                    } else if (typeof opts.onSuccess === 'function') {
                        opts.onSuccess(data);
                    }
                    _close({ clear: true });
                })
                .catch(function () {
                    // Privacy-safe response shape — even an unregistered/self
                    // recipient is a 200. Network/5xx land here; just close.
                });
        });

        input.addEventListener('keydown', function (e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                ok.click();
            }
        });

        if (opts.autocompleteUrl && window.bindBudAutocomplete && suggestions) {
            window.bindBudAutocomplete(input, suggestions, {
                searchUrl: opts.autocompleteUrl,
            });
        }
    };
}());
