<template>
    <div class="row" @keydown.enter.prevent>
        <input v-if="linkField" type="hidden" :id="linkField" :value="idThesaurus">
        <input
            class="saisie-30emr" type="text"
            autocomplete="off"
            completion="categories_mul"
            :value="category.displayLabel"
            :id="inputNameLabel"
            :name="inputNameLabel"
            :autfield="inputNameId"
            :linkfield="linkField"
            :callback="functionNameChange"
        />
        <input
            type="hidden"
            :id="inputNameId"
            :name="inputNameId"
            :value="category.id"
        />
        <input
            class="bouton" type="button"
            @click="openPopup()"
            :title="messages.get('common', 'search')"
            :value="messages.get('common', 'search_short')"
        />
        <input
            class="bouton" type="button"
            @click="deleteField($event)"
            :title="messages.get('common', 'remove')"
            :value="messages.get('common', 'remove_short')"
        />
        <slot></slot>
    </div>
</template>

<script>
export default {
    props: {
        multiple: {
            type: Boolean,
            required: false,
            default: () => false
        },
        idThesaurus: {
            type: Number,
            required: false,
            default: () => 0
        },
        index: {
            type: Number,
            required: false,
            default: () => 0
        },
        category: {
            type: Object,
            required: false,
            default: () => { return { id: 0, displayLabel: ''}}
        }
    },
    watch: {
        idThesaurus(oldVal, newVal) {
            if (oldVal !== newVal) {
                this.deleteField();
            }
        }
    },
    mounted() {
        window[this.functionNameChange] = this.changeField.bind(this);
        this.addScript('./javascript/ajax.js', 'ajax_pack_element_without_spans').then(() => {
            const node = document.getElementById(this.inputNameLabel);
            ajax_pack_element_without_spans(node, this.index);
        });
    },
    unmounted() {
        delete window[this.functionNameChange];
    },
    computed: {
        functionNameChange() {
            return `changeCategory${this.index}`;
        },
        linkField() {
            return this.idThesaurus ? `id_thesaurus_${this.index}` : '';
        },
        inputNameLabel() {
            return this.multiple ? `category_libelle${this.index}` : 'category_libelle';
        },
        inputNameId() {
            return this.multiple ? `category_id${this.index}` : 'category_id';
        },
    },
    methods: {
        /**
         * Injects a script tag into the document head if not already present,
         * then waits until a specific global function is available before resolving.
         *
         * @param {string} src - The script URL to load.
         * @param {string} readyFn - The global function name to wait for.
         * @param {number} [maxAttempts=100] - Maximum polling attempts (100 * 50ms = 5s).
         * @returns {Promise<void>}
         */
        addScript(src, readyFn, maxAttempts = 100) {
            return new Promise((resolve, reject) => {
                const existingScript = document.querySelector(`script[src="${src}"]`);

                if (!existingScript) {
                    const script = document.createElement('script');
                    script.src = src;
                    script.onerror = () => reject(new Error(`Script load error for ${src}`));
                    document.head.appendChild(script);
                }

                let attempts = 0;

                const waitForFunction = () => {
                    if (typeof window[readyFn] === 'function') {
                        resolve();
                        return;
                    }

                    if (attempts >= maxAttempts) {
                        reject(new Error(`Timeout: "${readyFn}" not available after ${maxAttempts} attempts`));
                        return;
                    }

                    attempts++;
                    setTimeout(waitForFunction, 50);
                };

                waitForFunction();
            });
        },
        /**
         * Opens the category selector popup.
         *
         * @returns {void}
         */
        openPopup() {
            const caller = this.$el.closest('form').name || document.body.getAttribute('page_name') + '_form';

            const params = new URLSearchParams();
            params.append('what', 'categorie');
            params.append('caller', caller);
            params.append('p1', this.inputNameId);
            params.append('p2', this.inputNameLabel);
            params.append('keep_tilde', '1');
            params.append('parent', '0');
            params.append('id2', '');
            params.append('callback', this.functionNameChange);
            if (this.idThesaurus) {
                params.append('id_thes_unique', this.idThesaurus);
            }

            openPopUp('./select.php?' + params.toString(), 'selector_category')
        },
        /**
         * Updates the category data when the category is changed.
         *
         * @returns {void}
         */
        changeField() {
            const nameNode = document.getElementById(this.inputNameLabel);
            const idNode = document.getElementById(this.inputNameId);
            if (!nameNode || !idNode) {
                this.deleteField();
                return;
            }

            const displayLabel = nameNode.value;
            const id = Number.parseInt(idNode.value, 10);

            this.$set(this.category, 'id', id);
            this.$set(this.category, 'displayLabel', displayLabel);
            this.$emit('categoryChange', this.index, this.category)
        },
        /**
         * Deletes the category data when the category is deleted.
         *
         * @param {Event} event - The event that triggered the deletion.
         * @returns {void}
         */
        deleteField(event) {
            const nameNode = document.getElementById(this.inputNameLabel);
            if (nameNode) {
                nameNode.value = '';
            }

            const idNode = document.getElementById(this.inputNameId);
            if (idNode) {
                idNode.value = '';
            }

            this.$set(this.category, 'id', 0);
            this.$set(this.category, 'displayLabel', '');
            this.$emit('categoryDelete', event, this.index)
        },
    }
}
</script>