// 用户名片弹窗 Alpine 组件，负责资料查看、好友、礼物、管理和职务快捷操作。

/**
 * 读取用户弹窗容器上的礼物初始数据。
 *
 * @returns {{gifts: Array<Record<string, any>>, defaultGiftId: number}}
 */
function userCardGiftDefaults() {
    const container = document.getElementById("user-modal-container");
    let gifts = [];

    try {
        gifts = JSON.parse(atob(container?.dataset.giftsBase64 || ""));
    } catch (error) {
        gifts = [];
    }

    return {
        gifts,
        defaultGiftId: Number(container?.dataset.defaultGiftId || 0),
    };
}

/**
 * 创建用户名片弹窗 Alpine 组件。
 *
 * @returns {Record<string, any>}
 */
export function userCardComponent() {
    const giftDefaults = userCardGiftDefaults();

        return {
            showUserModal: false,
            showOriginalLightbox: false,
            userInfo: {
                position_history: []
            },
            isMuting: false,
            muteDuration: 5,
            showWhispers: false,
            whisperList: [],
            showAnnounce: false,
            announceText: '',
            is_friend: false, // 当前用户是否已将对方加为好友
            friendLoading: false, // 好友操作加载状态
            gifts: giftDefaults.gifts,
            selectedGiftId: giftDefaults.defaultGiftId,
            giftCount: 1,
            sendingGift: false,
            showGiftPanel: false,
            showGiftGoldPanel: false,
            giftGoldAmount: "",
            giftGoldSending: false,

            // 职务奖励金币
            rewardAmount: 0,
            sendingReward: false,
            showRewardPanel: false,

            // 任命相关
            showAppointPanel: false,
            appointPositions: [],
            selectedPositionId: null,
            appointRemark: '',
            appointLoading: false,

            // 折叠状态
            showAdminView: false, // 管理员视野
            showPositionHistory: false, // 职务履历
            showAdminPanel: false, // 管理操作（管理操作+职务操作合并）

            // 婚姻状态
            targetMarriage: null, // 对方婚姻状态 { status, partner_name, marriage_id }
            marriageLoading: false,
            mySex: window.chatContext?.userSex ?? '', // 当前用户性别（用于求婚异性判断）

            // 自定义弹窗：直接代理到全局 window.chatDialog
            $alert: (...args) => window.chatDialog.alert(...args),
            $confirm: (...args) => window.chatDialog.confirm(...args),
            $prompt: (...args) => window.chatDialog.prompt(...args),

            /**
             * 判断当前操作者是否拥有指定的职务权限码。
             */
            hasPositionPermission(permissionCode) {
                return Boolean(window.chatContext?.positionPermissionMap?.[permissionCode]);
            },

            /**
             * 判断目标用户职务是否严格低于当前操作者。
             *
             * 规则：
             * 1. 先比较部门位阶 rank
             * 2. 部门相同再比较职务位阶 rank
             * 3. 对方没有在职职务时，视为可处理
             * 4. id=1 站长始终可处理
             */
            canManageTargetByDuty() {
                if (window.chatContext?.isSiteOwner) {
                    return true;
                }

                const targetDepartmentRank = Number(this.userInfo.department_rank || 0);
                const targetPositionRank = Number(this.userInfo.position_rank || 0);

                if (targetDepartmentRank <= 0 && targetPositionRank <= 0) {
                    return true;
                }

                const operatorDepartmentRank = Number(window.chatContext?.operatorDepartmentRank || 0);
                const operatorPositionRank = Number(window.chatContext?.operatorPositionRank || 0);

                if (operatorDepartmentRank > targetDepartmentRank) {
                    return true;
                }

                if (operatorDepartmentRank < targetDepartmentRank) {
                    return false;
                }

                return operatorPositionRank >= targetPositionRank;
            },

            /** 返回名片资产字段的中文名称。 */
            assetValueLabel(asset) {
                return {
                    exp_num: "经验",
                    jjb: "金币",
                    meili: "魅力",
                }[asset] || "资产";
            },

            /** 判断名片资产字段是否处于可付费查看的隐藏状态。 */
            canRevealAssetValue(asset) {
                return Boolean(
                    this.userInfo.asset_numbers_can_reveal
                    && this.userInfo.asset_numbers_masked
                    && this.userInfo[asset] === "******"
                    && this.userInfo.asset_reveal_user_id
                );
            },

            /** 格式化名片里的经验、金币、魅力显示。 */
            displayAssetValue(asset) {
                if (this.canRevealAssetValue(asset)) {
                    return "****** 👁️";
                }

                return Number(this.userInfo[asset] || 0).toLocaleString();
            },

            /** 返回名片资产字段的悬停提示。 */
            assetValueTitle(asset) {
                if (this.canRevealAssetValue(asset)) {
                    const cost = Number(this.userInfo.asset_numbers_reveal_cost || 1000).toLocaleString();

                    return `点击查看${this.assetValueLabel(asset)}，需扣除 ${cost} 金币`;
                }

                return this.assetValueLabel(asset);
            },

            /** 返回名片资产字段的点击态样式。 */
            assetValueStyle(asset, color) {
                const clickable = this.canRevealAssetValue(asset);

                return [
                    "font-weight: 700",
                    `color: ${color}`,
                    "font-size: 14px",
                    clickable ? "cursor: pointer" : "cursor: default",
                    "text-decoration: none",
                ].join("; ");
            },

            /** 付费查看当前名片里的经验、金币或魅力。 */
            async revealAssetValue(asset) {
                if (!this.canRevealAssetValue(asset)) {
                    return;
                }

                const cost = Number(this.userInfo.asset_numbers_reveal_cost || 1000);
                const label = this.assetValueLabel(asset);
                const confirmed = await this.$confirm(
                    `查看 TA 的${label}需扣除 ${cost.toLocaleString()} 金币，是否继续？`,
                    "信息查看付费",
                    "#d97706",
                    "扣费查看",
                    "取消"
                );

                if (!confirmed) {
                    return;
                }

                try {
                    const response = await fetch("/user/reveal-info", {
                        method: "POST",
                        headers: this._headers(),
                        body: JSON.stringify({
                            user_id: this.userInfo.asset_reveal_user_id,
                            asset,
                        }),
                    });
                    const data = await response.json();

                    if (data.status !== "success") {
                        this.$alert(data.message || "查看失败，请稍后重试。", "查看失败", "#cc4444");
                        return;
                    }

                    // 只解锁当前点击的资产字段，其他隐藏字段仍保持星号并可单独付费查看。
                    this.userInfo[asset] = data.value;

                    if (window.chatContext && data.jjb !== undefined) {
                        window.chatContext.myGold = data.jjb;
                    }

                    this.$alert(data.message || `${label}已显示。`, "查看成功", "#16a34a");
                } catch (e) {
                    this.$alert("网络异常，请稍后重试。", "查看失败", "#cc4444");
                }
            },

            /** 格式化名片里的银行存款显示。 */
            displayBankBalance() {
                if (this.userInfo.bank_jjb_can_reveal && this.userInfo.bank_jjb_masked) {
                    return "****** 👁️";
                }

                return Number(this.userInfo.bank_jjb || 0).toLocaleString();
            },

            /** 返回银行存款字段的悬停提示。 */
            bankBalanceTitle() {
                if (this.userInfo.bank_jjb_can_reveal && this.userInfo.bank_jjb_masked) {
                    const cost = Number(this.userInfo.bank_jjb_reveal_cost || 1000).toLocaleString();

                    return `点击查看存款，需扣除 ${cost} 金币`;
                }

                return "银行存款";
            },

            /** 返回银行存款字段的点击态样式。 */
            bankBalanceStyle() {
                const clickable = this.userInfo.bank_jjb_can_reveal && this.userInfo.bank_jjb_masked;

                return [
                    "font-weight: 700",
                    "color: #059669",
                    "font-size: 14px",
                    clickable ? "cursor: pointer" : "cursor: default",
                    "text-decoration: none",
                ].join("; ");
            },

            /** 付费查看当前名片用户的银行存款。 */
            async revealBankBalance() {
                if (!this.userInfo.bank_jjb_can_reveal || !this.userInfo.bank_jjb_masked || !this.userInfo.bank_reveal_user_id) {
                    return;
                }

                const cost = Number(this.userInfo.bank_jjb_reveal_cost || 1000);
                const confirmed = await this.$confirm(
                    `查看 TA 的银行存款需扣除 ${cost.toLocaleString()} 金币，是否继续？`,
                    "信息查看付费",
                    "#d97706",
                    "扣费查看",
                    "取消"
                );

                if (!confirmed) {
                    return;
                }

                try {
                    const response = await fetch("/user/reveal-info", {
                        method: "POST",
                        headers: this._headers(),
                        body: JSON.stringify({
                            user_id: this.userInfo.bank_reveal_user_id,
                            asset: "bank_jjb",
                        }),
                    });
                    const data = await response.json();

                    if (data.status !== "success") {
                        this.$alert(data.message || "查看失败，请稍后重试。", "查看失败", "#cc4444");
                        return;
                    }

                    // 仅解锁当前名片这一处显示，重新打开名片时仍以后端返回的遮罩状态为准。
                    this.userInfo.bank_jjb = data.value;
                    this.userInfo.bank_jjb_masked = false;
                    this.userInfo.bank_jjb_can_reveal = false;

                    if (window.chatContext && data.jjb !== undefined) {
                        window.chatContext.myGold = data.jjb;
                    }

                    this.$alert(data.message || "存款金额已显示。", "查看成功", "#16a34a");
                } catch (e) {
                    this.$alert("网络异常，请稍后重试。", "查看失败", "#cc4444");
                }
            },

            /** 切换好友关系（加好友 / 删好友） */
            async toggleFriend() {
                if (this.friendLoading) return;
                this.friendLoading = true;
                const username = this.userInfo.username;
                const roomId = window.chatContext.roomId;
                const removing = this.is_friend;

                try {
                    let res;
                    if (removing) {
                        // 删除好友
                        res = await fetch(`/friend/${encodeURIComponent(username)}/remove`, {
                            method: 'DELETE',
                            headers: this._headers(),
                            body: JSON.stringify({
                                room_id: roomId
                            }),
                        });
                    } else {
                        // 添加好友
                        res = await fetch(`/friend/${encodeURIComponent(username)}/add`, {
                            method: 'POST',
                            headers: this._headers(),
                            body: JSON.stringify({
                                room_id: roomId
                            }),
                        });
                    }
                    const data = await res.json();
                    const ok = data.status === 'success';
                    this.$alert(
                        data.message,
                        ok ? (removing ? '已删除好友' : '添加成功 🎉') : '操作失败',
                        ok ? (removing ? '#6b7280' : '#16a34a') : '#cc4444'
                    );
                    if (ok) {
                        this.is_friend = !this.is_friend;
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
                this.friendLoading = false;
            },

            async handleConfirmDivorce(marriageId) {
                // 等待后端接口实现，当前先略
                return;
            },

            /** 发起协议离婚（先拉惩罚配置，再弹专属全屏确认弹窗） */
            async doDivorce(marriageId) {
                if (!marriageId) return;
                this.showUserModal = false;

                // 从后台实时拉取最新惩罚配置
                let divorceConfig = {
                    mutual_charm_penalty: 0,
                    forced_charm_penalty: 0,
                    mutual_cooldown_days: 0,
                    forced_cooldown_days: 0
                };
                try {
                    const cfgRes = await fetch(window.chatContext.marriage.divorceConfigUrl, {
                        headers: {
                            'Accept': 'application/json',
                            'X-Requested-With': 'XMLHttpRequest'
                        }
                    });
                    if (cfgRes.ok) divorceConfig = await cfgRes.json();
                } catch (e) {
                    /* 网络异常则使用默认值 */
                }

                // 打开专属离婚确认弹窗
                const modal = document.getElementById('divorce-confirm-modal');
                if (modal && window.Alpine) {
                    window.Alpine.$data(modal).open(marriageId, divorceConfig);
                }
            },


            /** 获取用户资料 */
            async fetchUser(username) {
                try {
                    const res = await fetch('/user/' + encodeURIComponent(username), {
                        headers: {
                            'Accept': 'application/json',
                            'X-Requested-With': 'XMLHttpRequest'
                        }
                    });

                    if (!res.ok) {
                        const errorData = await res.json().catch(() => ({}));
                        console.error('Failed to fetch user:', errorData.message || res.statusText);
                        return;
                    }

                    const data = await res.json();
                    if (data.status === 'success') {
                        this.userInfo = data.data;
                        this.showPositionHistory = false;

                        // 加载好友状态（仅对非自己的用户查询）
                        if (data.data.username !== window.chatContext.username) {
                            fetch(`/friend/${encodeURIComponent(data.data.username)}/status`, {
                                headers: {
                                    'Accept': 'application/json',
                                    'X-Requested-With': 'XMLHttpRequest'
                                }
                            }).then(r => r.json()).then(s => {
                                this.is_friend = s.is_friend ?? false;
                            });

                            // 加载对方婚姻状态
                            this.targetMarriage = null;
                            this.marriageLoading = true;
                            fetch(`/marriage/target?username=${encodeURIComponent(data.data.username)}`, {
                                headers: {
                                    'Accept': 'application/json',
                                    'X-Requested-With': 'XMLHttpRequest'
                                }
                            }).then(r => r.json()).then(m => {
                                this.targetMarriage = m.marriage ?? null;
                            }).catch(() => {
                            }).finally(() => {
                                this.marriageLoading = false;
                            });
                        }
                        this.showUserModal = true;
                        this.isMuting = false;
                        this.showWhispers = false;
                        this.whisperList = [];
                        this.showAppointPanel = false;
                        this.selectedPositionId = null;
                        this.appointRemark = '';
                        // 有职务的操作人预加载可用职务列表
                        if (window.chatContext?.hasPosition) {
                            this._loadPositions();
                        }
                    }
                } catch (e) {
                    console.error('Error fetching user:', e);
                }
            },

            /** 加载可任命职务列表 */
            async _loadPositions() {
                if (!window.chatContext?.appointPositionsUrl) return;
                try {
                    const res = await fetch(window.chatContext.appointPositionsUrl, {
                        headers: {
                            'Accept': 'application/json'
                        }
                    });
                    const data = await res.json();
                    if (data.status === 'success') {
                        this.appointPositions = data.positions;
                        if (this.appointPositions.length > 0) {
                            this.selectedPositionId = this.appointPositions[0].id;
                        }
                    }
                } catch (e) {
                    /* 静默失败 */
                }
            },

            /** 快速任命 */
            async doAppoint() {
                if (this.appointLoading || !this.selectedPositionId) return;
                this.appointLoading = true;
                try {
                    const res = await fetch(window.chatContext.appointUrl, {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            username: this.userInfo.username,
                            position_id: this.selectedPositionId,
                            remark: this.appointRemark.trim() || null,
                            room_id: window.chatContext.roomId ?? null,
                        })
                    });
                    const data = await res.json();
                    const ok = data.status === 'success';
                    if (ok) {
                        this.showUserModal = false;
                    } else {
                        this.$alert(data.message, '操作失败', '#cc4444');
                    }
                } catch (e) {
                    this.$alert('网络异常，请稍后重试', '错误', '#cc4444');
                }
                this.appointLoading = false;
            },

            /** 快速撤销 */
            async doRevoke() {
                const ok = await this.$confirm(
                    '确定要撤销 「' + this.userInfo.username + '」 的职务吗？撤销后将不再拥有相关权限。',
                    '撤销职务'
                );
                if (!ok) return;
                this.appointLoading = true;
                try {
                    const res = await fetch(window.chatContext.revokeUrl, {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            username: this.userInfo.username,
                            remark: '聊天室快速撤销',
                            room_id: window.chatContext.roomId ?? null,
                        })
                    });
                    const data = await res.json();
                    const revOk = data.status === 'success';
                    if (revOk) {
                        this.showUserModal = false;
                    } else {
                        this.$alert(data.message, '操作失败', '#cc4444');
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
                this.appointLoading = false;
            },
            /** 踢出用户 */
            async kickUser() {
                const reason = await this.$prompt('踢出原因（可留空）：', '违反聊天室规则', '踢出用户', '#cc4444');
                if (reason === null) return;
                try {
                    const res = await fetch('/command/kick', {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            username: this.userInfo.username,
                            room_id: window.chatContext.roomId,
                            reason: reason || '违反聊天室规则'
                        })
                    });
                    const data = await res.json();
                    if (data.status === 'success') {
                        this.showUserModal = false;
                    } else {
                        this.$alert('操作失败：' + data.message, '操作失败', '#cc4444');
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
            },

            /** 禁言用户 */
            async muteUser() {
                try {
                    const res = await fetch('/command/mute', {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            username: this.userInfo.username,
                            room_id: window.chatContext.roomId,
                            duration: this.muteDuration
                        })
                    });
                    const data = await res.json();
                    if (data.status === 'success') {
                        this.showUserModal = false;
                    } else {
                        this.$alert('操作失败：' + data.message, '操作失败', '#cc4444');
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
            },

            /** 警告用户 */
            async warnUser() {
                const reason = await this.$prompt('警告原因：', '请注意言行', '警告用户', '#f59e0b');
                if (reason === null) return;
                try {
                    const res = await fetch('/command/warn', {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            username: this.userInfo.username,
                            room_id: window.chatContext.roomId,
                            reason: reason || '请注意言行'
                        })
                    });
                    const data = await res.json();
                    if (data.status === 'success') {
                        this.showUserModal = false;
                    } else {
                        this.$alert('操作失败：' + data.message, '操作失败', '#cc4444');
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
            },

            /** 封禁账号 */
            async banUser() {
                const confirmed = await this.$confirm(
                    '确定要封禁 ' + this.userInfo.username + ' 的账号吗？封禁后将无法登录。',
                    '封禁账号',
                    '#991b1b'
                );
                if (!confirmed) return;
                const reason = await this.$prompt('封禁原因：', '严重违规', '填写原因', '#991b1b');
                if (reason === null) return;
                try {
                    const res = await fetch('/command/ban', {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            username: this.userInfo.username,
                            room_id: window.chatContext.roomId,
                            reason: reason || '严重违规'
                        })
                    });
                    const data = await res.json();
                    if (data.status === 'success') {
                        this.showUserModal = false;
                    } else {
                        this.$alert('操作失败：' + data.message, '操作失败', '#cc4444');
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
            },

            /** 封禁 IP */
            async banIpUser() {
                const confirmed = await this.$confirm(
                    '确定要封禁 ' + this.userInfo.username + ' 的 IP 吗？该操作会同时冻结账号。',
                    '封禁 IP',
                    '#9a3412'
                );
                if (!confirmed) return;
                const reason = await this.$prompt('封禁原因：', '严重违规', '填写原因', '#9a3412');
                if (reason === null) return;
                try {
                    const res = await fetch('/command/banip', {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            username: this.userInfo.username,
                            room_id: window.chatContext.roomId,
                            reason: reason || '严重违规'
                        })
                    });
                    const data = await res.json();
                    if (data.status === 'success') {
                        this.showUserModal = false;
                    } else {
                        this.$alert('操作失败：' + data.message, '操作失败', '#cc4444');
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
            },

            /** 查看私信记录 */
            async loadWhispers() {
                try {
                    const res = await fetch('/command/whispers/' + encodeURIComponent(this.userInfo.username), {
                        headers: {
                            'Accept': 'application/json'
                        }
                    });
                    const data = await res.json();
                    if (data.status === 'success') {
                        this.whisperList = data.messages;
                        this.showWhispers = true;
                    } else {
                        this.$alert(data.message, '操作失败', '#cc4444');
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
            },

            /** 发送全服公告 */
            async sendAnnounce() {
                if (!this.announceText.trim()) return;
                try {
                    const res = await fetch('/command/announce', {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            content: this.announceText,
                            room_id: window.chatContext.roomId,
                        })
                    });
                    const data = await res.json();
                    if (data.status === 'success') {
                        this.announceText = '';
                        this.showAnnounce = false;
                    } else {
                        this.$alert(data.message, '操作失败', '#cc4444');
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
            },

            /** 送礼物 */
            async sendGift() {
                if (this.sendingGift || !this.selectedGiftId) return;
                this.sendingGift = true;
                try {
                    const res = await fetch('/gift/flower', {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            to_user: this.userInfo.username,
                            room_id: window.chatContext.roomId,
                            gift_id: this.selectedGiftId,
                            count: this.giftCount
                        })
                    });
                    const data = await res.json();
                    this.$alert(data.message, data.status === 'success' ? '送礼成功 🎁' : '操作失败',
                        data.status === 'success' ? '#e11d48' : '#cc4444');
                    if (data.status === 'success') {
                        this.showUserModal = false;
                        this.giftCount = 1;
                    }
                } catch (e) {
                    this.$alert('网络异常', '错误', '#cc4444');
                }
                this.sendingGift = false;
            },

            /** 切换礼物面板，和赠送金币面板互斥显示 */
            toggleGiftPanel() {
                this.showGiftPanel = !this.showGiftPanel;
                this.showGiftGoldPanel = false;
            },

            /** 切换赠送金币面板，和礼物面板互斥显示 */
            toggleGiftGoldPanel() {
                this.showGiftGoldPanel = !this.showGiftGoldPanel;
                this.showGiftPanel = false;
            },

            /** 给用户赠送自己的金币 */
            async sendGiftGold() {
                const amount = Number.parseInt(this.giftGoldAmount, 10);
                if (this.giftGoldSending || !amount || amount <= 0) {
                    return;
                }

                this.giftGoldSending = true;

                try {
                    const response = await fetch("/gift/gold", {
                        method: "POST",
                        headers: this._headers(),
                        body: JSON.stringify({
                            to_user: this.userInfo.username,
                            room_id: window.chatContext.roomId,
                            amount,
                        }),
                    });
                    const data = await response.json();

                    if (data.status === "success") {
                        window.chatContext.myGold = data.data?.my_jjb ?? window.chatContext.myGold;
                        this.showGiftGoldPanel = false;
                        this.giftGoldAmount = "";
                        this.$alert(data.message, "赠送成功 💝", "#d97706");
                        return;
                    }

                    this.$alert(data.message, "赠送失败", "#cc4444");
                } catch (error) {
                    this.$alert("网络异常", "错误", "#cc4444");
                }

                this.giftGoldSending = false;
            },

            /** 职务奖励：向用户发放金币（凭空产生，记入履职记录） */
            async sendReward() {
                if (this.sendingReward) return;
                const maxOnce = window.chatContext?.myMaxReward ?? 0;
                const amount = parseInt(this.rewardAmount, 10);
                if (!amount || amount <= 0) {
                    this.$alert('请输入有效的奖励金额', '提示', '#f59e0b');
                    return;
                }
                // 0 = 禁止（前端按钮不显示，此处二次保护）
                if (maxOnce === 0) {
                    this.$alert('你的职务没有奖励发放权限', '无权限', '#cc4444');
                    return;
                }
                // -1 = 不限，跳过上限校验；正整数 = 有具体上限
                if (maxOnce > 0 && amount > maxOnce) {
                    this.$alert(`单次奖励上限为 ${maxOnce} 金币`, '超出上限', '#cc4444');
                    return;
                }
                this.sendingReward = true;
                try {
                    const res = await fetch(window.chatContext.rewardUrl, {
                        method: 'POST',
                        headers: this._headers(),
                        body: JSON.stringify({
                            username: this.userInfo.username,
                            room_id: window.chatContext.roomId,
                            amount,
                        })
                    });
                    const data = await res.json();
                    const ok = data.status === 'success';
                    this.$alert(data.message, ok ? '奖励发放成功 🎉' : '操作失败',
                        ok ? '#d97706' : '#cc4444');
                    if (ok) {
                        this.showRewardPanel = false;
                        this.rewardAmount = 0;
                    }
                } catch (e) {
                    this.$alert('网络异常，请稍后重试', '错误', '#cc4444');
                }
                this.sendingReward = false;
            },

            /** 通用请求头 */
            _headers() {
                return {
                    'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
                    'Content-Type': 'application/json',
                    'Accept': 'application/json'
                };
            }
        };
}

/**
 * 挂载用户名片组件全局名称，兼容 Blade 的 x-data。
 *
 * @returns {void}
 */
export function bindUserCardControls() {
    if (typeof window === "undefined") {
        return;
    }

    window.userCardComponent = userCardComponent;
}
