/**
 * Summernote (descripción), Tom Select (búsqueda en selects),
 * Vue 3: imagen destacada (vista prevía + subida) y modales sede/categoría.
 *
 * Configuración en `#rt-event-form` (data-* URLs y CSRF en meta).
 */
(function () {
    'use strict';

    if (typeof window.jQuery === 'undefined') {
        return;
    }
    var $ = window.jQuery;

    function formEl() {
        return document.getElementById('rt-event-form');
    }

    function csrf() {
        var m = document.querySelector('meta[name="csrf-token"]');
        return m ? m.getAttribute('content') : '';
    }

    function initSummernote() {
        var $ta = $('#description');
        if (!$ta.length || typeof $ta.summernote !== 'function') {
            return;
        }
        if ($ta.next('.note-editor').length) {
            return;
        }
        $ta.summernote({
            height: 280,
            lang: 'es-ES',
            placeholder: $ta.attr('placeholder') || '',
            toolbar: [
                ['style', ['style']],
                ['font', ['bold', 'italic', 'underline', 'clear']],
                ['para', ['ul', 'ol', 'paragraph']],
                ['insert', ['link', 'picture']],
                ['view', ['fullscreen', 'codeview', 'help']],
            ],
            callbacks: {
                onImageUpload: function (files) {
                    for (var i = 0; i < files.length; i++) {
                        uploadSummernoteImage(files[i], $ta);
                    }
                },
            },
        });
    }

    function uploadSummernoteImage(file, $ta) {
        var fd = new FormData();
        fd.append('file', file);
        var uploadUrl = (formEl() && formEl().dataset.featuredUploadUrl) || '';
        if (!uploadUrl) {
            return;
        }
        fetch(uploadUrl, {
            method: 'POST',
            headers: {
                'X-CSRF-TOKEN': csrf(),
                Accept: 'application/json',
                'X-Requested-With': 'XMLHttpRequest',
            },
            body: fd,
        })
            .then(function (r) {
                return r.json();
            })
            .then(function (data) {
                if (data && data.url) {
                    $ta.summernote('insertImage', data.url);
                }
            })
            .catch(function () {});
    }

    function tomDefaults() {
        return {
            allowEmptyOption: false,
            create: false,
            maxOptions: 500,
        };
    }

    function bindTomSelect(el) {
        if (!el || el.tagName !== 'SELECT' || el.closest('.note-editor')) {
            return;
        }
        if (el.tomselect) {
            return;
        }
        if (!window.TomSelect) {
            return;
        }
        try {
            new TomSelect(el, tomDefaults());
        } catch (e) {}
    }

    window.rtInitTomSelectIn = function (root) {
        if (!root || !window.TomSelect) {
            return;
        }
        root.querySelectorAll('select.rt-ts-search').forEach(bindTomSelect);
    };

    window.rtDestroyTomSelectIn = function (root) {
        if (!root) {
            return;
        }
        root.querySelectorAll('select.rt-ts-search').forEach(function (el) {
            if (el.tomselect) {
                el.tomselect.destroy();
            }
        });
    };

    function initGlobalTomSelects() {
        window.rtInitTomSelectIn(document);
    }

    function parseUploadJson(res) {
        if (res == null) {
            return null;
        }
        if (typeof res === 'object' && res.path) {
            return res;
        }
        if (typeof res === 'string') {
            try {
                return JSON.parse(res);
            } catch (e) {
                return null;
            }
        }
        return null;
    }

    function mountFeaturedImageVue() {
        var mount = document.getElementById('rt-featured-vue');
        var form = formEl();
        if (!mount || !form || !window.Vue) {
            return;
        }
        var tpl = document.getElementById('rt-featured-vue-template');
        if (!tpl || !tpl.innerHTML) {
            return;
        }
        var uploadUrl = form.dataset.featuredUploadUrl || '';
        if (!uploadUrl) {
            return;
        }
        var Vue = window.Vue;
        var i18n = window.rtEventFormI18n || {};
        var serverImageUrl = form.dataset.featuredExistingUrl || '';
        var initialTempPath = mount.getAttribute('data-initial-temp-path') || '';
        var initialTempUrl = mount.getAttribute('data-initial-temp-url') || '';
        var maxBytes = 5 * 1024 * 1024;
        var allowedMime = {
            'image/jpeg': true,
            'image/png': true,
            'image/webp': true,
            'image/avif': true,
        };

        Vue.createApp({
            data: function () {
                return {
                    tempRelativePath: initialTempPath,
                    tempPublicUrl: initialTempUrl,
                    serverImageUrl: serverImageUrl,
                    clearedPersisted: false,
                    uploading: false,
                    error: '',
                    chooseLabel: i18n.featuredChoose || 'Elegir imagen',
                    removeLabel: i18n.featuredRemove || 'Quitar imagen',
                    uploadingLabel: i18n.featuredUploading || 'Subiendo…',
                    hintLabel: i18n.featuredHint || '',
                    placeholderText: i18n.featuredPlaceholder || '',
                    invalidTypeMsg: i18n.featuredInvalidType || 'Formato no permitido.',
                    tooBigMsg: i18n.featuredTooBig || 'Archivo demasiado grande.',
                    uploadErrMsg: i18n.featuredUploadError || 'Error al subir.',
                };
            },
            computed: {
                displayUrl: function () {
                    if (this.tempRelativePath && this.tempPublicUrl) {
                        return this.tempPublicUrl;
                    }
                    if (!this.clearedPersisted && this.serverImageUrl) {
                        return this.serverImageUrl;
                    }
                    return '';
                },
            },
            methods: {
                openPicker: function () {
                    this.error = '';
                    this.$refs.fileInput.value = '';
                    this.$refs.fileInput.click();
                },
                remove: function () {
                    this.error = '';
                    if (this.tempRelativePath) {
                        this.tempRelativePath = '';
                        this.tempPublicUrl = '';
                        return;
                    }
                    if (this.serverImageUrl && !this.clearedPersisted) {
                        this.clearedPersisted = true;
                    }
                },
                onFileChange: function (e) {
                    var self = this;
                    var file = e.target.files && e.target.files[0];
                    this.error = '';
                    if (!file) {
                        return;
                    }
                    if (!allowedMime[file.type]) {
                        this.error = this.invalidTypeMsg;
                        return;
                    }
                    if (file.size > maxBytes) {
                        this.error = this.tooBigMsg;
                        return;
                    }
                    var fd = new FormData();
                    fd.append('file', file);
                    this.uploading = true;
                    fetch(uploadUrl, {
                        method: 'POST',
                        headers: {
                            'X-CSRF-TOKEN': csrf(),
                            Accept: 'application/json',
                            'X-Requested-With': 'XMLHttpRequest',
                        },
                        body: fd,
                    })
                        .then(function (r) {
                            return r.text().then(function (t) {
                                var j = {};
                                try {
                                    j = t ? JSON.parse(t) : {};
                                } catch (err) {
                                    j = {};
                                }
                                if (!r.ok) {
                                    throw j;
                                }
                                return j;
                            });
                        })
                        .then(function (data) {
                            var parsed = parseUploadJson(data);
                            if (parsed && parsed.path && parsed.url) {
                                self.tempRelativePath = parsed.path;
                                self.tempPublicUrl = parsed.url;
                                self.clearedPersisted = false;
                            } else {
                                self.error = self.uploadErrMsg;
                            }
                        })
                        .catch(function () {
                            self.error = self.uploadErrMsg;
                        })
                        .finally(function () {
                            self.uploading = false;
                            self.$refs.fileInput.value = '';
                        });
                },
            },
            template: '#rt-featured-vue-template',
        }).mount('#rt-featured-vue');
    }

    function firstValidationMessage(payload) {
        if (typeof payload !== 'object' || payload === null) {
            return 'Error';
        }
        if (!payload.errors) {
            return payload.message ? String(payload.message) : 'Error';
        }
        var errs = payload.errors;
        for (var k in errs) {
            if (Object.prototype.hasOwnProperty.call(errs, k) && errs[k] && errs[k][0]) {
                return String(errs[k][0]);
            }
        }
        return payload.message ? String(payload.message) : 'Error';
    }

    function mountCatalogVue() {
        var mountEl = document.getElementById('rt-catalog-vue');
        var form = formEl();
        if (!mountEl || !form || !window.Vue) {
            return;
        }
        var venueUrl = form.dataset.venueStoreUrl || '';
        var catUrl = form.dataset.categoryStoreUrl || '';
        var mapsKey = form.dataset.googleMapsKey || '';
        var Vue = window.Vue;
        Vue.createApp({
            data: function () {
                return {
                    showV: false,
                    showC: false,
                    nameV: '',
                    nameC: '',
                    errV: '',
                    errC: '',
                    mapsKey: mapsKey,
                    addr1: '',
                    addr2: '',
                    cityV: '',
                    regionV: '',
                    postalV: '',
                    countryV: '',
                    latV: '',
                    lngV: '',
                };
            },
            watch: {
                showV: function (open) {
                    var self = this;
                    if (open && this.mapsKey && window.rtCatalogVenuePicker) {
                        this.$nextTick(function () {
                            window.rtCatalogVenuePicker.bootstrap(self, self.mapsKey);
                        });
                    } else if (!open && window.rtCatalogVenuePicker) {
                        window.rtCatalogVenuePicker.teardown();
                    }
                },
            },
            methods: {
                openVenueModal: function () {
                    this.showV = true;
                    this.errV = '';
                },
                closeVenueModal: function () {
                    this.showV = false;
                    if (window.rtCatalogVenuePicker) {
                        window.rtCatalogVenuePicker.teardown();
                    }
                    this.resetVenueFields();
                },
                resetVenueFields: function () {
                    this.nameV = '';
                    this.addr1 = '';
                    this.addr2 = '';
                    this.cityV = '';
                    this.regionV = '';
                    this.postalV = '';
                    this.countryV = '';
                    this.latV = '';
                    this.lngV = '';
                },
                addVenueOption: function (id, name) {
                    var sel = document.getElementById('venue_id');
                    if (!sel || !sel.tomselect) {
                        return;
                    }
                    sel.tomselect.addOption({ value: String(id), text: name });
                    sel.tomselect.setValue(String(id), true);
                },
                addCategoryOption: function (id, name) {
                    var sel = document.getElementById('category_id');
                    if (!sel || !sel.tomselect) {
                        return;
                    }
                    sel.tomselect.addOption({ value: String(id), text: name });
                    sel.tomselect.setValue(String(id), true);
                },
                postJson: function (url, body) {
                    return fetch(url, {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'X-CSRF-TOKEN': csrf(),
                            Accept: 'application/json',
                        },
                        body: JSON.stringify(body),
                    }).then(function (r) {
                        return r.text().then(function (t) {
                            var j = {};
                            try {
                                j = t ? JSON.parse(t) : {};
                            } catch (e) {
                                j = {};
                            }
                            if (!r.ok) {
                                throw j;
                            }
                            return j;
                        });
                    });
                },
                venuePayload: function () {
                    function numOrNull(s) {
                        if (s === '' || s === null || typeof s === 'undefined') {
                            return null;
                        }
                        var n = parseFloat(String(s).replace(',', '.'));
                        return isNaN(n) ? null : n;
                    }
                    return {
                        name: this.nameV.trim(),
                        address_line_1: this.addr1.trim() || null,
                        address_line_2: this.addr2.trim() || null,
                        city: this.cityV.trim() || null,
                        region: this.regionV.trim() || null,
                        postal_code: this.postalV.trim() || null,
                        country: this.countryV.trim() || null,
                        latitude: numOrNull(this.latV),
                        longitude: numOrNull(this.lngV),
                    };
                },
                saveVenue: function () {
                    var self = this;
                    this.errV = '';
                    this.postJson(venueUrl, this.venuePayload())
                        .then(function (data) {
                            if (data.venue) {
                                self.addVenueOption(data.venue.id, data.venue.name);
                            }
                            self.showV = false;
                            if (window.rtCatalogVenuePicker) {
                                window.rtCatalogVenuePicker.teardown();
                            }
                            self.resetVenueFields();
                            if (data.requires_review && typeof Swal !== 'undefined') {
                                Swal.fire({
                                    icon: 'info',
                                    title: 'Recinto registrado',
                                    text: 'Un administrador debe aprobar esta sede antes de que otros organizadores puedan usarla. Tú puedes usarla en tus eventos mientras tanto.',
                                    confirmButtonColor: '#b91830',
                                });
                            }
                        })
                        .catch(function (e) {
                            self.errV = firstValidationMessage(e);
                        });
                },
                saveCat: function () {
                    var self = this;
                    this.errC = '';
                    this.postJson(catUrl, { name: this.nameC })
                        .then(function (data) {
                            if (data.category) {
                                self.addCategoryOption(data.category.id, data.category.name);
                            }
                            self.showC = false;
                            self.nameC = '';
                            if (data.requires_review && typeof Swal !== 'undefined') {
                                Swal.fire({
                                    icon: 'info',
                                    title: 'Categoría registrada',
                                    text: 'Un administrador debe aprobarla antes de que otros organizadores puedan usarla.',
                                    confirmButtonColor: '#b91830',
                                });
                            }
                        })
                        .catch(function (e) {
                            self.errC = firstValidationMessage(e);
                        });
                },
            },
            template: '#rt-catalog-vue-template',
        }).mount('#rt-catalog-vue');
    }

    function syncSummernoteBeforeSubmit() {
        var $ta = $('#description');
        if ($ta.length && typeof $ta.summernote === 'function' && $ta.next('.note-editor').length) {
            var html = $ta.summernote('code');
            $ta.val(html);
        }
    }

    /** Flechas de las secciones 2 y 3 (collapse Bootstrap). */
    function bindStepSectionCollapseChevrons() {
        if (typeof window.jQuery === 'undefined') {
            return;
        }
        var $ = window.jQuery;
        $(document)
            .off('shown.bs.collapse.rtStepSect hidden.bs.collapse.rtStepSect')
            .on(
                'shown.bs.collapse.rtStepSect hidden.bs.collapse.rtStepSect',
                '#rt-collapse-entradas, #rt-collapse-enviar',
                function (e) {
                    var id = '#' + e.target.id;
                    var $btn = $('[data-target="' + id + '"]');
                    if (!$btn.length) {
                        return;
                    }
                    var open = e.type.indexOf('shown') === 0;
                    $btn.attr('aria-expanded', open ? 'true' : 'false');
                    $btn.find('.rt-step-panel-chevron').toggleClass('rt-chevron-open', open);
                }
            );
    }

    /** Enlaces del menú «1 · 2 · 3» abren el bloque correspondiente. */
    function bindStepNavLinksExpandSections() {
        if (typeof window.jQuery === 'undefined') {
            return;
        }
        var $ = window.jQuery;
        $(document).on('click', 'a[href="#rt-step-entradas"]', function () {
            window.setTimeout(function () {
                $('#rt-collapse-entradas').collapse('show');
            }, 150);
        });
        $(document).on('click', 'a[href="#rt-step-enviar"]', function () {
            window.setTimeout(function () {
                $('#rt-collapse-enviar').collapse('show');
            }, 150);
        });
    }

    /**
     * Componente Alpine `rtBibConfig`: configura el rango de BIB y los reservados.
     *
     * Expone:
     *  - mode, start, end, padding, reserved (sincronizados con inputs).
     *  - reservedCount: cantidad de números en `reserved` (parseados).
     *  - nextAvailable: primer BIB libre dentro del rango excluyendo reservados.
     *  - canonicalize(): reformatea `reserved` colapsando contiguos (1,2,3,4 → 1-4).
     *
     * Se registra escuchando `alpine:init` para asegurar que esté disponible
     * antes de que Alpine procese los `x-data` del DOM.
     */
    (function registerBibAlpineComponent() {
        function parseRanges(raw) {
            if (typeof raw !== 'string') {
                return [];
            }
            var tokens = raw.split(/[\s,;\r\n]+/);
            var seen = Object.create(null);
            for (var t = 0; t < tokens.length; t++) {
                var token = tokens[t].trim();
                if (!token) {
                    continue;
                }
                var rangeMatch = token.match(/^(\d+)\s*[-–]\s*(\d+)$/);
                if (rangeMatch) {
                    var a = parseInt(rangeMatch[1], 10);
                    var b = parseInt(rangeMatch[2], 10);
                    if (isNaN(a) || isNaN(b) || a > b || a < 0) {
                        continue;
                    }
                    if (b - a > 100000) {
                        continue;
                    }
                    for (var i = a; i <= b; i++) {
                        seen[i] = true;
                    }
                    continue;
                }
                if (/^\d+$/.test(token)) {
                    seen[parseInt(token, 10)] = true;
                }
            }
            var nums = Object.keys(seen).map(Number);
            nums.sort(function (a, b) { return a - b; });
            return nums;
        }

        function canonicalize(nums) {
            if (!nums.length) {
                return '';
            }
            var segments = [];
            var start = nums[0];
            var prev = nums[0];
            for (var i = 1; i < nums.length; i++) {
                if (nums[i] === prev + 1) {
                    prev = nums[i];
                    continue;
                }
                segments.push(start === prev ? String(start) : start + '-' + prev);
                start = prev = nums[i];
            }
            segments.push(start === prev ? String(start) : start + '-' + prev);
            return segments.join(', ');
        }

        function pad(n, width) {
            var s = String(n);
            while (s.length < width) {
                s = '0' + s;
            }
            return s;
        }

        function register() {
            if (!window.Alpine || typeof window.Alpine.data !== 'function') {
                return;
            }
            window.Alpine.data('rtBibConfig', function (initial) {
                return {
                    mode: initial.mode || 'later',
                    start: typeof initial.start === 'number' ? initial.start : 1,
                    end: initial.end == null ? null : initial.end,
                    padding: typeof initial.padding === 'number' ? initial.padding : 0,
                    reserved: initial.reserved || '',
                    get reservedNumbers() {
                        return parseRanges(this.reserved);
                    },
                    get reservedCount() {
                        return this.reservedNumbers.length;
                    },
                    get nextAvailable() {
                        var s = parseInt(this.start, 10);
                        if (isNaN(s) || s < 0) {
                            s = 0;
                        }
                        var e = this.end == null || this.end === '' ? null : parseInt(this.end, 10);
                        if (e !== null && (isNaN(e) || e < s)) {
                            return '—';
                        }
                        var reserved = this.reservedNumbers;
                        var reservedSet = Object.create(null);
                        for (var i = 0; i < reserved.length; i++) {
                            reservedSet[reserved[i]] = true;
                        }
                        var cap = e === null ? s + 100000 : e;
                        for (var n = s; n <= cap; n++) {
                            if (!reservedSet[n]) {
                                return this.padding > 0 ? pad(n, this.padding) : String(n);
                            }
                        }
                        return '—';
                    },
                    canonicalize: function () {
                        this.reserved = canonicalize(parseRanges(this.reserved));
                    },
                };
            });
        }

        if (window.Alpine) {
            register();
        } else {
            document.addEventListener('alpine:init', register);
        }
    })();

    document.addEventListener('DOMContentLoaded', function () {
        var form = formEl();
        if (!form) {
            return;
        }
        initSummernote();
        initGlobalTomSelects();
        mountFeaturedImageVue();
        mountCatalogVue();
        bindStepSectionCollapseChevrons();
        bindStepNavLinksExpandSections();
        form.addEventListener(
            'invalid',
            function (e) {
                var t = e.target;
                if (!t || !t.closest) {
                    return;
                }
                var col = t.closest('.collapse');
                if (
                    col &&
                    (col.id === 'rt-collapse-entradas' || col.id === 'rt-collapse-enviar') &&
                    !col.classList.contains('show') &&
                    window.jQuery
                ) {
                    window.jQuery(col).collapse('show');
                }
            },
            true
        );
        $(form).on('submit', function () {
            syncSummernoteBeforeSubmit();
        });
    });
})();
