// pages/messages/messages.js
const app = getApp();
import { formatDate } from '../../static/lib/utils';
import { resolveAvatarUrl, getDefaultAvatarUrl, resolveAvatarFromStorage } from '../../utils/avatar.js';
import { getLocalImUserId, getLocalImIdentity, getImUserIdForRole, loadGroupMetaCache, getDefaultAvatar } from '../../utils/im-user.js';
import { enrichGroupConversation, isOrderGroupConversation, sortConversations, recordConversationOpen, getZhuangtaiText } from '../../utils/group-chat.js';
import request from '../../utils/request';
import { openCustomerServiceChat } from '../../utils/kefu-nav.js';
import { getPrimaryRole } from '../../utils/primary-role.js';
import { isStaffMode } from '../../utils/staff-api.js';
import { createPage } from '../../utils/base-page.js';
const { jianquanxian } = require('../../utils/imAuth/jianquanxian');

Page(createPage({
    data: {
        allConversations: [],
        filteredConversations: [],
        activeTab: 0,
        tabUnread: [0, 0, 0],
        displayCount: 10,
        searchKeyword: '',
        actionPopup: { visible: false, conversation: null },
        currentUser: null,
        notificationMuted: false,
        scrollHeight: 0,
        imStatus: 'connecting',
        imStatusText: '',
        defaultAvatarUrl: '',
    },

    _permissionSeq: 0,
    _peerProfileCache: {},
    _lastConvSignature: '',
    _lastRefreshTs: 0,
    _showRefreshTimer: null,
    _statusRefreshTimer: null,
    _chatAllowed: true,

    onLoad() {
        this.calculateScrollHeight();
        this.setData({ defaultAvatarUrl: getDefaultAvatarUrl(app) });
        const muted = wx.getStorageSync('notificationMuted') || false;
        this.setData({ notificationMuted: muted });
        if (app.globalData.messageManager) {
            app.globalData.messageManager.notificationMuted = muted;
        }
        loadGroupMetaCache(app);
        this._onGlobalConvUpdated = (content) => {
            if (content && content.conversations) {
                this.renderConversations(content);
            } else if (app.loadConversations) {
                app.loadConversations();
            }
        };
        this._onUnreadChanged = (data) => {
            const unreadTotal = data?.unreadTotal ?? app.globalData.messageManager?.unreadTotal ?? 0;
            if (app.globalData.messageManager) {
                app.globalData.messageManager.unreadTotal = unreadTotal;
            }
            if (app.emitEvent) {
                app.emitEvent('tabBarBadgeChanged', {
                    badgeText: unreadTotal > 0 ? String(unreadTotal) : '',
                });
            }
        };
        this._onConnectionChanged = (data) => {
            const status = data?.status || 'disconnected';
            const textMap = {
                connected: '',
                connecting: '正在连接消息服务…',
                reconnecting: '正在重新连接…',
                disconnected: '消息未连接，点击重试',
                disabled: '消息服务未配置',
            };
            this.setData({
                imStatus: status,
                imStatusText: textMap[status] || (status === 'connected' ? '' : '消息未连接，点击重试'),
            });
            if (status === 'connected') {
                this.setupConversationListener();
                this.loadConversations();
            }
        };
        app.on('conversationsUpdated', this._onGlobalConvUpdated);
        app.on('unreadCountChanged', this._onUnreadChanged);
        app.on('connectionChanged', this._onConnectionChanged);
    },

    onUnload() {
        if (this._onGlobalConvUpdated) {
            app.off('conversationsUpdated', this._onGlobalConvUpdated);
        }
        if (this._onUnreadChanged) {
            app.off('unreadCountChanged', this._onUnreadChanged);
        }
        if (this._onConnectionChanged) {
            app.off('connectionChanged', this._onConnectionChanged);
        }
        if (this.conversationsUpdatedListener && wx.goEasy?.im) {
            wx.goEasy.im.off(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, this.conversationsUpdatedListener);
            this.conversationsUpdatedListener = null;
        }
    },

    async onShow() {
        if (!this.checkLoginStatus()) return;
        this.setData({ defaultAvatarUrl: getDefaultAvatarUrl(app) });
        loadGroupMetaCache(app);
        if (app.restoreTabBarBadge) app.restoreTabBarBadge();
        this.registerNotificationComponent();
        if (app.globalData.messageManager?.unreadTotal != null && app.emitEvent) {
            app.emitEvent('tabBarBadgeChanged', {
                badgeText: app.globalData.messageManager.unreadTotal > 0
                    ? String(app.globalData.messageManager.unreadTotal) : '',
            });
        }
        this.patchLocalReadState();
        await this.checkPermissionAndAutoConnect();
        if (this._chatAllowed) {
            if (app.ensureConnection) app.ensureConnection();
            this.setupConversationListener();
            if (app.syncConnectionStatus) app.syncConnectionStatus();
            this.scheduleSoftRefresh();
        }
    },

    scheduleSoftRefresh() {
        if (this._showRefreshTimer) clearTimeout(this._showRefreshTimer);
        if (this._statusRefreshTimer) clearTimeout(this._statusRefreshTimer);
        this._showRefreshTimer = setTimeout(() => {
            this._showRefreshTimer = null;
            const now = Date.now();
            if (now - this._lastRefreshTs < 1800 && this.data.allConversations.length) {
                return;
            }
            this._lastRefreshTs = now;
            if (app.loadConversations) app.loadConversations();
            else if (wx.goEasy?.im) this.loadConversations();
        }, 350);
    },

    patchLocalReadState() {
        const openId = app.globalData.pageState?.lastOpenedConvId;
        if (!openId || !this.data.allConversations.length) return;

        const list = this.data.allConversations.map((c) => {
            const id = c.groupId || c.userId;
            if (id === openId && (c.unread || 0) > 0) {
                return { ...c, unread: 0 };
            }
            return c;
        });

        const openTimes = wx.getStorageSync('conversationOpenTimes') || {};
        sortConversations(list, openTimes);
        this.setData({ allConversations: list }, () => this.applyFilter());
    },

    retryImConnection() {
        if (!app.globalData.chatEnabled) {
            wx.showToast({ title: '消息服务未就绪', icon: 'none' });
            return;
        }
        this.setData({ imStatus: 'connecting', imStatusText: '正在连接消息服务…' });
        app.globalData.goEasyConnection.autoReconnect = true;
        app.globalData.goEasyConnection.reconnectAttempts = 0;
        if (app.ensureConnection) app.ensureConnection();
        setTimeout(() => {
            if (app.syncConnectionStatus) app.syncConnectionStatus();
            if (app.loadConversations) app.loadConversations();
        }, 2000);
    },

    onHide() {},

    // ========== ==== ================ ==== ================ 鉴权检查 ==========
    async checkPermissionAndAutoConnect() {
        const seq = ++this._permissionSeq;
        let quanxian;
        try {
            quanxian = await jianquanxian(app, { silent: true });
        } catch (e) {
            this._chatAllowed = true;
            return;
        }
        if (seq !== this._permissionSeq) return;

        if (!quanxian.allowed) {
            this._chatAllowed = false;
            const currentRole = app.globalData.currentRole || 'normal';
            let hint = '消息连接暂不可用，列表可正常浏览';
            if (currentRole === 'dashou') {
                hint = '开通会员后可收发消息（列表可正常浏览）';
            }
            const prev = this.data.imStatusText;
            if (prev !== hint) {
                this.setData({ imStatusText: hint });
            }
            return;
        }
        this._chatAllowed = true;
        if (this.data.imStatusText && this.data.imStatusText.includes('会员')) {
            this.setData({ imStatusText: '' });
        }
        this.autoConnect();
    },

    // 登录状态检查
    checkLoginStatus() {
        const uid = wx.getStorageSync('uid');
        if (!uid) {
            wx.showToast({ title: '请先登录', icon: 'none' });
            setTimeout(() => { wx.redirectTo({ url: '/pages/mine/mine' }); }, 1500);
            return false;
        }
        let currentUser = app.globalData.currentUser;
        if (!currentUser) {
            currentUser = {
                id: getLocalImUserId(app) || uid,
                name: wx.getStorageSync('nicheng') || app.globalData.dashouNicheng || app.globalData.nicheng || ('用户' + uid.substring(0, 6)),
                avatar: resolveAvatarFromStorage(app),
            };
            app.globalData.currentUser = currentUser;
        }
        this.setData({ currentUser });
        return true;
    },

    autoConnect() {
        const role = isStaffMode() ? 'shangjia' : (getLocalImIdentity(app) || app.globalData.currentRole || 'normal');
        const uid = wx.getStorageSync('uid');
        const targetUserId = getImUserIdForRole(role, uid);
        if (!targetUserId) return;

        const onReady = () => {
            this.setupConversationListener();
            if (app.loadConversations) app.loadConversations();
            else this.loadConversations();
        };

        const status = wx.goEasy?.getConnectionStatus?.() || 'disconnected';
        const currentUserId = wx.goEasy?.im?.userId;
        if ((status === 'connected' || status === 'reconnected') && currentUserId === targetUserId) {
            onReady();
            return;
        }

        const tryConnect = async () => {
            try {
                if (app.ensureImForRole) {
                    await app.ensureImForRole(role);
                } else if (app.connectWithIdentity) {
                    await app.connectWithIdentity(role, targetUserId, true);
                } else if (app.ensureConnection) {
                    app.ensureConnection();
                }
                onReady();
            } catch (e) {
                const s = wx.goEasy?.getConnectionStatus?.();
                if (s === 'connected' || s === 'reconnected') onReady();
            }
        };
        tryConnect();
    },

    connectGoEasy(userId) {
        const { currentUser } = this.data;
        if (!currentUser) return;
        wx.goEasy.connect({
            id: userId,
            data: {
                name: currentUser.name,
                avatar: resolveAvatarUrl(currentUser.avatar, app),
            },
            onSuccess: () => {
                try {
                    wx.setStorageSync('savedGoEasyConnection', JSON.stringify({
                        userId,
                        identityType: app.globalData.currentRole,
                        lastConnectTime: Date.now(),
                        status: 'connected',
                    }));
                } catch (e) {}
                this.setupConversationListener();
                this.loadConversations();
                if (app.registerNotification) {
                }
            },
            onFailed: (error) => {
                if (error.code === 408) {
                    this.setupConversationListener();
                    this.loadConversations();
                } else {
                    wx.showToast({ title: '连接失败，请重试', icon: 'none' });
                }
            },
        });
    },

    setupConversationListener() {
        if (!wx.goEasy || !wx.goEasy.im) return;
        if (this.conversationsUpdatedListener) {
            wx.goEasy.im.off(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, this.conversationsUpdatedListener);
        }
        this.conversationsUpdatedListener = (result) => {
            const content = result?.content || result;
            this.renderConversations(content);
        };
        wx.goEasy.im.on(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, this.conversationsUpdatedListener);
    },

    loadConversations() {
        if (!wx.goEasy || !wx.goEasy.im) return;
        wx.goEasy.im.latestConversations({
            onSuccess: (result) => {
                const content = result?.content || result;
                this.renderConversations(content);
            },
            onFailed: () => {
                wx.showToast({ title: '获取会话失败', icon: 'none' });
            },
        });
    },

    // 会话渲染与排序
    renderConversations(content) {
        if (!content || !content.conversations) {
            this.setData({ allConversations: [] }, () => this.applyFilter());
            return;
        }
        let list = content.conversations;
        const defaultAvatar = getDefaultAvatar(app);
        const myGoEasyId = wx.goEasy?.im?.userId || getLocalImUserId(app);
        const ossBase = app.globalData.ossImageUrl || '';
        const groupMeta = app.globalData.groupInfoMap || {};

        list.forEach((item, idx) => {
            item.key = item.groupId || item.userId || item.teamId || `${item.type || 'c'}_${idx}`;
            if (item.type === 'group') {
                if (!item.data) item.data = {};
                if (!item.data.orderId && item.groupId) {
                    const m = /^group_(.+)$/.exec(String(item.groupId));
                    if (m) item.data.orderId = m[1];
                }
                const meta = groupMeta[item.groupId];
                if (meta) {
                    if (!item.data) item.data = {};
                    Object.assign(item.data, meta);
                }
                if (item.data.orderJieshao && !item.data.orderDesc) {
                    item.data.orderDesc = item.data.orderJieshao;
                }
                if (item.data && item.data.dashouGoEasyId) {
                    if (!app.globalData.groupInfoMap) app.globalData.groupInfoMap = {};
                    app.globalData.groupInfoMap[item.groupId] = {
                        ...app.globalData.groupInfoMap[item.groupId],
                        ...item.data,
                    };
                }
                enrichGroupConversation(item, myGoEasyId, defaultAvatar, ossBase);
            } else {
                if (!item.data) item.data = {};
                item.data.avatar = resolveAvatarUrl(item.data.avatar, app) || defaultAvatar;
            }
            if (!item.lastMessage) {
                item.lastMessage = { type: 'text', payload: { text: '' }, timestamp: 0 };
            }
            if (item.lastMessage.timestamp) {
                item.lastMessage.date = formatDate(item.lastMessage.timestamp);
            }
        });

        const openTimes = wx.getStorageSync('conversationOpenTimes') || {};
        sortConversations(list, openTimes);

        const unreadTotal = content.unreadTotal !== undefined
            ? content.unreadTotal
            : list.reduce((sum, c) => sum + (c.unread || 0), 0);

        const signature = list.map((c) => {
            const id = c.groupId || c.userId || c.teamId || '';
            const unread = c.unread || 0;
            const ts = c.lastMessage?.timestamp || 0;
            const preview = c.displayLastMsg || c.lastMessage?.payload?.text || '';
            return `${id}:${unread}:${ts}:${preview.slice(0, 20)}`;
        }).join('|');

        if (signature === this._lastConvSignature && this.data.allConversations.length) {
            if (app.globalData.messageManager) {
                app.globalData.messageManager.unreadTotal = unreadTotal;
            }
            if (app.updateUnreadCount) {
                app.updateUnreadCount(unreadTotal);
            } else if (app.emitEvent) {
                app.emitEvent('tabBarBadgeChanged', { badgeText: unreadTotal > 0 ? String(unreadTotal) : '' });
            }
            this.applyFilter();
            return;
        }
        this._lastConvSignature = signature;

        if (app.globalData.messageManager) {
            app.globalData.messageManager.unreadTotal = unreadTotal;
        }
        if (app.updateUnreadCount) {
            app.updateUnreadCount(unreadTotal);
        } else if (app.emitEvent) {
            app.emitEvent('tabBarBadgeChanged', { badgeText: unreadTotal > 0 ? String(unreadTotal) : '' });
        }

        const prevDisplay = this.data.displayCount;
        this.setData({
            allConversations: list,
            displayCount: prevDisplay > 10 ? prevDisplay : 10,
        }, () => {
            this.applyFilter();
        });

        this.subscribeGroupsIfNeeded(list);
        this.scheduleOrderStatusRefresh(list);
    },

    scheduleOrderStatusRefresh(conversations) {
        if (this._statusRefreshTimer) clearTimeout(this._statusRefreshTimer);
        this._statusRefreshTimer = setTimeout(() => {
            this._statusRefreshTimer = null;
            this.refreshOrderStatuses(conversations);
        }, 400);
    },

    async refreshOrderStatuses(conversations) {
        const orderIds = [];
        (conversations || this.data.allConversations).forEach((c) => {
            if (!isOrderGroupConversation(c)) return;
            const oid = c.data?.orderId;
            if (oid && !orderIds.includes(oid)) orderIds.push(oid);
        });
        if (!orderIds.length) return;

        try {
            const res = await request({
                url: '/dingdan/ltddztpl',
                method: 'POST',
                data: { order_ids: orderIds.slice(0, 20) },
            });
            const body = res?.data || {};
            const map = body.data || {};
            if (!Object.keys(map).length) return;

            let changed = false;
            const list = this.data.allConversations.map((c) => {
                const oid = c.data?.orderId;
                if (!oid || !map[oid]) return c;
                const st = map[oid];
                changed = true;
                const data = {
                    ...c.data,
                    orderId: oid,
                    orderDesc: st.jieshao || c.data.orderDesc,
                    orderJine: st.jine != null ? st.jine : c.data.orderJine,
                    orderZhuangtai: st.zhuangtai,
                    orderZhuangtaiText: getZhuangtaiText(st.zhuangtai),
                };
                if (c.groupId && app.globalData.groupInfoMap) {
                    app.globalData.groupInfoMap[c.groupId] = {
                        ...(app.globalData.groupInfoMap[c.groupId] || {}),
                        ...data,
                    };
                }
                return { ...c, data };
            });
            if (changed) {
                this.setData({ allConversations: list }, () => this.applyFilter());
            }
        } catch (e) {
            console.warn('刷新订单状态失败', e);
        }
    },

    /**
     * 群组订阅，每次获取群组列表时直接订阅保证消息不丢失
     */
    subscribeGroupsIfNeeded(conversations) {
        if (!wx.goEasy?.im || typeof wx.goEasy.im.subscribeGroup !== 'function') return;

        const groupIds = conversations
            .filter(c => c.type === 'group' && c.groupId)
            .map(c => c.groupId);

        if (groupIds.length === 0) return;

        // 不再判断缓存，直接订阅当前所有群组
        wx.goEasy.im.subscribeGroup({
            groupIds: groupIds,
            onSuccess: () => {
                // 可选的日志输出，不影响功能
                // console.log('群组订阅成功', groupIds);
            },
            onFailed: (error) => {
                console.error('群组订阅失败:', error);
            }
        });
    },

    applyFilter() {
        const { allConversations, activeTab, searchKeyword } = this.data;
        let filtered = [];
        if (activeTab === 0) {
            filtered = allConversations.filter(c => isOrderGroupConversation(c));
        } else if (activeTab === 1) {
            filtered = allConversations.filter(c => c.type === 'private');
        } else if (activeTab === 2) {
            filtered = allConversations.filter(c => c.type === 'cs');
        }

        if (searchKeyword.trim()) {
            const kw = searchKeyword.trim().toLowerCase();
            filtered = filtered.filter(c => {
                const name = (c.data && c.data.name || '').toLowerCase();
                const orderId = (c.data && c.data.orderId || '').toLowerCase();
                const id = (c.userId || c.groupId || '').toLowerCase();
                return name.includes(kw) || id.includes(kw) || orderId.includes(kw);
            });
        }

        const tabUnread = [0, 0, 0];
        allConversations.forEach(c => {
            if (isOrderGroupConversation(c)) tabUnread[0] += c.unread || 0;
            else if (c.type === 'private') tabUnread[1] += c.unread || 0;
            else if (c.type === 'cs') tabUnread[2] += c.unread || 0;
        });

        this.setData({ filteredConversations: filtered, tabUnread });
    },

    switchTab(e) {
        const index = parseInt(e.currentTarget.dataset.index);
        this.setData({ activeTab: index, displayCount: 10, searchKeyword: '' }, () => {
            this.applyFilter();
            this.calculateScrollHeight();
        });
    },

    onSearchInput(e) {
        this.setData({ searchKeyword: e.detail.value, displayCount: 10 }, () => this.applyFilter());
    },

    onScrollToLower() {
        const { displayCount, filteredConversations } = this.data;
        if (displayCount < filteredConversations.length) {
            this.setData({ displayCount: Math.min(displayCount + 10, filteredConversations.length) });
        }
    },

    onRefresh() {
        this.loadConversations();
    },

    chat(e) {
        const conversation = e.currentTarget.dataset.conversation;
        if (!conversation) return;
        if (this._chatAllowed === false) {
            wx.showToast({ title: '请先开通会员后再聊天', icon: 'none' });
            return;
        }
        recordConversationOpen(conversation);
        const convId = conversation.groupId || conversation.userId;
        if (convId) {
            if (!app.globalData.pageState) app.globalData.pageState = {};
            app.globalData.pageState.lastOpenedConvId = convId;
        }

        if (conversation.type === 'private') {
            const param = {
                toUserId: conversation.userId,
                toName: conversation.data.name || '用户',
                toAvatar: resolveAvatarUrl(conversation.data.avatar, app),
            };
            wx.navigateTo({ url: '/pages/chat/chat?data=' + encodeURIComponent(JSON.stringify(param)) });
        } else if (conversation.type === 'group' || (conversation.groupId && isOrderGroupConversation(conversation))) {
            const d = conversation.data || {};
            const rawGid = conversation.groupId || '';
            const oid = String(d.orderId || rawGid).replace(/^group_/, '');
            const groupId = rawGid.startsWith('group_') ? rawGid : (oid ? `group_${oid}` : rawGid);
            const param = {
                groupId,
                orderId: oid,
                groupName: d.name || '订单群聊',
                groupAvatar: d.avatar,
                isCross: d.isCross || 0,
                orderZhuangtai: d.orderZhuangtai,
                orderJine: d.orderJine,
                orderDesc: d.orderDesc || d.orderJieshao || '',
                currentUserId: wx.goEasy?.im?.userId || getLocalImUserId(app),
                currentUserName: this.data.currentUser?.name || '',
                currentUserAvatar: this.data.currentUser?.avatar || '',
            };
            wx.navigateTo({ url: '/pages/group-chat/group-chat?data=' + encodeURIComponent(JSON.stringify(param)) });
        } else if (conversation.type === 'cs') {
            const param = { teamId: conversation.teamId || conversation.id };
            wx.navigateTo({ url: '/pages/cs-chat/cs-chat?data=' + encodeURIComponent(JSON.stringify(param)) });
        }
    },

    chatKefu() {
        openCustomerServiceChat();
    },

    showAction(e) {
        const conversation = e.currentTarget.dataset.conversation;
        this.setData({ ['actionPopup.conversation']: conversation, ['actionPopup.visible']: true });
    },
    closeMask() {
        this.setData({ ['actionPopup.visible']: false });
    },
    topConversation() {
        let conversation = this.data.actionPopup.conversation;
        if (!conversation) return;
        const top = !conversation.top;
        wx.showLoading({ title: '处理中...' });
        if (conversation.type === 'private') {
            wx.goEasy.im.topPrivateConversation({
                userId: conversation.userId, top,
                onSuccess: () => {
                    wx.hideLoading(); this.loadConversations();
                    wx.showToast({ title: top ? '已置顶' : '已取消置顶' });
                },
                onFailed: () => { wx.hideLoading(); wx.showToast({ title: '操作失败', icon: 'none' }); }
            });
        } else {
            wx.goEasy.im.topGroupConversation({
                groupId: conversation.groupId, top,
                onSuccess: () => {
                    wx.hideLoading(); this.loadConversations();
                    wx.showToast({ title: top ? '已置顶' : '已取消置顶' });
                },
                onFailed: () => { wx.hideLoading(); wx.showToast({ title: '操作失败', icon: 'none' }); }
            });
        }
        this.closeMask();
    },
    removeConversation() {
        let conversation = this.data.actionPopup.conversation;
        if (!conversation) return;
        wx.showLoading({ title: '删除中...' });
        wx.goEasy.im.removeConversation({
            conversation: conversation,
            onSuccess: () => { wx.hideLoading(); this.loadConversations(); wx.showToast({ title: '已删除' }); },
            onFailed: () => { wx.hideLoading(); wx.showToast({ title: '删除失败', icon: 'none' }); }
        });
        this.closeMask();
    },

    toggleNotification() {
        const newMuted = !this.data.notificationMuted;
        this.setData({ notificationMuted: newMuted });
        wx.setStorageSync('notificationMuted', newMuted);
        wx.showToast({ title: newMuted ? '已静音' : '已开启通知', icon: 'none' });
    },

    calculateScrollHeight() {
        const systemInfo = wx.getSystemInfoSync();
        const windowHeight = systemInfo.windowHeight;
        const windowWidth = systemInfo.windowWidth;
        const rpxRatio = 750 / windowWidth;
        const headerHeight = 150 / rpxRatio;
        const tabBarHeight = 130 / rpxRatio;
        const kefuBarHeight = this.data.activeTab === 2 ? (112 / rpxRatio) : 0;
        const safeAreaBottom = systemInfo.safeArea ? (windowHeight - systemInfo.safeArea.bottom) : 0;
        this.setData({ scrollHeight: windowHeight - headerHeight - tabBarHeight - kefuBarHeight - safeAreaBottom });
    },

    onAvatarError(e) {
        const index = e.currentTarget.dataset.index;
        const def = getDefaultAvatarUrl(app);
        const key = `filteredConversations[${index}].data.avatar`;
        this.setData({ [key]: def });
    }
}))
