// 商店弹窗业务模块，负责商品加载、购买、赠礼、改名卡和商店按钮事件。

import { escapeHtml } from "./html.js";

const DEFAULT_SHOP_ITEMS_URL = "/shop/items";
const DEFAULT_SHOP_BUY_URL = "/shop/buy";
const DEFAULT_SHOP_RENAME_URL = "/shop/rename";

const WEEK_EFFECT_ICONS = {
    fireworks: "🎆",
    rain: "🌧",
    lightning: "⚡",
    snow: "❄️",
    sakura: "🌸",
    meteors: "🌠",
    "gold-rain": "🪙",
    hearts: "💖",
    confetti: "🎊",
    fireflies: "✨",
};

const SHOP_GROUPS = [
    {
        label: "⚡ 单次特效卡",
        desc: "立即播放一次",
        type: "instant",
    },
    {
        label: "📅 周卡  7天登录自动播放",
        desc: "同时只能激活一种，购新旧失效不退款",
        type: "duration",
    },
    {
        label: "💍 求婚戒指",
        desc: "存入背包，求婚时消耗（被拒则遗失）",
        type: "ring",
    },
    {
        label: "🎣 自动钓鱼卡",
        desc: "激活后自动收篼，无需手动点击浮漂",
        type: "auto_fishing",
    },
    {
        label: "🎭 道具",
        desc: "",
        type: "tools",
    },
];

const DECORATION_GROUPS = [
    {
        label: "💬 消息气泡",
        desc: "同类型只保留最新购买",
        type: "msg_bubble",
    },
    {
        label: "🎨 昵称颜色",
        desc: "同类型只保留最新购买",
        type: "msg_name_color",
    },
    {
        label: "🌈 文字颜色",
        desc: "同类型只保留最新购买",
        type: "msg_text_color",
    },
    {
        label: "🖼️ 头像框",
        desc: "同类型只保留最新购买",
        type: "avatar_frame",
    },
];

const DECORATION_TYPE_TO_SLOT = {
    msg_bubble: "bubble",
    msg_name_color: "name_color",
    msg_text_color: "text_color",
    avatar_frame: "avatar_frame",
};

let shopControlEventsBound = false;
let shopLoaded = false;
let giftItem = null;
let activeDecorations = {};

/**
 * 读取商店根节点上由 Blade 注入的接口地址。
 *
 * @returns {{items: string, buy: string, rename: string}}
 */
function getShopUrls() {
    const modal = document.getElementById("shop-modal");

    return {
        items: modal?.dataset.shopItemsUrl || DEFAULT_SHOP_ITEMS_URL,
        buy: modal?.dataset.shopBuyUrl || DEFAULT_SHOP_BUY_URL,
        rename: modal?.dataset.shopRenameUrl || DEFAULT_SHOP_RENAME_URL,
    };
}

/**
 * 读取 CSRF Token，给 fetch 请求统一使用。
 *
 * @returns {string}
 */
function csrfToken() {
    return document.querySelector('meta[name="csrf-token"]')?.content ?? "";
}

/**
 * 生成 fetch 请求头。
 *
 * @param {boolean} withJson 是否声明 JSON 请求体
 * @returns {Record<string, string>}
 */
function jsonHeaders(withJson = false) {
    const headers = {
        Accept: "application/json",
        "X-CSRF-TOKEN": csrfToken(),
    };

    if (withJson) {
        headers["Content-Type"] = "application/json";
    }

    return headers;
}

/**
 * 打开商店弹窗，首次打开时拉取商品列表。
 *
 * @returns {void}
 */
export function openShopModal() {
    const modal = document.getElementById("shop-modal");
    if (!modal) {
        return;
    }

    modal.style.display = "flex";
    bindShopTabs();
    if (!shopLoaded) {
        shopLoaded = true;
        fetchShopData();
    }
}

/**
 * 关闭商店弹窗。
 *
 * @returns {void}
 */
export function closeShopModal() {
    const modal = document.getElementById("shop-modal");
    if (modal) {
        modal.style.display = "none";
    }
    shopLoaded = false;
}

/**
 * 绑定商店 Tab 切换逻辑。
 *
 * @returns {void}
 */
function bindShopTabs() {
    const tabsContainer = document.getElementById("shop-tabs");
    if (!tabsContainer || tabsContainer.dataset.shopTabsBound) {
        return;
    }
    tabsContainer.dataset.shopTabsBound = "1";

    tabsContainer.addEventListener("click", (event) => {
        const tab = event.target.closest("[data-shop-tab]");
        if (!tab) {
            return;
        }

        const tabName = tab.dataset.shopTab;
        const itemsList = document.getElementById("shop-items-list");
        const decorationsList = document.getElementById("shop-decorations-list");

        // 切换当前 Tab 的选中状态。
        tabsContainer.querySelectorAll(".shop-tab").forEach((btn) => {
            btn.classList.toggle("active", btn.dataset.shopTab === tabName);
        });

        // 切换对应商品列表，装扮列表需要显式恢复 grid 布局。
        if (tabName === "items") {
            if (itemsList) itemsList.style.display = "";
            if (decorationsList) decorationsList.style.display = "none";
        } else {
            if (itemsList) itemsList.style.display = "none";
            // 装扮列表在 CSS 中为 display:none，需显式设置为 grid 才能覆盖
            if (decorationsList) decorationsList.style.display = "grid";
        }
    });
}

/**
 * 拉取商品数据并渲染列表。
 *
 * @returns {Promise<void>}
 */
export async function fetchShopData() {
    try {
        const response = await fetch(getShopUrls().items, {
            headers: jsonHeaders(),
        });
        const data = await response.json();
        renderShop(data);
        renderDecorations(data);
    } catch (error) {
        showShopToast("⚠ 加载失败，请重试", false);
    }
}

/**
 * 兼容旧入口，给未迁移脚本按原函数名刷新商店。
 *
 * @returns {Promise<void>}
 */
export function loadShop() {
    return fetchShopData();
}

/**
 * 构建分组标题旁边的状态徽章。
 *
 * @param {Record<string, any>} group 商品分组
 * @param {Record<string, any>} data 商店接口数据
 * @returns {string}
 */
function buildGroupSuffix(group, data) {
    if (group.type === "auto_fishing" && Number(data.auto_fishing_minutes_left || 0) > 0) {
        const left = Number(data.auto_fishing_minutes_left || 0);
        const leftStr = left >= 60 ? `${Math.floor(left / 60)} 小时` : `${left} 分钟`;

        return ` <span style="display:inline-block;margin-left:8px;padding:1px 8px;background:#7c3aed;color:#fff;border-radius:10px;font-size:10px;font-weight:bold;vertical-align:middle;">⏳ 剩余 ${escapeHtml(leftStr)}</span>`;
    }

    if (group.type === "duration" && data.active_week_effect) {
        const effectKey = String(data.active_week_effect);
        const effectItem = (data.items || []).find((item) => item.type === "duration" && String(item.slug || "").includes(effectKey));
        const effectName = effectItem ? effectItem.name : effectKey;

        return ` <span style="display:inline-block;margin-left:8px;padding:1px 8px;background:#16a34a;color:#fff;border-radius:10px;font-size:10px;font-weight:bold;vertical-align:middle;">✅ 已激活：${escapeHtml(effectName)}</span>`;
    }

    if (group.type === "tools" && Number(data.sign_repair_card_count || 0) > 0) {
        return ` <span style="display:inline-block;margin-left:8px;padding:1px 8px;background:#0f766e;color:#fff;border-radius:10px;font-size:10px;font-weight:bold;vertical-align:middle;">🎫 可用 ${Number(data.sign_repair_card_count || 0)} 张</span>`;
    }

    return "";
}

/**
 * 按商品类型筛选当前分组要展示的商品。
 *
 * @param {Record<string, any>} group 商品分组
 * @param {Array<Record<string, any>>} items 商品列表
 * @returns {Array<Record<string, any>>}
 */
function filterGroupItems(group, items) {
    if (group.type === "tools") {
        return items.filter((item) => ["one_time", "sign_repair"].includes(item.type));
    }

    return items.filter((item) => item.type === group.type);
}

/**
 * 渲染商店商品列表和余额状态。
 *
 * @param {Record<string, any>} data 商店接口数据
 * @returns {void}
 */
export function renderShop(data) {
    const balance = document.getElementById("shop-jjb");
    const badge = document.getElementById("shop-week-badge");
    const list = document.getElementById("shop-items-list");

    if (!list) {
        return;
    }

    if (balance) {
        balance.textContent = Number(data.user_jjb || 0).toLocaleString();
    }

    if (badge) {
        if (data.active_week_effect) {
            badge.textContent = `${WEEK_EFFECT_ICONS[data.active_week_effect] ?? ""} 周卡生效中`;
            badge.style.display = "inline-block";
        } else {
            badge.textContent = "";
            badge.style.display = "none";
        }
    }

    const items = Array.isArray(data.items) ? data.items : [];
    const ringCounts = data.ring_counts || {};
    list.innerHTML = "";

    SHOP_GROUPS.forEach((group) => {
        const groupItems = filterGroupItems(group, items);
        if (!groupItems.length) {
            return;
        }

        const header = document.createElement("div");
        header.className = "shop-group-header";
        header.innerHTML = `${escapeHtml(group.label)}${buildGroupSuffix(group, { ...data, items })}${group.desc ? ` <span>${escapeHtml(group.desc)}</span>` : ""}`;
        list.appendChild(header);

        groupItems.forEach((item) => {
            list.appendChild(createShopCard(item, data, ringCounts));
        });
    });
}

/**
 * 渲染个人装扮商品列表。
 *
 * @param {Record<string, any>} data 商店接口数据
 * @returns {void}
 */
export function renderDecorations(data) {
    const list = document.getElementById("shop-decorations-list");
    if (!list) {
        return;
    }

    // 记录当前激活装扮，渲染时只给当前款式显示"已激活"。
    activeDecorations = data.active_decorations || {};

    const items = Array.isArray(data.items) ? data.items : [];
    list.innerHTML = "";

    // 购买说明明确同类型替换规则，避免用户误以为可以叠加多款气泡或头像框。
    const note = document.createElement("div");
    note.className = "decoration-note";
    note.innerHTML = "📌 购买说明：每个类型只生效一个，购买同类型新装扮后，旧装扮自动作废且不退款。";
    list.appendChild(note);

    DECORATION_GROUPS.forEach((group) => {
        const groupItems = items.filter((item) => item.type === group.type);
        if (!groupItems.length) {
            return;
        }

        // 分组标题（独占一整行），描述文字内嵌到标题中避免单独占一格
        const header = document.createElement("div");
        header.className = "shop-group-header";
        header.innerHTML = `${escapeHtml(group.label)}${group.desc ? ` <span>${escapeHtml(group.desc)}</span>` : ''}`;
        list.appendChild(header);

        groupItems.forEach((item) => {
            const card = document.createElement("div");
            card.className = "shop-card";

            // active_decorations 由后端按槽位名索引，先把商品 type 映射到对应槽位。
            const slot = DECORATION_TYPE_TO_SLOT[item.type] || null;
            const activeDeco = slot ? (activeDecorations[slot] || null) : null;
            const isActiveStyle = activeDeco && activeDeco.style === item.slug;
            const expiresAt = activeDeco ? activeDeco.expires_at : null;
            let daysLeft = "";
            if (isActiveStyle && expiresAt) {
                const remaining = Math.max(0, Math.ceil((new Date(expiresAt).getTime() - Date.now()) / (1000 * 60 * 60 * 24)));
                daysLeft = remaining > 0 ? `剩余 ${remaining} 天` : "即将过期";
            }

            const button = document.createElement("button");
            if (isActiveStyle) {
                button.className = "shop-btn";
                button.textContent = "续费 💰 " + Number(item.price || 0).toLocaleString();
            } else {
                button.className = "shop-btn";
                button.textContent = "购买 💰 " + Number(item.price || 0).toLocaleString();
            }
            button.addEventListener("click", () => confirmAndBuyItem(item));

            // 仅当前已激活的款式显示状态标签，同槽位其他款式保持普通购买状态。
            const statusHtml = isActiveStyle
                ? `<span class="decoration-status active">已激活${daysLeft ? ' · ' + daysLeft : ''}</span>`
                : "";

            const validityHtml = buildValidityHtml(item);

            card.innerHTML = `
                <div class="shop-card-top">
                    <span class="shop-card-icon">${escapeHtml(item.icon)}</span>
                    <span class="shop-card-name">${escapeHtml(item.name)}</span>
                </div>
                ${statusHtml ? `<div class="decoration-status-line">${statusHtml}</div>` : ""}
                <div class="shop-card-desc">${escapeHtml(item.description ?? "")}</div>
                ${validityHtml}
                ${isActiveStyle && expiresAt ? `<div class="decoration-expiry">⏳ 到期：${escapeHtml(expiresAt.replace('T', ' ').slice(0, 16))}</div>` : ""}
            `;
            card.appendChild(button);
            list.appendChild(card);
        });
    });
}

/**
 * 创建单个商品卡片，并挂载购买或使用按钮事件。
 *
 * @param {Record<string, any>} item 商品数据
 * @param {Record<string, any>} data 商店接口数据
 * @param {Record<string, number>} ringCounts 戒指持有数量
 * @returns {HTMLDivElement}
 */
function createShopCard(item, data, ringCounts) {
    const isRename = item.slug === "rename_card";
    const canUseRename = isRename && data.has_rename_card;
    const isRing = item.type === "ring";
    const ownedQty = isRing ? Number(ringCounts[item.id] || 0) : 0;
    const isAutoFishing = item.type === "auto_fishing";
    const card = document.createElement("div");
    const button = document.createElement("button");

    card.className = "shop-card";
    card.innerHTML = buildShopCardHtml(item, {
        isRing,
        ownedQty,
        isAutoFishing,
    });

    if (canUseRename) {
        button.className = "shop-btn shop-btn-use";
        button.textContent = "✦ 使用改名卡";
        button.addEventListener("click", openRenameModal);
    } else if (item.type === "instant") {
        button.className = "shop-btn";
        button.textContent = `💰 ${Number(item.price || 0).toLocaleString()}`;
        button.addEventListener("click", () => openGiftDialog(item));
    } else {
        button.className = "shop-btn";
        button.textContent = `💰 ${Number(item.price || 0).toLocaleString()}`;
        button.addEventListener("click", () => confirmAndBuyItem(item));
    }

    card.appendChild(button);

    return card;
}

/**
 * 拼接商品卡片 HTML，所有接口字段都先转义再进入 innerHTML。
 *
 * @param {Record<string, any>} item 商品数据
 * @param {{isRing: boolean, ownedQty: number, isAutoFishing: boolean}} options 渲染选项
 * @returns {string}
 */
function buildShopCardHtml(item, options) {
    const iconHtml = options.isRing && options.ownedQty > 0
        ? `<span style="position:relative;display:inline-block;">
            <span class="shop-card-icon">${escapeHtml(item.icon)}</span>
            <span style="position:absolute;top:-4px;right:-6px;background:#f43f5e;color:#fff;font-size:9px;font-weight:800;min-width:15px;height:15px;border-radius:8px;text-align:center;line-height:15px;padding:0 2px;">${options.ownedQty}</span>
        </span>`
        : `<span class="shop-card-icon">${escapeHtml(item.icon)}</span>`;
    const validityHtml = buildValidityHtml(item);
    const ringBonus = options.isRing && (Number(item.intimacy_bonus || 0) > 0 || Number(item.charm_bonus || 0) > 0)
        ? `<div style="font-size:9px;margin-top:3px;display:flex;gap:8px;">
            ${Number(item.intimacy_bonus || 0) > 0 ? `<span style="color:#f43f5e;">💞 亲密 +${Number(item.intimacy_bonus || 0)}</span>` : ""}
            ${Number(item.charm_bonus || 0) > 0 ? `<span style="color:#a855f7;">✨ 魅力 +${Number(item.charm_bonus || 0)}</span>` : ""}
        </div>`
        : "";

    return `
        <div class="shop-card-top">
            ${iconHtml}
            <span class="shop-card-name">${escapeHtml(item.name)}</span>
        </div>
        <div class="shop-card-desc">${escapeHtml(item.description ?? "")}</div>
        ${ringBonus}
        ${validityHtml}
    `;
}

/**
 * 生成购买前展示的有效期或生效方式文案。
 *
 * @param {Record<string, any>} item 商品数据
 * @returns {string}
 */
function buildValidityText(item) {
    if (Number(item.duration_days || 0) > 0) {
        return `有效期：${Number(item.duration_days)} 天`;
    }

    if (Number(item.duration_minutes || 0) > 0) {
        return `有效期：${formatMinutes(item.duration_minutes)}`;
    }

    if (item.type === "instant") {
        return "购买后立即播放 1 次";
    }

    if (item.type === "ring") {
        return "购买后存入背包，求婚时消耗";
    }

    if (["one_time", "sign_repair"].includes(item.type)) {
        return "购买后存入背包，使用时消耗";
    }

    return "";
}

/**
 * 生成商品卡片里的有效期标签 HTML。
 *
 * @param {Record<string, any>} item 商品数据
 * @returns {string}
 */
function buildValidityHtml(item) {
    const text = buildValidityText(item);

    return text ? `<div class="shop-validity">⏱ ${escapeHtml(text)}</div>` : "";
}

/**
 * 格式化分钟数，供自动钓鱼卡有效期展示。
 *
 * @param {number|string} minutes 有效分钟数
 * @returns {string}
 */
function formatMinutes(minutes) {
    const value = Number(minutes || 0);

    return value >= 60 ? `${Math.floor(value / 60)} 小时` : `${value} 分钟`;
}

/**
 * 购买前弹出确认框，补签卡需要先询问数量。
 *
 * @param {Record<string, any>} item 商品数据
 * @returns {Promise<void>}
 */
async function confirmAndBuyItem(item) {
    let quantity = 1;

    if (item.type === "sign_repair") {
        quantity = await window.promptSignRepairQuantity?.(item);
        if (quantity === null || quantity === undefined) {
            return;
        }
    }

    const validityText = buildValidityText(item);
    const replacementText = DECORATION_TYPE_TO_SLOT[item.type]
        ? "\n购买说明：同类型只生效最新购买，原有同类型装扮会自动作废且不退款。"
        : "";
    const confirmMessage = `确认花费 💰 ${Number(Number(item.price || 0) * quantity).toLocaleString()} 金币购买\n【${item.name}】${quantity > 1 ? ` × ${quantity}` : ""}${validityText ? `\n${validityText}` : ""}${replacementText}\n\n确定购买吗？`;
    const confirmed = await confirmShopPurchase(confirmMessage);

    if (confirmed) {
        buyItem(item.id, item.name, item.price, "all", "", quantity);
    }
}

/**
 * 兼容全局弹窗组件缺失时的原生确认。
 *
 * @param {string} message 确认文案
 * @returns {Promise<boolean>}
 */
async function confirmShopPurchase(message) {
    if (window.chatDialog?.confirm) {
        return Boolean(await window.chatDialog.confirm(message, "确认购买"));
    }

    return window.confirm(message);
}

/**
 * 打开赠礼对话框，缓存当前要赠出的单次特效卡。
 *
 * @param {Record<string, any>} item 商品数据
 * @returns {void}
 */
export function openGiftDialog(item) {
    giftItem = item;

    const recipient = document.getElementById("gift-recipient");
    const message = document.getElementById("gift-message");
    const error = document.getElementById("gift-err");
    const itemName = document.getElementById("gift-item-name");
    const dialog = document.getElementById("gift-dialog");

    if (recipient) {
        recipient.value = "";
    }

    if (message) {
        message.value = "";
    }

    if (error) {
        error.textContent = "";
    }

    if (itemName) {
        const validityText = buildValidityText(item);
        itemName.textContent = `${item.icon} ${item.name}（💰 ${Number(item.price || 0).toLocaleString()}${validityText ? ` · ${validityText}` : ""}）`;
    }

    if (dialog) {
        dialog.style.display = "flex";
    }
}

/**
 * 关闭赠礼对话框并清理当前商品缓存。
 *
 * @returns {void}
 */
export function closeGiftDialog() {
    const dialog = document.getElementById("gift-dialog");
    if (dialog) {
        dialog.style.display = "none";
    }

    giftItem = null;
}

/**
 * 确认赠礼，按旧签名调用购买接口。
 *
 * @returns {void}
 */
export function confirmGift() {
    if (!giftItem) {
        return;
    }

    const recipient = document.getElementById("gift-recipient")?.value.trim() ?? "";
    const message = document.getElementById("gift-message")?.value.trim() ?? "";
    const item = giftItem;
    const error = document.getElementById("gift-err");

    if (error) {
        error.textContent = "";
    }

    closeGiftDialog();
    buyItem(item.id, item.name, item.price, recipient, message);
}

/**
 * 购买商品，保留旧全局签名供补签卡等存量脚本复用。
 *
 * @param {number|string} itemId 商品 ID
 * @param {string} name 商品名称
 * @param {number|string} price 商品价格
 * @param {string} recipient 接收人，空值表示全场
 * @param {string} message 赠言
 * @param {number} quantity 购买数量
 * @returns {Promise<void>}
 */
export async function buyItem(itemId, name, price, recipient, message, quantity = 1) {
    try {
        const response = await fetch(getShopUrls().buy, {
            method: "POST",
            headers: jsonHeaders(true),
            body: JSON.stringify({
                item_id: itemId,
                recipient: recipient || "all",
                message: message || "",
                quantity: quantity || 1,
                room_id: window.chatContext?.roomId ?? 0,
            }),
        });
        const data = await response.json();

        if (data.status === "success") {
            handleBuySuccess(data, name);
            return;
        }

        showShopToast(data.message, false);
    } catch (error) {
        showShopToast("⚠ 网络异常，请重试", false);
    }
}

/**
 * 购买成功后同步金币、播放本地特效并刷新商店状态。
 *
 * @param {Record<string, any>} data 购买接口返回
 * @param {string} itemName 商品名称
 * @returns {void}
 */
function handleBuySuccess(data, itemName) {
    const balance = document.getElementById("shop-jjb");

    if (data.jjb !== undefined && balance) {
        balance.textContent = Number(data.jjb).toLocaleString();
    }

    showShopToast(`✅ ${itemName} 购买成功！`, true);

    // 装扮购买成功后先更新本地缓存，随后再拉接口刷新完整状态。
    if (data.slot && data.style) {
        activeDecorations[data.slot] = {
            style: data.style,
            expires_at: data.expires_at,
        };
    }

    // 购买者本地也要立即看到特效，广播只负责其他在线用户。
    if (data.play_effect && window.EffectManager) {
        window.EffectManager.play(data.play_effect);
    }

    shopLoaded = false;
    setTimeout(() => {
        fetchShopData();
        shopLoaded = true;
    }, 1000);
}

/**
 * 显示商店内部 Toast。
 *
 * @param {string} message 提示内容
 * @param {boolean} ok 是否成功
 * @returns {void}
 */
export function showShopToast(message, ok) {
    const element = document.getElementById("shop-toast");
    if (!element) {
        return;
    }

    element.textContent = message;
    element.style.display = "block";
    element.style.background = ok ? "#064e3b" : "#7f1d1d";
    element.style.color = ok ? "#6ee7b7" : "#fca5a5";
    clearTimeout(element._shopToastTimer);
    element._shopToastTimer = setTimeout(() => {
        element.style.display = "none";
    }, 3500);
}

/**
 * 打开改名卡输入框。
 *
 * @returns {void}
 */
export function openRenameModal() {
    const modal = document.getElementById("shop-rename-overlay");
    const input = document.getElementById("rename-input");
    const error = document.getElementById("rename-err");

    if (modal) {
        modal.style.display = "flex";
    }

    if (input) {
        input.focus();
    }

    if (error) {
        error.textContent = "";
    }
}

/**
 * 关闭改名卡输入框。
 *
 * @returns {void}
 */
export function closeRenameModal() {
    const modal = document.getElementById("shop-rename-overlay");
    if (modal) {
        modal.style.display = "none";
    }
}

/**
 * 提交改名卡请求，成功后刷新页面同步昵称。
 *
 * @returns {Promise<void>}
 */
export async function submitRename() {
    const input = document.getElementById("rename-input");
    const error = document.getElementById("rename-err");
    const newName = input?.value.trim() ?? "";

    if (!newName) {
        if (error) {
            error.textContent = "请输入新昵称";
        }
        return;
    }

    try {
        const response = await fetch(getShopUrls().rename, {
            method: "POST",
            headers: jsonHeaders(true),
            body: JSON.stringify({
                new_name: newName,
            }),
        });
        const data = await response.json();

        if (data.status === "success") {
            closeRenameModal();
            showShopToast(data.message, true);
            shopLoaded = false;
            setTimeout(() => window.location.reload(), 2000);
            return;
        }

        if (error) {
            error.textContent = data.message;
        }
    } catch (requestError) {
        if (error) {
            error.textContent = "网络异常，请重试";
        }
    }
}

/**
 * 把模块函数挂到 window，兼容仍在 Blade 内的调用点。
 *
 * @returns {void}
 */
function exposeShopGlobals() {
    window.openShopModal = openShopModal;
    window.closeShopModal = closeShopModal;
    window.loadShop = loadShop;
    window.fetchShopData = fetchShopData;
    window.renderShop = renderShop;
    window.renderDecorations = renderDecorations;
    window.openGiftDialog = openGiftDialog;
    window.closeGiftDialog = closeGiftDialog;
    window.confirmGift = confirmGift;
    window.buyItem = buyItem;
    window.showShopToast = showShopToast;
    window.openRenameModal = openRenameModal;
    window.closeRenameModal = closeRenameModal;
    window.submitRename = submitRename;
}

/**
 * 绑定商店按钮、对话框按钮与遮罩关闭事件。
 *
 * @returns {void}
 */
export function bindShopControls() {
    if (typeof window === "undefined" || typeof document === "undefined") {
        return;
    }

    exposeShopGlobals();

    if (shopControlEventsBound) {
        return;
    }

    shopControlEventsBound = true;
    document.addEventListener("click", (event) => {
        if (!(event.target instanceof Element)) {
            return;
        }

        const modal = document.getElementById("shop-modal");

        // 点击商店遮罩或关闭按钮都走同一个关闭入口。
        if (event.target.closest("[data-shop-modal-close]") || (modal && event.target === modal)) {
            event.preventDefault();
            closeShopModal();
            return;
        }

        if (event.target.closest("[data-shop-rename-confirm]")) {
            event.preventDefault();
            submitRename();
            return;
        }

        if (event.target.closest("[data-shop-rename-cancel]")) {
            event.preventDefault();
            closeRenameModal();
            return;
        }

        if (event.target.closest("[data-shop-gift-confirm]")) {
            event.preventDefault();
            confirmGift();
            return;
        }

        if (event.target.closest("[data-shop-gift-cancel]")) {
            event.preventDefault();
            closeGiftDialog();
        }
    });
}
