// assets/alpine/dropdown-portal.js

export function registerDropdownPortal(Alpine) {
    Alpine.data('dropdownPortal', (opts = {}) => ({
        open: false,
        align: opts.align ?? 'right',
        cleanup: null,

        toggle() {
            this.open ? this.close() : this.show();
        },

        show() {
            this.open = true;

            this.$nextTick(() => {
                const menu = this.$refs.menu;
                const btn = this.$refs.btn;
                if (!menu || !btn) return;

                // Empêche le flash (top-left) : on le rend "mesurable" mais invisible
                menu.style.visibility = 'hidden';
                menu.style.display = 'block';
                menu.classList.add('opacity-0');

                this.reposition();

                // Affiche proprement après positionnement
                requestAnimationFrame(() => {
                    menu.style.visibility = 'visible';
                    menu.classList.remove('opacity-0');
                });

                const onDocClick = (e) => {
                    if (this.$refs.btn?.contains(e.target)) return;
                    if (this.$refs.menu?.contains(e.target)) return;
                    this.close();
                };

                const onKey = (e) => {
                    if (e.key === 'Escape') this.close();
                };

                const onScrollOrResize = () => this.reposition();

                document.addEventListener('mousedown', onDocClick);
                document.addEventListener('keydown', onKey);

                window.addEventListener('resize', onScrollOrResize, { passive: true });
                // capture=true : capte aussi les scrolls des containers overflow
                window.addEventListener('scroll', onScrollOrResize, { passive: true, capture: true });

                this.cleanup = () => {
                    document.removeEventListener('mousedown', onDocClick);
                    document.removeEventListener('keydown', onKey);

                    window.removeEventListener('resize', onScrollOrResize);
                    window.removeEventListener('scroll', onScrollOrResize, true);
                };
            });
        },

        close() {
            this.open = false;

            const menu = this.$refs.menu;
            if (menu) {
                // reset "safe" (utile si un x-transition laisse trainer un display)
                menu.style.visibility = 'hidden';
                menu.classList.add('opacity-0');
            }

            if (this.cleanup) {
                this.cleanup();
                this.cleanup = null;
            }
        },

        reposition() {
            if (!this.open) return;

            const btn = this.$refs.btn;
            const menu = this.$refs.menu;
            if (!btn || !menu) return;

            // reset pour mesurer correctement
            menu.style.left = '0px';
            menu.style.top = '0px';

            const r = btn.getBoundingClientRect();
            const m = menu.getBoundingClientRect();
            const gap = 8;

            let top = r.bottom + gap;
            let left = this.align === 'left'
                ? r.left
                : (r.right - m.width);

            // clamp dans le viewport
            const pad = 8;
            left = Math.max(pad, Math.min(left, window.innerWidth - m.width - pad));

            // flip si pas la place en bas
            if (top + m.height > window.innerHeight - pad) {
                top = Math.max(pad, r.top - gap - m.height);
            }

            menu.style.top = `${top}px`;
            menu.style.left = `${left}px`;
        },
    }));
}
