// utils/chat-core.js — 全局 IM 连接、监听、角标（稳定版）
import GoEasy from '../static/lib/goeasy-2.13.24.esm.min';
import { resolveAvatarUrl } from './avatar.js';
import { getLocalImUserId, getLocalImIdentity } from './im-user.js';

let _convListener = null;
let _privateListener = null;
let _groupListener = null;
let _notificationHandler = null;
let _heartbeatTimer = null;
let _listenersBoundForUser = null;
let _lastGroupSubscribeAt = 0;
const _notifiedMessageIds = new Map();
const NOTIFY_MAX_AGE_MS = 15000;

function shouldShowNotification(message) {
  if (!message) return false;
  const id = message.messageId || `${message.senderId}_${message.timestamp}`;
  if (_notifiedMessageIds.has(id)) return false;
  if (message.timestamp && Date.now() - message.timestamp > NOTIFY_MAX_AGE_MS) return false;
  _notifiedMessageIds.set(id, Date.now());
  if (_notifiedMessageIds.size > 400) {
    const cutoff = Date.now() - 60000;
    _notifiedMessageIds.forEach((t, k) => {
      if (t < cutoff) _notifiedMessageIds.delete(k);
    });
  }
  return true;
}

function bindGlobalListenersIfNeeded(app, userId) {
  if (_listenersBoundForUser === userId && _convListener) return;
  registerGlobalListeners(app);
  registerNotification(app);
  _listenersBoundForUser = userId;
}

function initGlobalMessageSystem(app) {
  app.ensureConnection = () => ensureConnection(app);
  app.connectForCurrentRole = () => ensureConnection(app);
  app.loadConversations = () => loadConversations(app);
  app.disconnectGoEasy = () => disconnectGoEasy(app);
  app.switchRoleAndReconnect = (newRole) => switchRoleAndReconnect(app, newRole);
  app.updateUnreadCount = (count) => updateTabBarBadge(app, count || 0);
  app.reregisterNotification = () => registerNotification(app);
  app.startImWhenReady = () => startImWhenReady(app);

  if (!app.globalData.messageManager) {
    app.globalData.messageManager = {};
  }
  try {
    const muted = wx.getStorageSync('notificationMuted');
    if (muted !== undefined) app.globalData.messageManager.notificationMuted = muted;
  } catch (e) {}

  initAppStateListener(app);
  initNetworkListener(app);
  startHeartbeat(app);
  startImWhenReady(app);
}

/** GoEasy 未就绪时轮询，登录后尽早建立监听 */
function startImWhenReady(app, maxAttempts = 40) {
  let attempts = 0;
  const tick = () => {
    if (!wx.getStorageSync('uid')) return;
    attempts += 1;
    if (!wx.goEasy) {
      if (attempts < maxAttempts) setTimeout(tick, 250);
      return;
    }
    ensureConnection(app);
  };
  tick();
}

function getCurrentUserId() {
  return (wx.goEasy && wx.goEasy.im && wx.goEasy.im.userId) || null;
}

function getConnectionStatus() {
  if (!wx.goEasy || !wx.goEasy.getConnectionStatus) return 'disconnected';
  return wx.goEasy.getConnectionStatus();
}

function isConnected() {
  const s = getConnectionStatus();
  return s === 'connected' || s === 'reconnected';
}

/** 统一会话数据结构，避免不同回调格式导致列表空白 */
function normalizeConversationsPayload(result) {
  if (!result) return { conversations: [], unreadTotal: 0 };
  const content = result.content || result;
  const conversations = content.conversations || result.conversations || [];
  const unreadTotal = content.unreadTotal ?? result.unreadTotal ?? 0;
  return { conversations, unreadTotal };
}

function emitConversationsUpdated(app, result) {
  const payload = normalizeConversationsPayload(result);
  updateTabBarBadge(app, payload.unreadTotal);
  app.emitEvent('conversationsUpdated', {
    content: payload,
    unreadTotal: payload.unreadTotal,
    raw: result,
  });
}

async function ensureConnection(app) {
  const uid = wx.getStorageSync('uid');
  if (!uid || !wx.goEasy) return;

  const targetUserId = getLocalImUserId(app);
  const identityType = getLocalImIdentity(app);
  if (!targetUserId) return;

  if (isConnected()) {
    const currentUserId = getCurrentUserId();
    if (currentUserId === targetUserId) {
      bindGlobalListenersIfNeeded(app, targetUserId);
      loadConversations(app);
      const now = Date.now();
      if (now - _lastGroupSubscribeAt > 60000) {
        _lastGroupSubscribeAt = now;
        await subscribeAllGroups(app);
      }
      return;
    }
    try {
      wx.goEasy.disconnect();
    } catch (e) {}
  }

  connectGoEasy(app, targetUserId, identityType);
}

function connectGoEasy(app, userId, identityType) {
  const defAvatar = resolveAvatarUrl('', app);
  const tx = wx.getStorageSync('touxiang') || '';
  const uid = wx.getStorageSync('uid') || '';
  const nick = wx.getStorageSync('nicheng') || app.globalData.nicheng || app.globalData.dashouNicheng || '';
  const name = nick || ('用户' + (uid || '').substring(0, 6));
  const avatar = resolveAvatarUrl(tx, app) || defAvatar;

  wx.goEasy.connect({
    id: userId,
    data: {
      name,
      avatar,
      identityType: identityType === 'normal' ? 'boss' : identityType,
    },
    onSuccess: async () => {
      try {
        wx.setStorageSync('savedGoEasyConnection', JSON.stringify({
          userId,
          identityType,
          lastConnectTime: Date.now(),
          status: 'connected',
        }));
      } catch (e) {}
      bindGlobalListenersIfNeeded(app, userId);
      _lastGroupSubscribeAt = Date.now();
      await subscribeAllGroups(app);
      loadConversations(app);
    },
    onFailed: (error) => {
      console.error('GoEasy连接失败', error);
      if (error.code === 408) {
        bindGlobalListenersIfNeeded(app, userId);
        loadConversations(app);
      } else {
        wx.showToast({ title: '连接失败，请重试', icon: 'none' });
      }
    },
  });
}

function subscribeAllGroups(app) {
  return new Promise((resolve) => {
    if (!wx.goEasy || !wx.goEasy.im) return resolve();
    wx.goEasy.im.latestConversations({
      onSuccess: (result) => {
        const payload = normalizeConversationsPayload(result);
        const groupIds = payload.conversations
          .filter((c) => c.type === 'group' && c.groupId)
          .map((c) => c.groupId);
        if (groupIds.length && wx.goEasy.im.subscribeGroup) {
          wx.goEasy.im.subscribeGroup({
            groupIds,
            onSuccess: () => resolve(),
            onFailed: () => resolve(),
          });
        } else {
          resolve();
        }
      },
      onFailed: () => resolve(),
    });
  });
}

function registerGlobalListeners(app) {
  if (!wx.goEasy || !wx.goEasy.im) return;

  if (_convListener) {
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, _convListener);
  }
  if (_privateListener) {
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _privateListener);
  }
  if (_groupListener) {
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _groupListener);
  }

  _convListener = (result) => {
    emitConversationsUpdated(app, result);
  };
  wx.goEasy.im.on(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, _convListener);

  _privateListener = () => {
    loadConversations(app);
  };
  wx.goEasy.im.on(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _privateListener);

  _groupListener = () => {
    loadConversations(app);
  };
  wx.goEasy.im.on(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _groupListener);
}

function loadConversations(app) {
  if (!wx.goEasy || !wx.goEasy.im) return;
  if (!getCurrentUserId()) return;

  wx.goEasy.im.latestConversations({
    onSuccess: (result) => {
      emitConversationsUpdated(app, result);
      subscribeAllGroups(app);
    },
    onFailed: (err) => {
      console.error('加载会话失败', err);
    },
  });
}

function updateTabBarBadge(app, unreadCount) {
  const badgeText = unreadCount > 0 ? (unreadCount > 99 ? '99+' : String(unreadCount)) : '';
  if (!app.globalData.messageManager) app.globalData.messageManager = {};
  app.globalData.messageManager.unreadTotal = unreadCount;
  app.globalData.messageManager.tabBarBadgeText = badgeText;
  app.emitEvent('tabBarBadgeChanged', { badgeText, showRedDot: unreadCount > 0 });

  try {
    const pages = getCurrentPages();
    if (pages.length) {
      const page = pages[pages.length - 1];
      const tabBar = page.selectComponent('#custom-tab-bar');
      if (tabBar && tabBar.setData) tabBar.setData({ badgeText });
      if (page.getTabBar) {
        const tb = page.getTabBar();
        if (tb && tb.setData) tb.setData({ badgeText });
      }
    }
  } catch (e) {}
  wx.setStorageSync('messageUnreadTotal', unreadCount);
}

function registerNotification(app) {
  if (!wx.goEasy || !wx.goEasy.im) return;

  if (_notificationHandler) {
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _notificationHandler);
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _notificationHandler);
  }

  _notificationHandler = (message) => {
    if (app.globalData.messageManager && app.globalData.messageManager.notificationMuted) return;
    if (!shouldShowNotification(message)) return;
    const pages = getCurrentPages();
    if (pages.length) {
      const curPage = pages[pages.length - 1];
      const route = curPage.route || '';
      if (route === 'pages/liaotian/liaotian' || route === 'pages/qunliaotian/qunliaotian') return;
    }
    const senderName = message.senderData?.name || (message.senderId || '用户');
    let content = '';
    if (message.type === 'text') content = message.payload?.text || '[文本]';
    else if (message.type === 'image') content = '[图片]';
    else if (message.type === 'audio') content = '[语音]';
    else content = '[新消息]';
    const avatar = resolveAvatarUrl(message.senderData?.avatar, app);

    if (app.globalData.globalNotification && app.globalData.globalNotification.show) {
      app.globalData.globalNotification.show({
        senderName,
        content,
        avatar,
        message,
        notificationType: message.groupId ? 'group' : 'private',
        groupId: message.groupId,
        orderId: message.orderId,
      });
    } else {
      wx.showToast({ title: `${senderName}: ${content}`, icon: 'none', duration: 2000 });
    }
  };
  wx.goEasy.im.on(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _notificationHandler);
  wx.goEasy.im.on(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _notificationHandler);
}

function detachGlobalListeners() {
  if (!wx.goEasy || !wx.goEasy.im) return;
  if (_convListener) {
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, _convListener);
    _convListener = null;
  }
  if (_privateListener) {
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _privateListener);
    _privateListener = null;
  }
  if (_groupListener) {
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _groupListener);
    _groupListener = null;
  }
  if (_notificationHandler) {
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _notificationHandler);
    wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _notificationHandler);
    _notificationHandler = null;
  }
  _listenersBoundForUser = null;
}

function disconnectGoEasy(app) {
  stopHeartbeat(app);
  detachGlobalListeners();
  if (wx.goEasy && wx.goEasy.disconnect) {
    wx.goEasy.disconnect({ onSuccess: () => {}, onFailed: () => {} });
  }
  wx.removeStorageSync('savedGoEasyConnection');
}

async function switchRoleAndReconnect(app, newRole) {
  disconnectGoEasy(app);
  app.globalData.currentRole = newRole;
  wx.setStorageSync('currentRole', newRole);
  if (app.globalData.primaryRole !== newRole && ['normal', 'dashou', 'shangjia'].includes(newRole)) {
    app.globalData.primaryRole = newRole;
    wx.setStorageSync('primaryRole', newRole);
  }
  startHeartbeat(app);
  await ensureConnection(app);
  return true;
}

function startHeartbeat(app) {
  stopHeartbeat(app);
  _heartbeatTimer = setInterval(() => {
    if (!wx.getStorageSync('uid')) return;
    if (isConnected()) {
      loadConversations(app);
    } else {
      ensureConnection(app);
    }
  }, 45000);
}

function stopHeartbeat(app) {
  if (_heartbeatTimer) {
    clearInterval(_heartbeatTimer);
    _heartbeatTimer = null;
  }
}

function initAppStateListener(app) {
  wx.onAppShow(() => {
    setTimeout(() => {
      if (!wx.getStorageSync('uid')) return;
      if (!isConnected()) {
        ensureConnection(app);
      } else {
        loadConversations(app);
        setTimeout(() => {
          const unread = (app.globalData.messageManager && app.globalData.messageManager.unreadTotal) || 0;
          updateTabBarBadge(app, unread);
        }, 300);
      }
    }, 200);
  });
}

function initNetworkListener(app) {
  wx.onNetworkStatusChange((res) => {
    if (res.isConnected) {
      setTimeout(() => ensureConnection(app), 1000);
    }
  });
}

module.exports = { initGlobalMessageSystem };
