// 乐彩百家乐主面板 Alpine 组件，负责当前局状态、下注、开奖结果和历史趋势。

const DEFAULT_BACCARAT_CURRENT_URL = "/baccarat/current";
const DEFAULT_BACCARAT_BET_URL = "/baccarat/bet";
const DEFAULT_BACCARAT_HISTORY_URL = "/baccarat/history";
const DEFAULT_BACCARAT_MIN_BET = 100;
const DEFAULT_BACCARAT_MAX_BET = 50000;
const DEFAULT_BACCARAT_TOTAL_SECONDS = 60;
const RESULT_LABELS = {
    big: "大",
    small: "小",
    triple: "豹子",
};

/**
 * 读取百家乐接口地址，优先使用 Blade 写入的命名路由。
 *
 * @returns {{current: string, bet: string, history: string}}
 */
function baccaratUrls() {
    const panel = document.getElementById("baccarat-panel");

    return {
        current: panel?.dataset.baccaratCurrentUrl || DEFAULT_BACCARAT_CURRENT_URL,
        bet: panel?.dataset.baccaratBetUrl || DEFAULT_BACCARAT_BET_URL,
        history: panel?.dataset.baccaratHistoryUrl || DEFAULT_BACCARAT_HISTORY_URL,
    };
}

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

/**
 * 生成快捷下注金额，保持最小值、最大值和中间档位可快速选择。
 *
 * @param {number} min 最小下注额
 * @param {number} max 最大下注额
 * @returns {number[]}
 */
function buildQuickBetAmounts(min, max) {
    const candidates = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000];
    const steps = candidates
        .map((multiplier) => min * multiplier)
        .filter((value) => value >= min && value < max);
    let sortedSteps = [...new Set([...steps, max])].sort((a, b) => a - b);

    if (sortedSteps.length >= 5) {
        return [
            sortedSteps[0],
            sortedSteps[Math.floor((sortedSteps.length - 1) * 0.25)],
            sortedSteps[Math.floor((sortedSteps.length - 1) * 0.5)],
            sortedSteps[Math.floor((sortedSteps.length - 1) * 0.75)],
            sortedSteps[sortedSteps.length - 1],
        ];
    }

    // 下注范围很小时补齐中间档位，避免模板渲染时按钮数量跳变。
    while (sortedSteps.length < 5) {
        let maxGap = 0;
        let insertIndex = -1;

        for (let index = 0; index < sortedSteps.length - 1; index += 1) {
            if (sortedSteps[index + 1] - sortedSteps[index] > maxGap) {
                maxGap = sortedSteps[index + 1] - sortedSteps[index];
                insertIndex = index;
            }
        }

        if (insertIndex === -1) {
            break;
        }

        let newValue = Math.floor((sortedSteps[insertIndex] + sortedSteps[insertIndex + 1]) / 2);
        if (newValue > 100) {
            newValue = Math.floor(newValue / 10) * 10;
        }
        sortedSteps.splice(insertIndex + 1, 0, newValue);
    }

    return sortedSteps;
}

/**
 * 创建百家乐游戏面板 Alpine 组件。
 *
 * @returns {Record<string, any>}
 */
export function baccaratPanel() {
    return {
        show: false,
        phase: "idle",
        roundId: null,
        totalSeconds: DEFAULT_BACCARAT_TOTAL_SECONDS,
        countdown: DEFAULT_BACCARAT_TOTAL_SECONDS,
        countdownTimer: null,
        totalBetBig: 0,
        totalBetSmall: 0,
        totalBetTriple: 0,
        betCountBig: 0,
        betCountSmall: 0,
        betCountTriple: 0,
        myBet: false,
        myBetType: "",
        myBetAmount: 0,
        selectedType: "",
        betAmount: DEFAULT_BACCARAT_MIN_BET,
        minBet: DEFAULT_BACCARAT_MIN_BET,
        maxBet: DEFAULT_BACCARAT_MAX_BET,
        submitting: false,
        settledDice: [],
        settledTotal: 0,
        settledResult: "",
        resultLabel: "",
        diceEmoji: "",
        myWon: false,
        myPayout: 0,
        history: [],
        autoCloseTimer: null,
        autoCloseCountdown: 0,

        /**
         * 同步全局聊天上下文中的金币余额，供弹窗右上角与其他面板共用。
         *
         * @param {number|string|null|undefined} jjb 最新金币余额
         * @returns {void}
         */
        syncUserGold(jjb) {
            if (jjb === undefined || jjb === null || !window.chatContext) {
                return;
            }

            window.chatContext.userJjb = Number(jjb);
            window.chatContext.myGold = Number(jjb);
        },

        /**
         * 获取快捷下注金额数组。
         *
         * @returns {number[]}
         */
        get quickBetAmounts() {
            return buildQuickBetAmounts(this.minBet || DEFAULT_BACCARAT_MIN_BET, this.maxBet || DEFAULT_BACCARAT_MAX_BET);
        },

        /**
         * 从大厅或通知点击打开。
         *
         * @returns {void}
         */
        openFromHall() {
            this.show = true;
            this.loadCurrentRound();
        },

        /**
         * 重置为未开局状态。
         *
         * @returns {void}
         */
        setIdleState() {
            clearInterval(this.countdownTimer);
            clearInterval(this.autoCloseTimer);
            this.countdownTimer = null;
            this.autoCloseTimer = null;
            this.phase = "idle";
            this.roundId = null;
            this.countdown = 0;
            this.autoCloseCountdown = 0;
            this.totalBetBig = 0;
            this.totalBetSmall = 0;
            this.totalBetTriple = 0;
            this.betCountBig = 0;
            this.betCountSmall = 0;
            this.betCountTriple = 0;
            this.myBet = false;
            this.myBetType = "";
            this.myBetAmount = 0;
            this.selectedType = "";
            this.settledDice = [];
            this.settledTotal = 0;
            this.settledResult = "";
            this.resultLabel = "";
            this.diceEmoji = "";
            this.myWon = false;
            this.myPayout = 0;
            this.updateFab(false);
        },

        /**
         * 开局：填充局次数据并开始倒计时。
         *
         * @param {Record<string, any>} data 广播局次数据
         * @returns {void}
         */
        openRound(data) {
            this.phase = "betting";
            this.roundId = data.round_id;
            this.countdown = data.bet_seconds || DEFAULT_BACCARAT_TOTAL_SECONDS;
            this.totalSeconds = this.countdown;
            this.myBet = false;
            this.myBetType = "";
            this.myBetAmount = 0;
            this.settledDice = [];
            this.selectedType = "";
            this.betAmount = this.minBet || DEFAULT_BACCARAT_MIN_BET;
            this.betCountBig = 0;
            this.betCountSmall = 0;
            this.betCountTriple = 0;
            this.show = true;

            this.loadCurrentRound();
            this.startCountdown();
            this.updateFab(true);
        },

        /**
         * 从接口获取当前局状态，包括我的下注和投注池。
         *
         * @returns {Promise<void>}
         */
        async loadCurrentRound() {
            try {
                const response = await fetch(baccaratUrls().current);
                const data = await response.json();
                this.syncUserGold(data.jjb);

                if (data.round && (data.round.seconds_left || 0) > 0) {
                    this.phase = "betting";
                    this.roundId = data.round.id;
                    this.countdown = data.round.seconds_left || this.countdown || 0;
                    this.totalBetBig = data.round.total_bet_big;
                    this.totalBetSmall = data.round.total_bet_small;
                    this.totalBetTriple = data.round.total_bet_triple;
                    this.betCountBig = data.round.bet_count_big;
                    this.betCountSmall = data.round.bet_count_small;
                    this.betCountTriple = data.round.bet_count_triple;
                    this.minBet = data.round.min_bet || DEFAULT_BACCARAT_MIN_BET;
                    this.maxBet = data.round.max_bet || DEFAULT_BACCARAT_MAX_BET;

                    if (data.round.my_bet) {
                        this.myBet = true;
                        this.myBetType = data.round.my_bet.bet_type;
                        this.myBetAmount = data.round.my_bet.amount;
                    } else {
                        this.myBet = false;
                        this.myBetType = "";
                        this.myBetAmount = 0;
                    }
                    return;
                }

                this.setIdleState();
            } catch (error) {
                this.setIdleState();
            }
        },

        /**
         * 启动下注倒计时。
         *
         * @returns {void}
         */
        startCountdown() {
            clearInterval(this.countdownTimer);
            this.countdownTimer = setInterval(() => {
                this.countdown -= 1;
                if (this.countdown <= 0) {
                    clearInterval(this.countdownTimer);
                    this.countdownTimer = null;
                    this.phase = "waiting";
                }
            }, 1000);
        },

        /**
         * 提交本局下注。
         *
         * @returns {Promise<void>}
         */
        async submitBet() {
            if (!this.roundId || !this.selectedType || this.betAmount < DEFAULT_BACCARAT_MIN_BET || this.submitting) {
                return;
            }

            this.submitting = true;

            try {
                const response = await fetch(baccaratUrls().bet, {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json",
                        Accept: "application/json",
                        "X-CSRF-TOKEN": csrfToken(),
                    },
                    body: JSON.stringify({
                        round_id: this.roundId,
                        bet_type: this.selectedType,
                        amount: this.betAmount,
                    }),
                });
                const data = await response.json();

                if (response.ok && data.ok) {
                    this.myBet = true;
                    this.myBetType = data.bet_type;
                    this.myBetAmount = data.amount;
                    return;
                }

                if (response.status === 422 && data.errors) {
                    const firstError = Object.values(data.errors)[0][0];
                    window.chatDialog?.alert(firstError, "下注验证失败", "#ef4444");
                    return;
                }

                window.chatDialog?.alert(data.message || "下注失败", "提示", "#ef4444");
            } catch (error) {
                window.chatDialog?.alert("网络异常，请稍后重试。", "错误", "#ef4444");
            } finally {
                this.submitting = false;
            }
        },

        /**
         * 显示开奖结果动画，并按本人是否下注决定是否弹出结算面板。
         *
         * @param {Record<string, any>} data 开奖广播数据
         * @returns {void}
         */
        showResult(data) {
            clearInterval(this.countdownTimer);
            this.countdownTimer = null;
            this.settledDice = data.dice;
            this.settledTotal = data.total_points;
            this.settledResult = data.result;
            this.resultLabel = data.result_label;
            this.phase = "settled";

            if (this.myBet) {
                this.show = true;
            }

            if (this.myBet && this.myBetType === data.result && data.result !== "kill") {
                this.myWon = true;
                this.myPayout = this.myBetAmount * (data.result === "triple" ? 25 : 2);
            } else {
                this.myWon = false;
                this.myPayout = 0;
            }

            this.updateFab(false);
            this.loadHistory();
            this.startAutoCloseCountdown();
        },

        /**
         * 加载历史趋势。
         *
         * @returns {Promise<void>}
         */
        async loadHistory() {
            try {
                const response = await fetch(baccaratUrls().history);
                const data = await response.json();
                this.history = (data.history || []).reverse();
            } catch (error) {
                // 历史趋势失败不阻塞下注主流程。
            }
        },

        /**
         * 更新悬浮按钮显示状态。
         *
         * @param {boolean} visible 是否显示
         * @returns {void}
         */
        updateFab(visible) {
            const fab = document.getElementById("baccarat-fab");

            if (fab && typeof window.Alpine?.$data === "function") {
                window.Alpine.$data(fab).visible = visible;
            }
        },

        /**
         * 关闭面板；下注中保留悬浮按钮方便再次打开。
         *
         * @returns {void}
         */
        close() {
            clearInterval(this.autoCloseTimer);
            this.autoCloseTimer = null;
            this.autoCloseCountdown = 0;
            this.show = false;

            if (this.phase === "betting") {
                this.updateFab(true);
            }
        },

        /**
         * 押注类型中文标签。
         *
         * @param {string} type 押注类型
         * @returns {string}
         */
        betTypeLabel(type) {
            return RESULT_LABELS[type] || "";
        },

        /**
         * 启动结算后的自动关闭倒计时。
         *
         * @returns {void}
         */
        startAutoCloseCountdown() {
            this.autoCloseCountdown = 10;
            clearInterval(this.autoCloseTimer);
            this.autoCloseTimer = setInterval(() => {
                this.autoCloseCountdown -= 1;
                if (this.autoCloseCountdown <= 0) {
                    clearInterval(this.autoCloseTimer);
                    this.autoCloseTimer = null;
                    this.close();
                }
            }, 1000);
        },
    };
}

/**
 * 挂载百家乐主面板全局组件名，兼容 Blade 的 x-data。
 *
 * @returns {void}
 */
export function bindBaccaratPanelControls() {
    if (typeof window === "undefined") {
        return;
    }

    window.baccaratPanel = baccaratPanel;
}
