// retoor <retoor@molodetz.nl>

export class ModalManager {
    constructor() {
        this.initPasswordToggles();
        this.initModals();
        this.initConfirmations();
    }

    initPasswordToggles() {
        document.querySelectorAll(".auth-toggle-pw").forEach((btn) => {
            btn.addEventListener("click", () => {
                const input = btn.parentElement.querySelector("input");
                if (!input) {
                    return;
                }
                const type = input.type === "password" ? "text" : "password";
                input.type = type;
                btn.textContent = type === "password" ? "\u{1F441}" : "\u{1F648}";
            });
        });
    }

    initModals() {
        document.querySelectorAll("[data-modal]").forEach((trigger) => {
            trigger.addEventListener("click", (e) => {
                e.preventDefault();
                const modalId = trigger.dataset.modal;
                const modal = document.getElementById(modalId);
                if (modal) {
                    modal.classList.add("visible");
                }
            });
        });

        document.querySelectorAll(".modal-overlay").forEach((modal) => {
            modal.addEventListener("click", (e) => {
                if (e.target === modal) {
                    modal.classList.remove("visible");
                }
            });
            modal.querySelectorAll(".modal-close").forEach((closeBtn) => {
                closeBtn.addEventListener("click", () => {
                    modal.classList.remove("visible");
                });
            });
            this.enhanceModal(modal);
        });

        document.addEventListener("keydown", (e) => {
            if (e.key !== "Escape") return;
            const open = [...document.querySelectorAll(".modal-overlay.visible")].pop();
            if (open) open.classList.remove("visible");
        });
    }

    enhanceModal(modal) {
        if (!modal.getAttribute("role")) modal.setAttribute("role", "dialog");
        modal.setAttribute("aria-modal", "true");
        const heading = modal.querySelector(
            ".modal-title, .modal-header h1, .modal-header h2, .modal-header h3, h1, h2, h3"
        );
        if (heading) {
            if (!heading.id) {
                heading.id = `modal-title-${Math.random().toString(36).slice(2, 9)}`;
            }
            modal.setAttribute("aria-labelledby", heading.id);
        }

        const trap = (e) => {
            if (e.key !== "Tab") return;
            const items = this.focusable(modal);
            if (!items.length) return;
            const first = items[0];
            const last = items[items.length - 1];
            if (e.shiftKey && document.activeElement === first) {
                e.preventDefault();
                last.focus();
            } else if (!e.shiftKey && document.activeElement === last) {
                e.preventDefault();
                first.focus();
            }
        };

        const observer = new MutationObserver(() => {
            const visible = modal.classList.contains("visible");
            if (visible && !modal._a11yOpen) {
                modal._a11yOpen = true;
                modal._lastFocus = document.activeElement;
                modal.addEventListener("keydown", trap);
                const items = this.focusable(modal);
                if (items.length) setTimeout(() => items[0].focus(), 20);
            } else if (!visible && modal._a11yOpen) {
                modal._a11yOpen = false;
                modal.removeEventListener("keydown", trap);
                if (modal._lastFocus && modal._lastFocus.focus) modal._lastFocus.focus();
            }
        });
        observer.observe(modal, { attributes: true, attributeFilter: ["class"] });
    }

    focusable(root) {
        return [
            ...root.querySelectorAll(
                'a[href], button:not([disabled]), input:not([disabled]):not([type="hidden"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
            ),
        ].filter((el) => el.offsetParent !== null || el === document.activeElement);
    }

    initConfirmations() {
        document.addEventListener("click", (e) => {
            const el = e.target.closest("[data-confirm]");
            if (!el) return;
            if (el.hasAttribute("data-auto-submit")) return;
            if (el.dataset.confirmed === "1") {
                delete el.dataset.confirmed;
                return;
            }
            e.preventDefault();
            e.stopImmediatePropagation();
            const proceed = () => {
                if (!el.isConnected) return;
                el.dataset.confirmed = "1";
                el.click();
            };
            const dialog = window.app && window.app.dialog;
            if (!dialog) {
                if (confirm(el.dataset.confirm)) proceed();
                return;
            }
            dialog.confirm({
                message: el.dataset.confirm,
                title: el.dataset.confirmTitle || "Please confirm",
                confirmLabel: el.dataset.confirmLabel,
                danger: el.dataset.confirmDanger !== undefined,
            }).then((ok) => {
                if (ok) proceed();
            });
        }, true);
    }
}
