// 聊天室老虎机游戏前端组件，提供 slotPanel/slotFab Alpine 入口。

const SLOT_FAB_STORAGE_KEY = "slot_fab_pos";
const SLOT_EMOJIS = ["🍒", "🍋", "🍊", "🍇", "🔔", "💎", "💀", "7️⃣"];

/**
 * 读取 CSRF Token。
 *
 * @returns {string}
 */
function csrf() {
    return document.querySelector("meta[name=csrf-token]")?.content || "";
}

/**
 * 随机取一个老虎机图案。
 *
 * @returns {string}
 */
function randomSlotEmoji() {
    return SLOT_EMOJIS[Math.floor(Math.random() * SLOT_EMOJIS.length)];
}

/**
 * 读取悬浮按钮保存位置。
 *
 * @returns {{x:number,y:number}|null}
 */
function readSavedFabPosition() {
    try {
        return JSON.parse(localStorage.getItem(SLOT_FAB_STORAGE_KEY) || "null");
    } catch (error) {
        return null;
    }
}

/**
 * 创建老虎机悬浮入口 Alpine 组件。
 *
 * @returns {object}
 */
export function slotFab() {
    const saved = readSavedFabPosition();

    return {
        visible: false,
        posX: saved?.x ?? 18,
        posY: saved?.y ?? 150,
        dragging: false,
        _startX: 0,
        _startY: 0,
        _origX: 0,
        _origY: 0,
        _moved: false,

        /**
         * 初始化时检测老虎机是否开启。
         *
         * @returns {Promise<void>}
         */
        async init() {
            try {
                const response = await fetch("/slot/info");
                const data = await response.json();
                this.visible = data.enabled === true;
            } catch (error) {
                this.visible = false;
            }
        },

        /**
         * 开始拖动悬浮入口。
         *
         * @param {PointerEvent} event
         * @returns {void}
         */
        startDrag(event) {
            this.dragging = true;
            this._moved = false;
            this._startX = event.clientX;
            this._startY = event.clientY;
            this._origX = this.posX;
            this._origY = this.posY;
            event.currentTarget.setPointerCapture?.(event.pointerId);
        },

        /**
         * 拖动悬浮入口。
         *
         * @param {PointerEvent} event
         * @returns {void}
         */
        onDrag(event) {
            if (!this.dragging) {
                return;
            }

            const dx = event.clientX - this._startX;
            const dy = event.clientY - this._startY;
            if (Math.abs(dx) > 3 || Math.abs(dy) > 3) {
                this._moved = true;
            }

            this.posX = Math.max(4, Math.min(window.innerWidth - 60, this._origX - dx));
            this.posY = Math.max(4, Math.min(window.innerHeight - 60, this._origY + dy));
        },

        /**
         * 结束拖动；未移动时直接打开老虎机面板。
         *
         * @returns {void}
         */
        endDrag() {
            if (!this.dragging) {
                return;
            }

            this.dragging = false;
            localStorage.setItem(SLOT_FAB_STORAGE_KEY, JSON.stringify({
                x: this.posX,
                y: this.posY,
            }));

            if (!this._moved) {
                this.openPanel();
            }
        },

        /**
         * 打开老虎机面板。
         *
         * @returns {void}
         */
        openPanel() {
            const panel = document.getElementById("slot-panel");
            if (panel && window.Alpine) {
                window.Alpine.$data(panel)?.open?.();
            }
        },
    };
}

/**
 * 创建老虎机主面板 Alpine 组件。
 *
 * @returns {object}
 */
export function slotPanel() {
    return {
        show: false,
        costPerSpin: 100,
        dailyLimit: 0,
        remaining: null,
        balance: 0,
        spinning: false,
        reel1Stopped: false,
        reel2Stopped: false,
        reel3Stopped: false,
        spinEmojis: ["🎰", "🎰", "🎰"],
        resultEmojis: ["❓", "❓", "❓"],
        resultType: "",
        resultLabel: "",
        netChange: 0,
        history: [],
        _spinInterval: null,

        /**
         * Alpine 初始化，监听 show 变化自动加载配置和历史。
         *
         * @returns {void}
         */
        init() {
            this.$watch("show", async (value) => {
                if (value) {
                    await this.loadInfo();
                    await this.loadHistory();
                }
            });
        },

        /**
         * 打开面板并加载数据。
         *
         * @returns {Promise<void>}
         */
        async open() {
            this.show = true;
            await this.loadInfo();
            await this.loadHistory();
        },

        /**
         * 加载游戏配置和用户余额。
         *
         * @returns {Promise<void>}
         */
        async loadInfo() {
            try {
                const response = await fetch("/slot/info");
                const data = await response.json();
                if (!data.enabled) {
                    this.show = false;
                    return;
                }

                this.costPerSpin = data.cost_per_spin;
                this.dailyLimit = data.daily_limit;
                this.remaining = data.remaining;
                this.balance = window.__chatUser?.jjb ?? 0;
            } catch (error) {
                // 配置加载失败时保持面板当前状态，避免影响其他游戏入口。
            }
        },

        /**
         * 加载最近转动记录。
         *
         * @returns {Promise<void>}
         */
        async loadHistory() {
            try {
                const response = await fetch("/slot/history");
                const data = await response.json();
                this.history = data.history || [];
            } catch (error) {
                this.history = [];
            }
        },

        /**
         * 执行一次老虎机转动。
         *
         * @returns {Promise<void>}
         */
        async doSpin() {
            if (this.spinning || (this.dailyLimit > 0 && this.remaining <= 0)) {
                return;
            }

            this.spinning = true;
            this.resultType = "";
            this.resultLabel = "";
            this.netChange = 0;
            this.reel1Stopped = false;
            this.reel2Stopped = false;
            this.reel3Stopped = false;

            // 本地先随机滚动，服务端返回结果后再逐列停下。
            this._spinInterval = window.setInterval(() => {
                this.spinEmojis = [randomSlotEmoji(), randomSlotEmoji(), randomSlotEmoji()];
            }, 80);

            let data;
            try {
                const response = await fetch("/slot/spin", {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                        "Accept": "application/json",
                        "X-CSRF-TOKEN": csrf(),
                    },
                });
                data = await response.json();
            } catch (error) {
                window.clearInterval(this._spinInterval);
                this.spinning = false;
                window.chatDialog?.alert?.("网络异常，请稍后重试", "错误", "#ef4444");
                return;
            }

            if (!data.ok) {
                window.clearInterval(this._spinInterval);
                this.spinning = false;
                window.chatDialog?.alert?.(data.message || "转动失败", "提示", "#ef4444");
                return;
            }

            const stopReel = (reelIndex, emoji, delay) => new Promise((resolve) => {
                window.setTimeout(() => {
                    window.clearInterval(this._spinInterval);
                    this[`reel${reelIndex + 1}Stopped`] = true;
                    this.spinEmojis = [...this.spinEmojis];
                    this.spinEmojis[reelIndex] = emoji;
                    resolve();
                }, delay);
            });

            await stopReel(0, data.emojis[0], 600);
            this._spinInterval = window.setInterval(() => {
                this.spinEmojis = [data.emojis[0], randomSlotEmoji(), randomSlotEmoji()];
            }, 80);

            await stopReel(1, data.emojis[1], 500);
            this._spinInterval = window.setInterval(() => {
                this.spinEmojis = [data.emojis[0], data.emojis[1], randomSlotEmoji()];
            }, 80);

            await stopReel(2, data.emojis[2], 400);
            window.clearInterval(this._spinInterval);

            this.resultEmojis = data.emojis;
            this.resultType = data.result_type;
            this.resultLabel = data.result_label;
            this.netChange = data.payout > 0
                ? data.payout - this.costPerSpin
                : -this.costPerSpin + (data.payout < 0 ? data.payout : 0);
            this.balance = data.balance;
            this.spinning = false;

            // 转动成功后同步聊天室全局余额，避免其他面板继续显示旧金币数。
            if (window.__chatUser) {
                window.__chatUser.jjb = data.balance;
            }

            if (this.dailyLimit > 0 && this.remaining !== null) {
                this.remaining = Math.max(0, this.remaining - 1);
            }

            await this.loadHistory();
        },

        /**
         * 关闭面板并清理滚动动画。
         *
         * @returns {void}
         */
        close() {
            window.clearInterval(this._spinInterval);
            this.spinning = false;
            this.show = false;
        },
    };
}

/**
 * 绑定老虎机全局 Alpine 工厂函数。
 *
 * @returns {void}
 */
export function bindSlotMachineControls() {
    if (typeof window === "undefined") {
        return;
    }

    window.slotFab = slotFab;
    window.slotPanel = slotPanel;
}
