// 聊天室节日福利弹窗模块，负责福利广播、系统消息按钮、领取弹窗和状态同步。

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

let holidayModalEventsBound = false;

/**
 * 返回第一个非空值。
 *
 * @param {...unknown} values
 * @returns {unknown|null}
 */
function firstHolidayDefined(...values) {
    for (const value of values) {
        if (value !== undefined && value !== null && value !== "") {
            return value;
        }
    }

    return null;
}

/**
 * 将后端字段转换为数字。
 *
 * @param {unknown} value
 * @param {number} fallback
 * @returns {number}
 */
function toHolidayNumber(value, fallback = 0) {
    if (value === undefined || value === null || value === "") {
        return fallback;
    }

    const parsedValue = Number(value);

    return Number.isFinite(parsedValue) ? parsedValue : fallback;
}

/**
 * 解析日期字符串。
 *
 * @param {unknown} value
 * @returns {Date|null}
 */
function parseHolidayDate(value) {
    if (!value) {
        return null;
    }

    const parsedDate = new Date(value);

    return Number.isNaN(parsedDate.getTime()) ? null : parsedDate;
}

/**
 * 格式化福利时间。
 *
 * @param {unknown} value
 * @returns {string}
 */
function formatHolidayDate(value) {
    const parsedDate = parseHolidayDate(value);

    if (!parsedDate) {
        return "";
    }

    return new Intl.DateTimeFormat("zh-CN", {
        month: "2-digit",
        day: "2-digit",
        hour: "2-digit",
        minute: "2-digit",
    }).format(parsedDate);
}

/**
 * 格式化剩余有效期。
 *
 * @param {Date|null} expiresAt
 * @returns {string}
 */
function formatHolidayRemaining(expiresAt) {
    if (!expiresAt) {
        return "以后端状态为准";
    }

    const remainingMilliseconds = expiresAt.getTime() - Date.now();

    if (remainingMilliseconds <= 0) {
        return "已过期";
    }

    const totalMinutes = Math.ceil(remainingMilliseconds / 60000);

    if (totalMinutes < 60) {
        return `${totalMinutes} 分钟`;
    }

    if (totalMinutes < 24 * 60) {
        const hours = Math.floor(totalMinutes / 60);
        const minutes = totalMinutes % 60;

        return minutes > 0 ? `${hours} 小时 ${minutes} 分钟` : `${hours} 小时`;
    }

    const days = Math.floor(totalMinutes / (24 * 60));
    const hours = Math.floor((totalMinutes % (24 * 60)) / 60);

    return hours > 0 ? `${days} 天 ${hours} 小时` : `${days} 天`;
}

/**
 * 生成福利轮次标签。
 *
 * @param {object} detail
 * @returns {string}
 */
function buildHolidayRoundLabel(detail) {
    const explicitLabel = firstHolidayDefined(detail.round_label, detail.batch_label, detail.run_label);

    if (explicitLabel) {
        return String(explicitLabel);
    }

    const roundNumber = toHolidayNumber(detail.round_no, 0);

    if (detail.repeat_type === "yearly") {
        return roundNumber > 0 ? `年度第 ${roundNumber} 轮福利` : "年度福利批次";
    }

    if (roundNumber > 0) {
        return `第 ${roundNumber} 轮福利`;
    }

    return detail.scheduled_for ? "本轮定时福利" : "当前福利批次";
}

/**
 * 生成弹窗描述文案。
 *
 * @param {object} detail
 * @returns {string}
 */
function buildHolidayDescription(detail) {
    if (detail.description) {
        return String(detail.description);
    }

    const amountText = detail.distribute_type === "fixed" && detail.fixed_amount !== null
        ? `每人固定 ${Number(detail.fixed_amount).toLocaleString()} 金币`
        : "随机金额发放";
    const quotaText = detail.max_claimants > 0
        ? `前 ${detail.max_claimants} 名在线用户可领取`
        : "在线用户均可领取";

    return `本轮福利已开启，${amountText}，${quotaText}。`;
}

/**
 * 兼容后端广播字段归一化入口。
 *
 * @param {object|null|undefined} detail
 * @returns {object}
 */
function normalizeHolidayPayload(detail) {
    if (typeof window.normalizeHolidayBroadcastEvent === "function") {
        return window.normalizeHolidayBroadcastEvent(detail);
    }

    return detail ?? {};
}

/**
 * 构建公屏系统消息里的领取按钮。
 *
 * @param {number|string|null} runId
 * @param {string} label
 * @returns {string}
 */
export function buildHolidayClaimActionButton(runId, label = "🎁 立即领取") {
    if (!runId) {
        return "";
    }

    return ` <button type="button"
            data-holiday-run-id="${escapeHtml(runId)}"
            style="display:inline-flex; align-items:center; gap:4px; margin-left:8px; padding:3px 10px; border:none; border-radius:999px; background:linear-gradient(135deg,#f59e0b,#d97706); color:#fff; font-size:12px; font-weight:bold; cursor:pointer; box-shadow:0 2px 6px rgba(0,0,0,.22); vertical-align:middle;"
            title="点击领取本轮节日福利">${escapeHtml(label)}</button>`;
}

/**
 * 构建公屏节日福利系统消息。
 *
 * @param {object} detail
 * @returns {string}
 */
export function buildHolidaySystemMessage(detail) {
    const quotaText = detail.max_claimants > 0
        ? `前 ${detail.max_claimants} 名在线用户可领取`
        : "在线用户均可领取";
    const amountText = detail.distribute_type === "fixed" && detail.fixed_amount !== null
        ? `每人固定 ${Number(detail.fixed_amount).toLocaleString()} 金币`
        : "随机金额发放";
    const scheduleText = detail.scheduled_for ? `发放时间 ${formatHolidayDate(detail.scheduled_for)}` : null;
    const roundText = detail.round_label ? ` ${detail.round_label}` : "";
    const runId = firstHolidayDefined(detail.run_id, detail.id);

    return [
        `🎊 【${escapeHtml(detail.name || "节日福利")}】${escapeHtml(roundText)}开始啦！`,
        `总奖池 💰${toHolidayNumber(detail.total_amount, 0).toLocaleString()} 金币`,
        escapeHtml(amountText),
        escapeHtml(quotaText),
        escapeHtml(scheduleText || ""),
    ].filter(Boolean).join("，") + buildHolidayClaimActionButton(runId);
}

/**
 * 创建节日福利 Alpine 弹窗组件。
 *
 * @returns {object}
 */
export function holidayEventModal() {
    return {
        show: false,
        loadingStatus: false,
        claiming: false,
        claimable: true,
        claimed: false,
        expiresTimer: null,
        autoCloseTimer: null,
        runId: null,
        legacyEventId: null,
        eventName: "",
        eventDesc: "",
        roundLabel: "",
        totalAmount: 0,
        maxClaimants: 0,
        distributeType: "random",
        fixedAmount: null,
        scheduledFor: null,
        scheduledForText: "",
        expiresAt: null,
        expiresIn: "",
        claimedAmount: 0,
        statusHint: "",

        /**
         * 返回领取按钮文字。
         *
         * @returns {string}
         */
        claimButtonText() {
            if (this.loadingStatus) {
                return "同步领取状态中…";
            }

            if (this.claiming) {
                return "领取中…";
            }

            if (!this.claimable) {
                return "当前不可领取";
            }

            return "🎁 立即领取福利";
        },

        /**
         * 打开弹窗并填充活动数据。
         *
         * @param {object} detail
         * @returns {void}
         */
        open(detail) {
            const holidayDetail = normalizeHolidayPayload(detail);

            this.runId = holidayDetail.run_id ?? null;
            this.legacyEventId = holidayDetail.event_id ?? null;
            this.eventName = holidayDetail.name ?? "节日福利";
            this.eventDesc = buildHolidayDescription(holidayDetail);
            this.roundLabel = buildHolidayRoundLabel(holidayDetail);
            this.totalAmount = toHolidayNumber(holidayDetail.total_amount, 0);
            this.maxClaimants = toHolidayNumber(holidayDetail.max_claimants, 0);
            this.distributeType = holidayDetail.distribute_type ?? "random";
            this.fixedAmount = firstHolidayDefined(holidayDetail.fixed_amount, null);
            this.scheduledFor = parseHolidayDate(holidayDetail.scheduled_for);
            this.scheduledForText = formatHolidayDate(holidayDetail.scheduled_for);
            this.expiresAt = parseHolidayDate(holidayDetail.expires_at);
            this.claimable = true;
            this.claimed = false;
            this.loadingStatus = false;
            this.claiming = false;
            this.claimedAmount = 0;
            this.stopAutoCloseTimer();
            this.statusHint = holidayDetail.run_id
                ? "当前奖励按本轮福利批次发放，请在有效期内领取。"
                : "兼容旧活动通道，等待主线广播升级";
            this.updateExpiresIn();
            this.startExpiresTimer();
            this.show = true;
            void this.syncStatus();
        },

        /**
         * 关闭弹窗并停止计时器。
         *
         * @returns {void}
         */
        close() {
            this.show = false;
            this.stopExpiresTimer();
            this.stopAutoCloseTimer();
        },

        /**
         * 启动有效期刷新计时器。
         *
         * @returns {void}
         */
        startExpiresTimer() {
            this.stopExpiresTimer();
            this.expiresTimer = window.setInterval(() => this.updateExpiresIn(), 30000);
        },

        /**
         * 停止有效期刷新计时器。
         *
         * @returns {void}
         */
        stopExpiresTimer() {
            if (this.expiresTimer) {
                window.clearInterval(this.expiresTimer);
                this.expiresTimer = null;
            }
        },

        /**
         * 启动领取成功后的自动关闭。
         *
         * @returns {void}
         */
        startAutoCloseTimer() {
            this.stopAutoCloseTimer();
            this.autoCloseTimer = window.setTimeout(() => this.close(), 3000);
        },

        /**
         * 停止自动关闭计时器。
         *
         * @returns {void}
         */
        stopAutoCloseTimer() {
            if (this.autoCloseTimer) {
                window.clearTimeout(this.autoCloseTimer);
                this.autoCloseTimer = null;
            }
        },

        /**
         * 更新有效期展示。
         *
         * @returns {void}
         */
        updateExpiresIn() {
            this.expiresIn = formatHolidayRemaining(this.expiresAt);
        },

        /**
         * 构建状态接口候选地址。
         *
         * @returns {string[]}
         */
        buildStatusUrls() {
            const urls = [];

            if (this.runId) {
                urls.push(`/holiday/runs/${encodeURIComponent(this.runId)}/status`);
            }

            if (this.legacyEventId) {
                urls.push(`/holiday/${encodeURIComponent(this.legacyEventId)}/status`);
            }

            return urls;
        },

        /**
         * 构建领取接口候选地址。
         *
         * @returns {string[]}
         */
        buildClaimUrls() {
            const urls = [];

            if (this.runId) {
                urls.push(`/holiday/runs/${encodeURIComponent(this.runId)}/claim`);
            }

            if (this.legacyEventId) {
                urls.push(`/holiday/${encodeURIComponent(this.legacyEventId)}/claim`);
            }

            return urls;
        },

        /**
         * 同步当前福利批次状态。
         *
         * @returns {Promise<void>}
         */
        async syncStatus() {
            const statusUrls = this.buildStatusUrls();

            if (statusUrls.length === 0) {
                this.claimable = false;
                this.statusHint = "缺少 run_id，无法查询当前福利状态。";
                return;
            }

            this.loadingStatus = true;

            try {
                for (const url of statusUrls) {
                    const response = await fetch(url, {
                        headers: {
                            Accept: "application/json",
                            "X-Requested-With": "XMLHttpRequest",
                        },
                    });

                    if (response.status === 404 || response.status === 405) {
                        continue;
                    }

                    const data = await response.json();
                    this.applyStatus(data);
                    return;
                }

                this.statusHint = "状态接口尚未切换完成，可直接尝试领取。";
            } catch (error) {
                this.statusHint = "状态同步失败，可直接尝试领取。";
            } finally {
                this.loadingStatus = false;
            }
        },

        /**
         * 应用后端返回的状态快照。
         *
         * @param {object} data
         * @returns {void}
         */
        applyStatus(data) {
            if (data.expires_at) {
                this.expiresAt = parseHolidayDate(data.expires_at);
                this.updateExpiresIn();
            }

            const statusValue = firstHolidayDefined(data.status, data.claim_status);
            const alreadyClaimed = Boolean(data.claimed ?? data.has_claimed ?? false) || ["claimed", "received", "paid"].includes(statusValue);
            const amount = toHolidayNumber(firstHolidayDefined(data.claimed_amount, data.amount), 0);

            if (alreadyClaimed) {
                this.claimed = true;
                this.claimable = false;
                this.claimedAmount = amount;
                this.statusHint = data.message ?? "本轮福利已领取。";
                return;
            }

            if (data.claimable === false || data.can_claim === false) {
                this.claimable = false;
                this.statusHint = data.message ?? "当前不在可领取名单或领取窗口已关闭。";
                return;
            }

            this.claimable = true;
            this.statusHint = data.message ?? this.statusHint;
        },

        /**
         * 发起领取请求。
         *
         * @returns {Promise<void>}
         */
        async doClaim() {
            if (this.claiming || this.claimed || !this.claimable) {
                return;
            }

            const claimUrls = this.buildClaimUrls();

            if (claimUrls.length === 0) {
                window.chatDialog?.alert?.("缺少福利批次标识，暂时无法领取。", "提示", "#f59e0b");
                return;
            }

            this.claiming = true;

            try {
                for (const url of claimUrls) {
                    const response = await fetch(url, {
                        method: "POST",
                        headers: {
                            "Content-Type": "application/json",
                            "Accept": "application/json",
                            "X-CSRF-TOKEN": document.querySelector("meta[name=csrf-token]")?.content || "",
                        },
                    });

                    if (response.status === 404 || response.status === 405) {
                        continue;
                    }

                    const data = await response.json();
                    const claimedAmount = toHolidayNumber(firstHolidayDefined(data.claimed_amount, data.amount), 0);
                    const alreadyClaimed = Boolean(data.claimed ?? data.has_claimed ?? false) || data.message?.includes("已领取");

                    if (data.ok || alreadyClaimed) {
                        this.claimed = true;
                        this.claimable = false;
                        this.claimedAmount = claimedAmount;
                        this.statusHint = `${data.message ?? "本轮福利已入账。"} 3 秒后自动关闭。`;
                        this.appendClaimMessage(claimedAmount);
                        this.startAutoCloseTimer();

                        if (window.__chatUser && data.balance !== undefined) {
                            window.__chatUser.jjb = data.balance;
                        }

                        return;
                    }

                    this.statusHint = data.message ?? "领取失败，请稍后重试。";
                    window.chatDialog?.alert?.(this.statusHint, "提示", "#f59e0b");

                    if (data.message?.includes("已结束") || data.message?.includes("过期")) {
                        this.claimable = false;
                        this.close();
                    } else {
                        void this.syncStatus();
                    }

                    return;
                }

                window.chatDialog?.alert?.("领取接口尚未切换完成，请稍后再试。", "提示", "#f59e0b");
            } catch (error) {
                window.chatDialog?.alert?.("网络异常，请稍后重试。", "错误", "#cc4444");
            } finally {
                this.claiming = false;
            }
        },

        /**
         * 向公屏追加领取成功消息。
         *
         * @param {number} claimedAmount
         * @returns {void}
         */
        appendClaimMessage(claimedAmount) {
            if (typeof window.appendSystemMessage !== "function") {
                return;
            }

            const username = escapeHtml(window.chatContext?.username ?? "当前用户");
            const eventName = escapeHtml(this.eventName);
            const roundText = this.roundLabel ? `【${escapeHtml(this.roundLabel)}】` : "";
            window.appendSystemMessage(
                `🌟 <b>${username}</b> 领取了【${eventName}】${roundText}，获得 <b>${claimedAmount.toLocaleString()}</b> 金币！${buildHolidayClaimActionButton(this.runId)}`,
            );
        },
    };
}

/**
 * 从公屏系统消息中打开已缓存的节日福利批次。
 *
 * @param {string|number} runId 福利批次 ID
 * @returns {void}
 */
export function openHolidayRunFromSystemMessage(runId) {
    const normalizedRunId = String(runId || "");
    const detail = window.__holidayRuns?.[normalizedRunId];
    const modal = document.getElementById("holiday-event-modal");

    if (!normalizedRunId || !modal || typeof window.Alpine?.$data !== "function") {
        return;
    }

    if (!detail) {
        window.chatDialog?.alert?.("当前福利批次信息未缓存，请等待下一轮广播或刷新页面后重试。", "提示", "#f59e0b");
        return;
    }

    window.Alpine.$data(modal)?.open?.(detail);
}

/**
 * 处理节日福利广播事件。
 *
 * @param {CustomEvent} event
 * @returns {void}
 */
function handleHolidayStarted(event) {
    const detail = normalizeHolidayPayload(event.detail);

    if (detail.run_id !== undefined && detail.run_id !== null) {
        window.__holidayRuns[String(detail.run_id)] = detail;
    }

    if (typeof window.appendSystemMessage === "function") {
        window.appendSystemMessage(buildHolidaySystemMessage({
            ...detail,
            round_label: buildHolidayRoundLabel(detail),
        }));
    }

    const modal = document.getElementById("holiday-event-modal");
    if (modal && typeof window.Alpine?.$data === "function") {
        window.Alpine.$data(modal)?.open?.(detail);
    }
}

/**
 * 绑定节日福利弹窗全局入口、系统消息按钮和广播事件。
 *
 * @returns {void}
 */
export function bindHolidayModalControls() {
    if (typeof window === "undefined") {
        return;
    }

    window.__holidayRuns = window.__holidayRuns || {};
    window.holidayEventModal = holidayEventModal;
    window.buildHolidayClaimActionButton = buildHolidayClaimActionButton;
    window.buildHolidaySystemMessage = buildHolidaySystemMessage;
    window.openHolidayRunFromSystemMessage = openHolidayRunFromSystemMessage;

    if (holidayModalEventsBound || typeof document === "undefined") {
        return;
    }

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

        const claimButton = event.target.closest("[data-holiday-run-id]");
        if (!claimButton) {
            return;
        }

        event.preventDefault();
        openHolidayRunFromSystemMessage(claimButton.getAttribute("data-holiday-run-id") || "");
    });
    window.addEventListener("chat:holiday.started", handleHolidayStarted);
}
