// 婚姻弹窗辅助入口，承接从 marriage-modals.blade.php 迁移出的全局函数。

import { isAutoScrollEnabled, scrollChatToBottom } from "./message-utils.js";

/**
 * 向聊天主窗口追加一条婚姻系统公告，允许传入受控 HTML 按钮。
 *
 * @param {string} html 系统模板生成的 HTML 内容
 * @returns {void}
 */
export function appendSystemMessage(html) {
    const container = document.getElementById("chat-messages-container");

    if (!container) {
        return;
    }

    const div = document.createElement("div");
    div.style.cssText = "background:linear-gradient(135deg,#fdf4ff,#fce7f3); border-left:3px solid #ec4899; border-radius:6px; padding:5px 12px; margin:3px 0; font-size:13px; line-height:1.6;";
    div.innerHTML = `<span style="color:#9d174d;">${html}</span>`;
    container.appendChild(div);
    scrollChatToBottom(container, isAutoScrollEnabled);
}

/**
 * 打开求婚弹窗入口，从用户名片按钮触发。
 *
 * @param {string} username 求婚对象用户名
 * @returns {Promise<void>}
 */
export async function openProposeModal(username) {
    let rings = [];

    try {
        const response = await fetch(window.chatContext.marriage.myRingsUrl, {
            headers: {
                Accept: "application/json",
            },
        });
        const data = await response.json();

        if (data.status === "success") {
            rings = data.rings || [];
        }
    } catch {
        // 网络异常时继续交给后端兜底，避免前端误拦截真实可用的求婚流程。
    }

    if (rings.length === 0) {
        const goShop = await window.chatDialog?.confirm(
            "求婚需要一枚💍结婚戒指，你的背包里还没有。\n\n要前往商店购买吗？",
            "需要结婚戒指",
        );

        if (goShop && typeof window.openShopModal === "function") {
            window.openShopModal();
        }

        return;
    }

    const modal = document.getElementById("marriage-propose-modal");
    const alpine = window.Alpine;

    if (modal && alpine) {
        alpine.$data(modal).openWithRings(username, rings);
    }
}

/**
 * 打开婚礼设置弹窗，供新婚公告和名片入口复用。
 *
 * @param {number|string} marriageId 婚姻记录 ID
 * @returns {void}
 */
export function openWeddingSetupModal(marriageId) {
    const modal = document.getElementById("wedding-setup-modal");
    const alpine = window.Alpine;

    if (modal && alpine) {
        alpine.$data(modal).open(marriageId);
    }
}

/**
 * 创建求婚弹窗 Alpine 数据，负责戒指选择、婚礼档位和求婚提交。
 *
 * @returns {Record<string, any>}
 */
export function marriageProposeModal() {
    return {
        show: false,
        targetUsername: "",
        marriageId: null,
        rings: [],
        selectedRing: null,
        tiers: window.chatContext?.marriage?.weddingTiers || [],
        selectedTierId: window.chatContext?.marriage?.defaultWeddingTierId || "",
        loading: false,
        sending: false,
        error: "",

        get selectedTier() {
            if (!this.selectedTierId) {
                return null;
            }

            return this.tiers.find((tier) => tier.id == this.selectedTierId);
        },

        get canAfford() {
            const amount = this.selectedTier ? Number(this.selectedTier.amount) : 0;

            return window.chatContext.userJjb >= amount;
        },

        async open(username) {
            this.targetUsername = username;
            this.selectedRing = null;
            this.error = "";
            this.loading = true;
            this.show = true;

            try {
                const response = await fetch(window.chatContext.marriage.myRingsUrl, {
                    headers: {
                        Accept: "application/json",
                    },
                });
                const data = await response.json();

                if (data.status === "success") {
                    this.rings = data.rings;

                    if (this.rings.length > 0) {
                        this.selectedRing = this.rings[0].purchase_id;
                    }
                }
            } catch {
                this.rings = [];
            }

            this.loading = false;
        },

        /**
         * 使用预加载戒指列表打开弹窗，避免入口检查后重复请求背包。
         *
         * @param {string} username 求婚对象用户名
         * @param {Array<Record<string, any>>} rings 已加载的戒指列表
         * @returns {void}
         */
        openWithRings(username, rings) {
            this.targetUsername = username;
            this.error = "";
            this.loading = false;
            this.rings = rings;
            this.selectedRing = rings.length > 0 ? rings[0].purchase_id : null;
            this.show = true;
        },

        close() {
            this.show = false;
        },

        async doPropose() {
            if (this.sending || !this.selectedRing) {
                return;
            }

            this.sending = true;
            this.error = "";

            try {
                const response = await fetch(window.chatContext.marriage.proposeUrl, {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                        Accept: "application/json",
                        "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
                    },
                    body: JSON.stringify({
                        target_username: this.targetUsername,
                        ring_purchase_id: this.selectedRing,
                        wedding_tier_id: this.selectedTierId || null,
                        room_id: window.chatContext.roomId,
                    }),
                });
                const data = await response.json();

                if (data.status === "success") {
                    this.close();
                    window.chatDialog?.alert("💍 求婚成功！等待对方回应（有效期 48 小时）", "已发出", "#f43f5e");
                } else {
                    this.error = data.message || "求婚失败";
                }
            } catch {
                this.error = "网络异常，请稍后重试";
            }

            this.sending = false;
        },
    };
}

/**
 * 创建收到求婚弹窗 Alpine 数据，处理同意和拒绝求婚。
 *
 * @returns {Record<string, any>}
 */
export function marriageIncomingModal() {
    return {
        show: false,
        proposerName: "",
        marriageId: null,
        ringName: "",
        ringIcon: "💍",
        expiresAt: "",
        acting: false,

        open(detail) {
            this.proposerName = detail.proposer_name || detail.proposer?.username || "";
            this.marriageId = detail.marriage_id;
            this.ringName = detail.ring_name || "";
            this.ringIcon = detail.ring_icon || "💍";
            this.expiresAt = detail.expires_at || "";
            this.show = true;
        },

        close() {
            this.show = false;
        },

        async doAccept() {
            if (this.acting) {
                return;
            }

            this.acting = true;

            try {
                const response = await fetch(window.chatContext.marriage.acceptUrl(this.marriageId), {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                        Accept: "application/json",
                        "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
                    },
                    body: JSON.stringify({
                        room_id: window.chatContext.roomId,
                    }),
                });
                const data = await response.json();

                this.close();

                if (data.status !== "success") {
                    window.chatDialog?.alert(data.message || "操作失败", "提示", "#cc4444");
                }
            } catch {
                window.chatDialog?.alert("网络异常", "错误", "#cc4444");
            }

            this.acting = false;
        },

        async doReject() {
            if (this.acting) {
                return;
            }

            this.acting = true;

            try {
                const response = await fetch(window.chatContext.marriage.rejectUrl(this.marriageId), {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                        Accept: "application/json",
                        "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
                    },
                    body: JSON.stringify({
                        room_id: window.chatContext.roomId,
                    }),
                });
                const data = await response.json();

                this.close();

                if (data.status !== "success") {
                    window.chatDialog?.alert(data.message || "操作失败", "提示", "#cc4444");
                } else {
                    window.chatDialog?.alert("已婉拒对方的求婚", "操作完成", "#6b7280");
                }
            } catch {
                window.chatDialog?.alert("网络异常", "错误", "#cc4444");
            }

            this.acting = false;
        },
    };
}

/**
 * 创建结婚成功公告弹窗 Alpine 数据，并触发婚礼礼花特效。
 *
 * @returns {Record<string, any>}
 */
export function marriageAcceptedModal() {
    return {
        show: false,
        announcement: "",
        subText: "",
        marriageId: null,
        isNewlywed: false,

        open(detail) {
            this.marriageId = detail.marriage_id;
            const groomName = detail.user?.username ?? detail.groom_name ?? "??";
            const brideName = detail.partner?.username ?? detail.bride_name ?? "??";

            this.announcement = `${groomName} 与 ${brideName} 喜结连理！`;
            this.subText = detail.message || "愿百年好合，白头偕老！";

            // 只有新婚双方本人可以继续打开婚礼设置弹窗。
            const currentUsername = window.chatContext.username;
            this.isNewlywed = groomName === currentUsername || brideName === currentUsername;
            this.show = true;

            window.EffectManager?.play("wedding-fireworks");
        },

        close() {
            this.show = false;
        },

        openWeddingSetup() {
            window.openWeddingSetupModal?.(this.marriageId);
        },
    };
}

/**
 * 创建离婚公告弹窗 Alpine 数据，并播放雷雨组合特效。
 *
 * @returns {Record<string, any>}
 */
export function marriageDivorcedModal() {
    return {
        show: false,
        announcement: "",
        subText: "",

        open(detail) {
            const userName = detail.user_username ?? detail.user?.username ?? "??";
            const partnerName = detail.partner_username ?? detail.partner?.username ?? "??";

            this.announcement = `${userName} 与 ${partnerName} 已解除婚姻关系`;
            this.subText = detail.message || "往昔已矣，各自珍重。";
            this.show = true;

            window.EffectManager?.play("lightning");

            // 雷电结束前后再叠加雨效，保留原本的离婚公告氛围。
            setTimeout(() => {
                window.EffectManager?.play("rain");
            }, 3500);
        },

        close() {
            this.show = false;
        },
    };
}

/**
 * 创建发起离婚确认弹窗 Alpine 数据，展示协议/强制离婚的惩罚结果。
 *
 * @returns {Record<string, any>}
 */
export function divorceConfirmModal() {
    return {
        show: false,
        marriageId: null,
        mutualPenalty: 0,
        forcedPenalty: 0,
        mutualCooldown: 0,
        forcedCooldown: 0,
        acting: false,
        error: "",

        open(marriageId, config) {
            this.marriageId = marriageId;
            this.mutualPenalty = config.mutual_charm_penalty ?? 0;
            this.forcedPenalty = config.forced_charm_penalty ?? 0;
            this.mutualCooldown = config.mutual_cooldown_days ?? 0;
            this.forcedCooldown = config.forced_cooldown_days ?? 0;
            this.acting = false;
            this.error = "";
            this.show = true;
        },

        close() {
            this.show = false;
        },

        async doConfirm() {
            if (this.acting) {
                return;
            }

            this.acting = true;
            this.error = "";

            try {
                const response = await fetch(window.chatContext.marriage.divorceUrl(this.marriageId), {
                    method: "POST",
                    headers: {
                        Accept: "application/json",
                        "Content-Type": "application/json",
                        "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
                    },
                });
                const data = await response.json();

                this.close();

                if (data.ok) {
                    window.chatDialog?.alert(data.message, "申请已发出 📩", "#6b7280");
                } else {
                    window.chatDialog?.alert(data.message || "操作失败", "错误", "#dc2626");
                }
            } catch {
                this.error = "网络请求失败，请重试。";
            } finally {
                this.acting = false;
            }
        },
    };
}

/**
 * 创建离婚申请通知弹窗 Alpine 数据，处理同意或拒绝离婚请求。
 *
 * @returns {Record<string, any>}
 */
export function divorceRequestModal() {
    return {
        show: false,
        marriageId: null,
        initiatorName: "",
        mutualPenalty: 0,
        forcedPenalty: 0,
        acting: false,
        error: "",

        open(detail) {
            this.marriageId = detail.marriage_id;
            this.initiatorName = detail.initiator_name ?? detail.divorcer_username ?? "对方";
            this.mutualPenalty = detail.mutual_charm_penalty ?? 0;
            this.forcedPenalty = detail.forced_charm_penalty ?? 0;
            this.acting = false;
            this.error = "";
            this.show = true;
        },

        close() {
            this.show = false;
        },

        async doAgree() {
            if (this.acting) {
                return;
            }

            this.acting = true;
            this.error = "";

            try {
                const response = await fetch(window.chatContext.marriage.confirmDivorceUrl(this.marriageId), {
                    method: "POST",
                    headers: {
                        Accept: "application/json",
                        "Content-Type": "application/json",
                        "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
                    },
                    body: JSON.stringify({
                        room_id: window.chatContext.roomId,
                    }),
                });
                const data = await response.json();

                this.close();
                window.chatDialog?.alert(data.message, data.ok ? "操作完成" : "失败", data.ok ? "#6b7280" : "#cc4444");
            } catch {
                this.error = "网络请求失败，请重试。";
            } finally {
                this.acting = false;
            }
        },

        async doReject() {
            if (this.acting) {
                return;
            }

            this.acting = true;
            this.error = "";

            try {
                const response = await fetch(window.chatContext.marriage.rejectDivorceUrl(this.marriageId), {
                    method: "POST",
                    headers: {
                        Accept: "application/json",
                        "Content-Type": "application/json",
                        "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
                    },
                    body: JSON.stringify({
                        room_id: window.chatContext.roomId,
                    }),
                });
                const data = await response.json();

                this.close();
                window.chatDialog?.alert(data.message, data.ok ? "已处理" : "失败", data.ok ? "#d97706" : "#cc4444");
            } catch {
                this.error = "网络请求失败，请重试。";
            } finally {
                this.acting = false;
            }
        },
    };
}

/**
 * 创建婚礼设置弹窗 Alpine 数据，负责选择婚礼档位并提交举办请求。
 *
 * @returns {Record<string, any>}
 */
export function weddingSetupModal() {
    return {
        show: false,
        marriageId: null,
        tiers: [],
        selectedTier: null,
        payBy: "groom",
        loading: false,
        sending: false,
        error: "",

        get myCost() {
            if (!this.selectedTier) {
                return 0;
            }

            return this.payBy === "split" ? Math.ceil(this.selectedTier.amount / 2) : this.selectedTier.amount;
        },

        async open(marriageId) {
            this.marriageId = marriageId;
            this.selectedTier = null;
            this.payBy = "groom";
            this.error = "";
            this.loading = true;
            this.show = true;

            try {
                const response = await fetch(window.chatContext.marriage.weddingTiersUrl, {
                    headers: {
                        Accept: "application/json",
                    },
                });
                const data = await response.json();

                if (data.status === "success") {
                    this.tiers = data.tiers;

                    if (this.tiers.length > 0) {
                        this.selectedTier = this.tiers[0];
                    }
                }
            } catch {
                this.tiers = [];
            }

            this.loading = false;
        },

        close() {
            this.show = false;
        },

        async doSetup() {
            if (this.sending || !this.selectedTier) {
                return;
            }

            this.error = "";
            this.sending = true;

            try {
                // 当前产品只支持立即举办，前端固定 ceremony_type，避免保留无效时间选择状态。
                const body = {
                    tier_id: this.selectedTier.id,
                    payer_type: this.payBy,
                    ceremony_type: "immediate",
                    room_id: window.chatContext.roomId,
                };
                const response = await fetch(window.chatContext.marriage.weddingSetupUrl(this.marriageId), {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                        Accept: "application/json",
                        "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
                    },
                    body: JSON.stringify(body),
                });
                const data = await response.json();

                if (data.status === "success") {
                    this.close();
                    window.chatDialog?.alert("🎊 婚礼已开始！红包正在分发给在线用户…", "设置成功", "#f59e0b");
                } else {
                    this.error = data.message || "设置失败";
                }
            } catch {
                this.error = "网络异常，请稍后重试";
            }

            this.sending = false;
        },
    };
}

/**
 * 创建婚礼红包弹窗 Alpine 数据，负责展示和领取婚礼红包。
 *
 * @returns {Record<string, any>}
 */
export function weddingEnvelopeModal() {
    return {
        show: false,
        marriageId: null,
        ceremonyId: null,
        title: "",
        subTitle: "",
        claimed: false,
        claiming: false,
        claimedAmount: 0,

        open(detail) {
            this.marriageId = detail.marriage_id;
            this.ceremonyId = detail.ceremony_id;
            const groomName = detail.groom_name ?? detail.user?.username ?? "??";
            const brideName = detail.bride_name ?? detail.partner?.username ?? "??";

            this.title = `${groomName} × ${brideName} 婚礼红包`;
            this.subTitle = detail.tier_name ? `【${detail.tier_name}】普天同庆` : "婚礼庆典红包";
            this.claimed = false;
            this.claimedAmount = 0;
            this.show = true;
        },

        close() {
            this.show = false;
        },

        async doClaim() {
            if (this.claiming || this.claimed) {
                return;
            }

            this.claiming = true;

            try {
                const response = await fetch(`/wedding/ceremony/${this.ceremonyId}/claim`, {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                        Accept: "application/json",
                        "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]").content,
                    },
                    body: JSON.stringify({
                        ceremony_id: this.ceremonyId,
                    }),
                });
                const data = await response.json();

                if (data.ok) {
                    this.claimed = true;
                    this.claimedAmount = data.amount || 0;
                } else {
                    window.chatDialog?.alert(data.message || "领取失败", "提示", "#f59e0b");

                    // 已领取或已过期时同步锁定按钮，避免用户重复提交同一个红包。
                    if (data.message?.includes("已领取") || data.message?.includes("已过期")) {
                        this.claimed = true;
                    }
                }
            } catch {
                window.chatDialog?.alert("网络异常", "错误", "#cc4444");
            }

            this.claiming = false;
        },
    };
}

/**
 * 读取 Alpine 组件数据，避免直接访问 Alpine 私有字段。
 *
 * @param {string} modalId 弹窗节点 ID
 * @returns {Record<string, any>|null}
 */
function getAlpineModalData(modalId) {
    const modal = document.getElementById(modalId);
    const alpine = window.Alpine;

    if (!modal || !alpine) {
        return null;
    }

    return alpine.$data(modal);
}

/**
 * 构建婚礼红包领取按钮 HTML，按钮通过 ceremonyId 读取全局缓存。
 *
 * @param {number|string} ceremonyId 婚礼场次 ID
 * @returns {string}
 */
function buildWeddingClaimButton(ceremonyId) {
    return `<button data-wedding-envelope-claim="${Number(ceremonyId)}"
        style="display:inline-block; margin-left:10px; padding:4px 14px; border-radius:20px;
               background:#d97706; color:#fff;
               border:none; font-size:12px; font-weight:bold; cursor:pointer;
               vertical-align:middle; line-height:1.8; box-shadow:0 2px 8px rgba(0,0,0,.3);"
        title="点击领取婚礼红包">🧧 点击领取红包</button>`;
}

/**
 * 将红包详情写入全局缓存，供领取按钮和状态面板复用。
 *
 * @param {number|string} ceremonyId 婚礼场次 ID
 * @param {Record<string, any>} detail 红包详情
 * @returns {void}
 */
function cacheWeddingEnvelope(ceremonyId, detail) {
    if (!window._weddingEnvelopes) {
        window._weddingEnvelopes = {};
    }

    window._weddingEnvelopes[ceremonyId] = detail;
}

/**
 * 绑定婚姻系统广播事件，处理弹窗、公告和红包到账提示。
 *
 * @returns {void}
 */
function bindMarriageModalEvents() {
    if (window.__marriageModalEventsBound) {
        return;
    }

    window.__marriageModalEventsBound = true;

    window.addEventListener("chat:marriage-accepted", (event) => {
        const detail = event.detail;
        const groomName = detail.user?.username ?? detail.groom_name ?? "??";
        const brideName = detail.partner?.username ?? detail.bride_name ?? "??";

        if (typeof window.appendSystemMessage === "function") {
            window.appendSystemMessage(`💑 ${groomName} 与 ${brideName} 喜结连理！`);
        }

        getAlpineModalData("marriage-accepted-modal")?.open(detail);
    });

    window.addEventListener("chat:marriage-proposed", (event) => {
        getAlpineModalData("marriage-incoming-modal")?.open(event.detail);
    });

    window.addEventListener("chat:wedding-celebration", (event) => {
        const detail = event.detail;
        const groomName = detail.user?.username ?? "??";
        const brideName = detail.partner?.username ?? "??";
        const tierIcon = detail.tier_icon ?? "🎊";
        const tierName = detail.tier_name ?? "婚礼";
        const amount = detail.total_amount ? Number(detail.total_amount).toLocaleString() : "?";
        const ceremonyId = detail.ceremony_id;

        cacheWeddingEnvelope(ceremonyId, detail);

        if (typeof window.appendSystemMessage === "function") {
            window.appendSystemMessage(
                `${tierIcon} ${groomName} 与 ${brideName} 举办了【${tierName}】！总金额 💰${amount} 金币，快来抢红包！${buildWeddingClaimButton(ceremonyId)}`,
            );
        }

        getAlpineModalData("wedding-envelope-modal")?.open(detail);
    });

    window.addEventListener("chat:marriage-rejected", (event) => {
        const { partner_name: partnerName } = event.detail;
        window.chatDialog?.alert(`${partnerName} 婉拒了你的求婚，戒指随之遗失… 💔`, "求婚被拒绝", "#6b7280");
    });

    window.addEventListener("chat:marriage-expired", () => {
        window.chatDialog?.alert("你的求婚超时未获回应，戒指已消失… ⏰", "求婚已过期", "#9ca3af");
    });

    window.addEventListener("chat:divorce-requested", (event) => {
        getAlpineModalData("divorce-request-modal")?.open(event.detail);
    });

    window.addEventListener("chat:envelope-claimed", (event) => {
        const { amount } = event.detail;
        window.chatDialog?.alert(`+${amount.toLocaleString()} 金币已到账 🎉`, "红包到手！", "#f59e0b");
    });

    window.addEventListener("chat:marriage-divorced", (event) => {
        const detail = event.detail;
        const userName = detail.user_username ?? detail.user?.username ?? "??";
        const partnerName = detail.partner_username ?? detail.partner?.username ?? "??";

        if (typeof window.appendSystemMessage === "function") {
            window.appendSystemMessage(`💔 ${userName} 与 ${partnerName} 解除了婚姻关系。`);
        }

        getAlpineModalData("marriage-divorced-modal")?.open(detail);
    });
}

/**
 * 页面恢复时查询未领取婚礼红包，并补回公屏领取入口。
 *
 * @returns {void}
 */
function restorePendingWeddingEnvelopes() {
    const deferBootstrap = window.deferChatGameBootstrap || ((callback, delay = 0) => setTimeout(callback, delay));

    deferBootstrap(async () => {
        try {
            const response = await fetch("/wedding/pending-envelopes", {
                headers: {
                    Accept: "application/json",
                },
            });
            const data = await response.json();

            if (!response.ok || !data.envelopes?.length) {
                return;
            }

            data.envelopes.forEach((envelope) => {
                const ceremonyId = envelope.ceremony_id;

                cacheWeddingEnvelope(ceremonyId, {
                    ceremony_id: ceremonyId,
                    total_amount: envelope.total_amount,
                    tier_name: envelope.tier_name,
                    tier_icon: envelope.tier_icon,
                    user: {
                        username: envelope.groom,
                    },
                    partner: {
                        username: envelope.bride,
                    },
                });

                if (typeof window.appendSystemMessage === "function") {
                    window.appendSystemMessage(
                        `⚠️ 您有来自 ${envelope.tier_icon} ${envelope.groom} 与 ${envelope.bride}【${envelope.tier_name}】的婚礼红包未领取！${buildWeddingClaimButton(ceremonyId)}`,
                    );
                }
            });
        } catch (error) {
            console.warn("[婚礼红包] 恢复待领取按钮失败", error);
        }
    }, 3000);
}

/**
 * 页面就绪后初始化婚姻私人频道和待领取红包恢复。
 *
 * @returns {void}
 */
function bindMarriageModalBootstrap() {
    document.addEventListener("DOMContentLoaded", () => {
        const userId = window.chatContext?.userId;

        if (userId && typeof window.initMarriagePrivateChannel === "function") {
            // Echo 初始化可能晚于 DOM 就绪，保留短延迟避免私人频道注册失败。
            setTimeout(() => window.initMarriagePrivateChannel(userId), 1500);
        }

        restorePendingWeddingEnvelopes();
    });
}

/**
 * 暴露婚姻弹窗存量入口，兼容 Blade 内 onclick、Alpine 方法和广播回调。
 *
 * @returns {void}
 */
export function bindMarriageModalControls() {
    window.appendSystemMessage = appendSystemMessage;
    window.divorceConfirmModal = divorceConfirmModal;
    window.divorceRequestModal = divorceRequestModal;
    window.marriageAcceptedModal = marriageAcceptedModal;
    window.marriageDivorcedModal = marriageDivorcedModal;
    window.marriageIncomingModal = marriageIncomingModal;
    window.marriageProposeModal = marriageProposeModal;
    window.openProposeModal = openProposeModal;
    window.openWeddingSetupModal = openWeddingSetupModal;
    window.weddingEnvelopeModal = weddingEnvelopeModal;
    window.weddingSetupModal = weddingSetupModal;

    bindMarriageModalEvents();
    bindMarriageModalBootstrap();
}
