// 聊天页面逻辑
const app = getApp();
const apiClient = require('../../../utils/api-client.js');
const wsManager = require('../../../utils/websocket-manager-v2.js');
const wsdiagnostic = require('../../../utils/websocket-diagnostic.js');
const mediaPicker = require('../../../utils/media-picker.js');
const voiceMessageManager = require('../../../utils/voice-message-manager.js');
const { initPageSystemInfo } = require('../../../utils/system-info-modern.js');
const imageCacheManager = require('../../../utils/image-cache-manager.js');

Page({
  data: {
    // 聊天基本信息
    conversationId: '',
    targetId: '',
    chatName: '',
    chatType: 0, // 0: 单聊, 1: 群聊
    isOnline: false,
    isNewConversation: false, // 是否为新会话

    // 消息数据
    messages: [],
    hasMore: true,
    lastMessageId: '',
    unreadCount: 0,
    loadingMessages: false, // 🔥 添加加载状态

    // 输入相关
    inputType: 'text', // 'text' 或 'voice'
    inputText: '',
    inputFocus: false,
    recording: false,
    isComposing: false, // 中文输入法状态

    // 面板状态
    showEmojiPanel: false,
    showMorePanel: false,
    showVoiceRecorder: false,

    // 滚动相关
    scrollTop: 0,
    scrollIntoView: '',
    showScrollToBottom: false, // 🔥 控制滚动到底部按钮显示

    // 常用表情
    commonEmojis: [
      '😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '🙃',
      '😉', '😊', '😇', '🥰', '😍', '🤩', '😘', '😗', '😚', '😙',
      '😋', '😛', '😜', '🤪', '😝', '🤑', '🤗', '🤭', '🤫', '🤔',
      '🤐', '🤨', '😐', '😑', '😶', '😏', '😒', '🙄', '😬', '🤥',
      '😌', '😔', '😪', '🤤', '😴', '😷', '🤒', '🤕', '🤢', '🤮',
      '🤧', '🥵', '🥶', '🥴', '😵', '🤯', '🤠', '🥳', '🥸', '😎',
      '🤓', '🧐', '😕', '😟', '🙁', '☹️', '😮', '😯', '😲', '😳',
      '🥺', '😦', '😧', '😨', '😰', '😥', '😢', '😭', '😱', '😖',
      '😣', '😞', '😓', '😩', '😫', '🥱', '😤', '😡', '😠', '🤬',
      '👋', '🤚', '🖐️', '✋', '🖖', '👌', '🤌', '🤏', '✌️', '🤞',
      '🤟', '🤘', '🤙', '👈', '👉', '👆', '🖕', '👇', '☝️', '👍',
      '👎', '👊', '✊', '🤛', '🤜', '👏', '🙌', '👐', '🤲', '🤝'
    ],

    // 用户信息
    userInfo: null,
    userAvatar: '',
    targetUserInfo: null, // 对方用户信息
    targetAvatar: '', // 对方头像

    // 消息相关
    messages: [],
    hasMore: true,
    lastMessageId: '',
    loadingMessages: false, // 🔥 添加加载状态字段

    // 系统适配信息
    systemInfo: {},
    statusBarHeight: 0,
    menuButtonHeight: 0,
    menuButtonTop: 0,
    navBarHeight: 0,
    windowHeight: 0,
    safeAreaBottom: 0,

    // 表情数据
    emojis: [
      '😀', '😃', '😄', '😁', '😆', '😅', '🤣', '😂', '🙂', '🙃',
      '😉', '😊', '😇', '🥰', '😍', '🤩', '😘', '😗', '😚', '😙',
      '😋', '😛', '😜', '🤪', '😝', '🤑', '🤗', '🤭', '🤫', '🤔'
    ],

    // 🔥 新增：组件状态（不影响现有功能）
    // 媒体预览组件
    mediaPreviewVisible: false,
    mediaPreviewList: [],
    currentMediaIndex: 0,

    // 消息操作菜单组件
    messageActionVisible: false,
    currentMessage: null,
    isOwnMessage: false,

    // @提醒选择器组件
    mentionSelectorVisible: false,

    // 加载状态
    isLoading: false,

    // 主题相关
    themeClass: 'theme-dark',
    isThemeTransitioning: false,
    // 主题切换径向遮罩
    showThemeOverlay: false,
    overlayPlaying: false,
    overlayTo: 'theme-light',
    overlayX: 0,
    overlayY: 0,
    overlayDiameter: 0,
    overlayLeft: 0,
    overlayTop: 0
  },

  async onLoad(options) {
    console.log('聊天页面加载:', options);

    // 显示加载状态
    this.setData({ isLoading: true });

    // 初始化系统信息（同步，立即完成）
    this.initSystemInfo();

    // 🔥 并行执行用户信息初始化和聊天信息初始化
    const userInfoPromise = this.initUserInfo();
    const chatInfoPromise = this.initChatInfo(options);

    // 等待用户信息完成（消息加载需要用户信息）
    await userInfoPromise;

    // 初始化WebSocket（不等待）
    this.initWebSocket();

    // 等待聊天信息初始化完成
    await chatInfoPromise;

    // 隐藏加载状态
    this.setData({ isLoading: false });
  },

  onShow: function () {
    // 初始化主题
    const savedTheme = wx.getStorageSync('theme') || 'theme-dark';
    this.setData({ themeClass: savedTheme });

    // 页面显示时连接WebSocket
    if (wsManager && !wsManager.isConnected) {
      wsManager.connect();
    }

    // 🔥 进入聊天页面时自动标记所有消息已读
    this.markAllMessagesRead();
  },

  onHide: function () {
    // 页面隐藏时可以保持WebSocket连接，因为其他页面可能需要
  },

  onUnload: function () {
    // 页面卸载时清理WebSocket监听器
    if (wsManager) {
      wsManager.off('new_message');
      wsManager.off('message_status');
      wsManager.off('message_recalled');
    }
  },

  // 初始化系统信息
  initSystemInfo() {
    const pageSystemInfo = initPageSystemInfo();

    this.setData({
      systemInfo: pageSystemInfo.systemInfo,
      statusBarHeight: pageSystemInfo.statusBarHeight,
      menuButtonHeight: pageSystemInfo.menuButtonHeight,
      menuButtonTop: pageSystemInfo.menuButtonTop,
      navBarHeight: pageSystemInfo.navBarHeight,
      windowHeight: pageSystemInfo.windowHeight,
      safeAreaBottom: pageSystemInfo.safeAreaBottom
    });
  },

  // 初始化聊天信息 - 修正：从API获取正确的conversationId
  async initChatInfo(options) {
    const inputConversationId = options.conversationId || '';
    const targetId = options.targetId || '';
    const chatName = decodeURIComponent(options.name || '聊天');
    const chatType = parseInt(options.chatType || 0);

    // 临时设置基本信息
    this.setData({
      targetId,
      chatName,
      chatType,
      conversationId: inputConversationId // 临时设置，等API返回正确的
    });

    // 🔥 动态设置导航栏标题为用户昵称
    wx.setNavigationBarTitle({
      title: chatName
    });

    console.log('聊天信息初始化:', {
      inputConversationId,
      targetId,
      chatName,
      chatType
    });

    // 🔥 从API获取正确的conversationId
    await this.getCorrectConversationId(targetId, chatType);
  },

  // 从API获取正确的conversationId
  async getCorrectConversationId(targetId, chatType) {
    try {
      console.log('🔍 从API获取正确的conversationId...');

      // 调用conversations接口获取会话列表
      const response = await apiClient.getConversations();

      if (response && response.code === 0) {
        const conversations = response.data || [];
        console.log('✅ 获取到会话列表:', conversations.length, '个');

        // 🔥 调试：显示所有会话信息
        console.log('🔍 调试会话查找:');
        console.log('- 目标targetId:', targetId);
        console.log('- 聊天类型chatType:', chatType);
        console.log('- 会话列表:', conversations.map(conv => ({
          id: conv.id || conv.conversationId,
          targetId: conv.targetId,
          type: conv.type,
          targetName: conv.targetName
        })));

        // 查找与目标用户的会话
        let targetConversation = null;

        if (chatType === 0) {
          // 单聊：查找targetId匹配的会话
          targetConversation = conversations.find(conv =>
            conv.type === 0 && conv.targetId === targetId
          );
          console.log('🔍 单聊查找结果:', targetConversation);
        } else {
          // 群聊：查找群ID匹配的会话
          targetConversation = conversations.find(conv =>
            conv.type === 1 && conv.targetId === targetId
          );
          console.log('🔍 群聊查找结果:', targetConversation);
        }

        // 🔥 检查会话ID字段
        const conversationId = targetConversation?.id || targetConversation?.conversationId;
        console.log('🔍 会话ID检查:', {
          hasConversation: !!targetConversation,
          id: targetConversation?.id,
          conversationId: targetConversation?.conversationId,
          finalId: conversationId
        });

        if (targetConversation && conversationId) {
          // 🔥 找到了现有会话，使用API返回的会话ID
          console.log('✅ 找到现有会话:', conversationId);

          this.setData({
            conversationId: conversationId,
            // 同时更新其他会话信息
            chatName: targetConversation.targetName || this.data.chatName,
            unreadCount: targetConversation.unreadCount || 0,
            isNewConversation: false
          });

          // 🔥 并行获取对方用户信息和加载消息
          if (chatType === 0) {
            // 不等待头像加载完成，立即开始加载消息
            this.loadTargetUserInfo(targetId).catch(error => {
              console.error('获取对方用户信息失败:', error);
            });
          }

          // 立即加载消息，不等待头像
          this.loadMessages();

        } else {
          // 🔥 没有找到现有会话，这是新会话，不设置conversationId
          // 等发送第一条消息时，后端会创建会话并返回会话ID
          console.log('⚠️ 未找到现有会话，这是新会话');

          this.setData({
            conversationId: '', // 🔥 新会话不设置ID
            isNewConversation: true,
            messages: [],
            hasMore: false
          });

          // 🔥 获取对方用户信息（包括头像）- 异步执行
          if (chatType === 0) {
            this.loadTargetUserInfo(targetId).catch(error => {
              console.error('获取对方用户信息失败:', error);
            });
          }

          console.log('🆕 新会话，等待发送消息时创建');
        }

      } else {
        throw new Error(response?.message || '获取会话列表失败');
      }

    } catch (error) {
      console.error('❌ 获取conversationId失败:', error);

      // 🔥 对于新会话，不设置conversationId，等后端创建
      this.setData({
        conversationId: '',
        isNewConversation: true,
        messages: [],
        hasMore: false
      });

      // 🔥 获取对方用户信息（包括头像）
      if (this.data.chatType === 0) {
        await this.loadTargetUserInfo(this.data.targetId);
      }

      console.log('🔄 降级处理：新会话模式');
    }
  },

  // 🔥 新增：获取对方用户信息（包括头像）
  async loadTargetUserInfo(targetId) {
    try {
      console.log('👤 开始获取对方用户信息:', targetId);

      // 调用好友详情API获取用户信息
      const response = await apiClient.getFriendDetail(targetId);

      if (response && response.code === 0) {
        const userInfo = response.data;
        console.log('✅ 获取到对方用户信息:', userInfo);

        // 设置对方头像
        const targetAvatar = userInfo.avatar || '';
        console.log('👤 设置对方头像:', targetAvatar);

        // 🔥 先设置用户信息，头像缓存异步执行
        this.setData({
          targetUserInfo: userInfo,
          targetAvatar: targetAvatar // 先使用原始URL
        });

        // 🔥 异步缓存头像，不阻塞UI
        imageCacheManager.cacheAvatar(targetAvatar).then(cachedAvatar => {
          this.setData({
            targetAvatar: cachedAvatar
          });
          console.log('✅ 对方头像缓存完成');
        }).catch(error => {
          console.error('❌ 对方头像缓存失败:', error);
        });

      } else {
        console.warn('⚠️ 获取对方用户信息失败:', response?.message);
      }

    } catch (error) {
      console.error('❌ 获取对方用户信息异常:', error);
    }
  },

  // 初始化用户信息
  async initUserInfo() {
    // 先尝试从全局获取
    let userInfo = app.globalData.userInfo;

    // 如果全局没有，尝试从本地存储获取
    if (!userInfo || !userInfo.token) {
      try {
        const storedUserInfo = wx.getStorageSync('userInfo');
        if (storedUserInfo && storedUserInfo.token) {
          userInfo = storedUserInfo;
          // 更新全局数据
          app.globalData.userInfo = userInfo;
          app.globalData.isLoggedIn = true;
          console.log('从本地存储恢复用户信息');
        }
      } catch (error) {
        console.error('从本地存储获取用户信息失败:', error);
      }
    }

    // 确保有用户信息
    if (userInfo && userInfo.token) {
      // 正确获取用户头像
      const userAvatar = userInfo.user?.avatar || userInfo.avatar || '';
      console.log('👤 设置用户头像:', userAvatar);
      console.log('👤 用户信息结构:', userInfo);

      // 🔥 先设置用户信息，头像缓存异步执行
      this.setData({
        userInfo: userInfo,
        userAvatar: userAvatar // 先使用原始URL
      });

      // 🔥 异步缓存头像，不阻塞UI
      imageCacheManager.cacheAvatar(userAvatar).then(cachedAvatar => {
        this.setData({
          userAvatar: cachedAvatar
        });
        console.log('✅ 用户头像缓存完成');
      }).catch(error => {
        console.error('❌ 用户头像缓存失败:', error);
      });
      console.log('用户信息初始化成功:', userInfo.user?.customId || userInfo.customId);
    } else {
      console.error('用户信息初始化失败，跳转到登录页');
      wx.reLaunch({
        url: '/pages/login/login'
      });
    }
  },

  // 初始化WebSocket
  initWebSocket() {
    console.log('🔌 初始化WebSocket连接...');

    // 🔥 禁用WebSocket诊断，避免创建额外连接
    // this.runWebSocketDiagnostic();

    // 获取用户token
    const token = this.data.userInfo?.token || wx.getStorageSync('token');
    if (!token) {
      console.error('❌ 用户token不存在，无法连接WebSocket');
      return;
    }

    // 设置WebSocket管理器的token
    wsManager.setToken(token);

    // 连接WebSocket
    wsManager.connect().then(() => {
      console.log('✅ WebSocket连接成功');

      // 监听新消息
      wsManager.on('new_message', (messageData) => {
        console.log('📨 收到新消息:', messageData);
        this.handleNewMessage(messageData);
      });

      // 监听消息状态更新（兼容 data 包裹与直传两种格式）
      wsManager.on('message_status', (statusMsg) => {
        const payload = statusMsg && statusMsg.data ? statusMsg.data : statusMsg;
        console.log('📊 消息状态更新:', payload);
        this.updateMessageStatus(payload);
      });

      // 监听服务端发送回执，使用clientTempId替换临时消息
      wsManager.on('message_sent', async (sentData) => {
        try {
          const srv = sentData?.data || {};
          const formatted = await this.formatMessage(srv);

          let replaced = false;
          const newMessages = this.data.messages.map(msg => {
            if (!replaced && msg.isSelf && (msg.deliveryStatus === 'sending' || msg.deliveryStatus === 'uploading')) {
              const matchByTempId = srv.clientTempId && msg.messageId === srv.clientTempId;
              if (matchByTempId) {
                replaced = true;
                return { ...formatted, deliveryStatus: 'sent' };
              }
            }
            return msg;
          });

          this.setMessagesWithDate(replaced ? newMessages : this.data.messages.concat([{ ...formatted, deliveryStatus: 'sent' }]));
          setTimeout(() => this.scrollToBottom(), 100);
        } catch (e) {
          console.error('❌ 处理message_sent回执失败:', e);
        }
      });

      // 监听服务端发送回执，用服务端消息替换临时消息，避免重复
      wsManager.on('message_sent', async (sentData) => {
        try {
          // sentData.data 内应包含服务端消息详情
          const srv = sentData?.data || {};
          const formatted = await this.formatMessage(srv);

          // 查找最近一条同类型、自己发送、且仍为sending/上传完成的临时消息进行替换
          let replaced = false;
          const newMessages = this.data.messages.map(msg => {
            if (!replaced && msg.isSelf && (msg.msgType === formatted.msgType) && (msg.deliveryStatus === 'sending' || msg.deliveryStatus === 'uploading')) {
              // 文件/图片等有可能通过content.url对齐
              const sameUrl = (typeof msg.content === 'object' ? msg.content.url : msg.content) === (typeof formatted.content === 'object' ? formatted.content.url : formatted.content);
              // 近5分钟内的临时消息
              const closeTime = Math.abs((msg.timestamp || 0) - (formatted.timestamp || 0)) < 5 * 60 * 1000;
              if (sameUrl || closeTime) {
                replaced = true;
                return { ...formatted, deliveryStatus: 'sent' };
              }
            }
            return msg;
          });

          // 如果未替换，直接追加（兜底）
          this.setMessagesWithDate(replaced ? newMessages : newMessages.concat([{ ...formatted, deliveryStatus: 'sent' }]));

          // 滚动到底
          setTimeout(() => this.scrollToBottom(), 100);
        } catch (e) {
          console.error('❌ 处理message_sent回执失败:', e);
        }
      });

      // 监听消息撤回
      wsManager.on('message_recalled', (recallData) => {
        console.log('↩️ 收到消息撤回通知:', recallData);
        this.handleMessageRecalled(recallData);
      });

      // 监听连接状态变化
      wsManager.on('connection_status', (status) => {
        console.log('🔌 WebSocket连接状态变化:', status);
        this.setData({ wsConnected: status.connected });
      });

    }).catch((error) => {
      console.error('❌ WebSocket连接失败:', error);
      this.setData({ wsConnected: false });
    });
  },

  // 🔥 运行WebSocket连接全面诊断
  async runWebSocketDiagnostic() {
    console.log('🔍 开始WebSocket连接全面诊断...');

    try {
      const results = await wsdiagnostic.runFullDiagnostic();

      // 检查诊断结果
      const wsResult = results.find(r => r.test === 'WebSocket连接');
      if (wsResult && wsResult.status === 'success') {
        console.log('✅ WebSocket连接诊断通过，可以正常连接');
      } else {
        console.error('❌ WebSocket连接诊断失败，请查看上方的详细报告');
      }

    } catch (error) {
      console.error('❌ WebSocket诊断异常:', error);
    }
  },

  // 处理新消息
  async handleNewMessage(messageData) {
    console.log('🔍 收到新消息，开始处理:', messageData);
    console.log('🔍 当前会话ID:', this.data.conversationId);
    console.log('🔍 消息会话ID:', messageData.conversationId);

    // 检查是否是当前会话的消息
    if (messageData.conversationId !== this.data.conversationId) {
      console.log('⚠️ 消息会话ID不匹配，跳过处理');
      console.log('⚠️ 期望:', this.data.conversationId);
      console.log('⚠️ 实际:', messageData.conversationId);
      return;
    }

    console.log('✅ 消息会话ID匹配，开始格式化消息');
    const newMessage = await this.formatMessage(messageData);
    console.log('✅ 消息格式化完成:', newMessage);

  const messages = [...this.data.messages, newMessage];
  this.setMessagesWithDate(messages);

    console.log('✅ 消息已添加到列表，当前消息数:', messages.length);

    // 🔥 确保新消息后滚动到底部
    setTimeout(() => {
      this.scrollToBottom();
    }, 100);

    // 发送已读回执
    this.sendReadReceipt(messageData.messageId);
  },

  // 更新消息状态（兼容多格式payload）
  updateMessageStatus(statusData) {
    try {
      const payload = statusData || {};
      const messageId = payload.messageId || payload.id || payload.msgId;
      // 可能是 data.status 或 payload.status 或 payload.state
      const rawStatus = payload.status !== undefined ? payload.status : (payload.state !== undefined ? payload.state : payload.deliveryStatus);

      // 将后端状态统一映射为前端 deliveryStatus
      let mapped = this.convertStatus(rawStatus);
      // 显式错误态
      if (rawStatus === 'error' || rawStatus === 'fail' || rawStatus === 'failed') {
        mapped = 'failed';
      }

      if (!messageId) {
        console.warn('⚠️ message_status 缺少 messageId，忽略:', payload);
        return;
      }

      const messages = this.data.messages.map(msg => {
        if (msg.messageId === messageId) {
          // 仅对自己发送的消息展示状态；他人消息不显示 deliveryStatus
          if (msg.isSelf) {
            return { ...msg, deliveryStatus: mapped };
          }
        }
        return msg;
      });

      this.setData({ messages });
    } catch (e) {
      console.error('❌ 更新消息状态失败:', e, statusData);
    }
  },

  // 处理收到的消息撤回通知
  handleMessageRecalled(recallData) {
    const { messageId, senderName } = recallData;
  const messages = this.data.messages.map(msg => {
      if (msg.messageId === messageId) {
        return {
          ...msg,
          isRecalled: true,
          content: msg.isSelf ? '你撤回了一条消息' : `${senderName || '对方'}撤回了一条消息`,
          originalContent: msg.content, // 保存原始内容
          recallTime: Date.now(),
          msgType: 'system' // 改为系统消息样式
        };
      }
      return msg;
    });
  this.setMessagesWithDate(messages);
  },

  // 加载消息 - 使用正确的API接口和分页逻辑
  async loadMessages(isLoadMore = false) {
    try {
      console.log('📨 加载聊天消息:', {
        isLoadMore,
        targetId: this.data.targetId,
        chatType: this.data.chatType,
        conversationId: this.data.conversationId,
        lastMessageId: this.data.lastMessageId
      });

      // 检查必要参数
      if (!this.data.targetId) {
        console.log('⚠️ 缺少targetId，无法加载消息');
        return;
      }

      // 🔥 避免重复请求
      if (this.data.loadingMessages) {
        console.log('⚠️ 消息正在加载中，跳过重复请求');
        console.log('🔍 当前loadingMessages状态:', this.data.loadingMessages);
        return;
      }

      // 设置加载状态
      this.setData({ loadingMessages: true });
      console.log('🔧 loadMessages设置loadingMessages: true');

      // 🔥 使用正确的API接口：GET /api/v1/chat/history
      const params = {
        receiverId: this.data.targetId,
        chatType: this.data.chatType,
        limit: 20,
        direction: 'before'
      };

      // 如果是加载更多，添加lastMsgId参数
      if (isLoadMore && this.data.lastMessageId) {
        params.lastMsgId = this.data.lastMessageId;
      }

      console.log('📡 API请求参数:', params);

      // 调用API
      const response = await apiClient.get(`/api/v1/chat/history`, params);

      if (response && response.code === 0) {
        const newMessages = response.data || [];
        console.log('✅ 获取到消息:', newMessages.length, '条');

        // 🔥 异步格式化消息（包括头像缓存）
        const formattedMessages = await Promise.all(newMessages.map(msg => this.formatMessage(msg)));

        // 🔥 判断是否是首次加载
        const isFirstLoad = this.data.messages.length === 0;

        // 🔥 修正hasMore逻辑：如果返回的消息数等于请求数，说明可能还有更多
        const hasMoreMessages = newMessages.length === 20;
        console.log('📊 hasMore逻辑:', {
          returnedCount: newMessages.length,
          requestedLimit: 20,
          hasMoreMessages,
          isFirstLoad
        });

        // 🔥 去重处理：避免重复消息
        const existingIds = new Set(this.data.messages.map(msg => msg.messageId));
        const uniqueNewMessages = formattedMessages.filter(msg => !existingIds.has(msg.messageId));
        console.log('🔄 去重后新消息数量:', uniqueNewMessages.length, '原数量:', formattedMessages.length);

        // 🔥 修复消息排序：确保消息按时间正序排列（旧消息在前，新消息在后）
        let sortedMessages;
        if (isFirstLoad) {
          // 首次加载：直接使用API返回的消息，按时间排序
          sortedMessages = uniqueNewMessages.sort((a, b) => a.timestamp - b.timestamp);
          console.log('📅 首次加载，按时间排序消息');
        } else {
          // 加载更多历史消息：新加载的历史消息应该插入到现有消息前面
          const allMessages = uniqueNewMessages.concat(this.data.messages);
          sortedMessages = allMessages.sort((a, b) => a.timestamp - b.timestamp);
          console.log('📅 加载更多消息，重新排序所有消息');
        }

        // 🔥 更新lastMessageId：使用最早的消息ID（用于下次分页）
        const earliestMessage = newMessages.length > 0 ? newMessages[newMessages.length - 1] : null;
        const newLastMessageId = earliestMessage ? (earliestMessage.id || earliestMessage.messageId) : '';

        const annotated = this.recomputeDateDividers(sortedMessages);
        this.setData({
          messages: annotated,
          hasMore: hasMoreMessages,
          lastMessageId: newLastMessageId,
          loadingMessages: false
        });
        console.log('🔧 重置loadingMessages: false');

        console.log('✅ 消息加载完成:', {
          totalMessages: sortedMessages.length,
          hasMore: hasMoreMessages,
          lastMessageId: newLastMessageId
        });

        // 🔥 首次加载时自动滚动到底部
        if (isFirstLoad && this.data.messages.length > 0) {
          console.log('📍 首次加载，自动滚动到最新消息');
          setTimeout(() => {
            this.scrollToBottom();
          }, 100);
        }
      } else {
        console.warn('⚠️ 获取消息响应异常:', response);
        this.setData({
          hasMore: false,
          loadingMessages: false
        });
        console.log('🔧 异常情况重置loadingMessages: false');
      }
    } catch (error) {
      console.error('❌ 加载消息失败:', error);
      this.setData({
        hasMore: false,
        loadingMessages: false
      });
      console.log('🔧 错误情况重置loadingMessages: false');
      wx.showToast({
        title: '加载消息失败',
        icon: 'none'
      });
    }
  },

  // 格式化消息 - 适配接口文档的数据结构，特殊处理图片消息
  async formatMessage(msgData) {
    // 🔍 调试：查看消息数据中的头像字段
    console.log('🔍 消息数据字段检查:', {
      senderAvatar: msgData.senderAvatar,
      avatar: msgData.avatar,
      userAvatar: msgData.userAvatar,
      targetAvatar: msgData.targetAvatar,
      fromAvatar: msgData.fromAvatar,
      allFields: Object.keys(msgData)
    });

    // 🔥 多重获取当前用户ID，确保能正确获取
    let currentUserId = this.data.userInfo?.user?.customId || this.data.userInfo?.customId || '';

    // 🔥 如果从data中获取不到，尝试从全局获取
    if (!currentUserId) {
      const app = getApp();
      const globalUserInfo = app.globalData.userInfo;
      currentUserId = globalUserInfo?.user?.customId || globalUserInfo?.customId || '';
      console.log('🔍 从全局获取用户ID:', currentUserId);
    }

    // 🔥 如果还是获取不到，尝试从本地存储获取
    if (!currentUserId) {
      try {
        const storedUserInfo = wx.getStorageSync('userInfo');
        currentUserId = storedUserInfo?.user?.customId || storedUserInfo?.customId || '';
        console.log('🔍 从本地存储获取用户ID:', currentUserId);
      } catch (error) {
        console.error('从本地存储获取用户ID失败:', error);
      }
    }

    // 适配接口文档中的字段名
    const senderId = msgData.senderId || msgData.senderCustomId;
    const messageId = msgData.id || msgData.messageId;
    const isSelf = senderId === currentUserId;

    // 🔥 调试：检查发送者判断逻辑
    console.log('🔍 发送者判断调试:', {
      currentUserId,
      senderId,
      messageId,
      isSelf,
      userInfo: this.data.userInfo,
      msgData: {
        senderId: msgData.senderId,
        senderCustomId: msgData.senderCustomId,
        id: msgData.id,
        messageId: msgData.messageId
      }
    });

    // 🔥 智能消息类型识别：如果msgType是1但内容是文字，自动识别为文字消息
    let msgType = this.convertMsgType(msgData.msgType);
    if (msgType === 'image' && typeof msgData.content === 'string' &&
      !msgData.content.startsWith('http') && !msgData.content.startsWith('data:')) {
      console.log('🔧 检测到错误的图片类型，自动修正为文字消息');
      msgType = 'text';
    }

    // 🔥 特殊处理媒体消息内容
    let processedContent = msgData.content;
    if (msgType === 'image') {
      processedContent = await this.parseImageContent(msgData.content);
      console.log('🖼️ 图片消息处理结果:', processedContent);
    } else if (msgType === 'voice') {
      processedContent = this.parseVoiceContent(msgData.content);
      console.log('🎤 语音消息处理结果:', processedContent);
    } else if (msgType === 'file') {
      processedContent = this.parseFileContent(msgData.content);
      console.log('📄 文件消息处理结果:', processedContent);
    } else if (msgType === 'location') {
      processedContent = this.parseLocationContent(msgData.content);
      console.log('📍 位置消息处理结果:', processedContent);
    }

    // 🔥 统一时间戳字段，确保排序正确
    const timestamp = new Date(msgData.sendTime).getTime();

    // 🔥 先使用默认头像，异步更新
    let senderAvatar = '';
    if (isSelf) {
      senderAvatar = this.data.userAvatar || '';
    } else {
      senderAvatar = this.data.targetAvatar || '';
    }

    // 🔥 异步提取和缓存头像
    this.extractSenderAvatar(msgData, isSelf).then(cachedAvatar => {
      // 更新对应消息的头像
      const messages = this.data.messages.map(msg => {
        if (msg.messageId === messageId) {
          return { ...msg, senderAvatar: cachedAvatar };
        }
        return msg;
      });
      this.setData({ messages });
    }).catch(error => {
      console.error('提取头像失败:', error);
    });

    const baseMessage = {
      messageId: messageId,
      senderId: senderId,
      targetId: msgData.receiverId || msgData.targetId,
      content: processedContent, // 使用处理后的内容
      msgType: msgType,
      sendTime: timestamp, // 确保是时间戳格式
      timestamp: timestamp, // 🔥 添加timestamp字段用于排序
      isSelf: isSelf,
      senderName: msgData.senderName || (isSelf ? '我' : '对方'),
      senderAvatar: senderAvatar, // 🔥 使用异步提取的头像
      deliveryStatus: this.convertStatus(msgData.status), // 转换状态
      bubbleTime: this.formatBubbleTime(timestamp)
    };

    // 文件消息补充文件展示字段，便于WXML直接使用
    if (msgType === 'file') {
      return {
        ...baseMessage,
        fileName: processedContent.fileName || msgData.fileName || '',
        fileSize: this.formatFileSize(processedContent.fileSize || msgData.fileSize || 0),
        fileType: processedContent.fileType || msgData.fileType || ''
      };
    }

    // 🔥 位置消息：为兼容旧渲染逻辑，将名称/地址/经纬度同步到根级字段，避免显示默认“位置”
    if (msgType === 'location') {
      return {
        ...baseMessage,
        locationName: processedContent?.locationName || msgData.locationName || '位置',
        locationAddress: processedContent?.address || msgData.locationAddress || '',
        latitude: processedContent?.latitude,
        longitude: processedContent?.longitude
      };
    }

    return baseMessage;
  },

  // 🔥 解析语音内容：兼容字符串URL、JSON字符串、对象三种情况
  parseVoiceContent(content) {
    try {
      if (!content) return { url: '' };

      // 如果已经是对象且包含url，直接返回
      if (typeof content === 'object' && content !== null) {
        if (content.url) return content;
        // 兼容部分后端字段
        if (content.voiceUrl) return { url: content.voiceUrl, duration: content.duration };
        // 无法识别，返回空URL，避免崩溃
        return { url: '' };
      }

      // 如果是字符串，尝试JSON解析
      if (typeof content === 'string') {
        const trimmed = content.trim();
        if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
          try {
            const obj = JSON.parse(trimmed);
            if (obj && obj.url) return obj;
            // 兼容 file_url 字段
            if (obj && obj.file_url) return { url: obj.file_url, duration: obj.duration };
          } catch (e) {
            // 继续按URL兜底
          }
        }
        // 直接当作URL使用
        return { url: trimmed };
      }

      return { url: '' };
    } catch (error) {
      console.error('❌ 解析语音内容失败:', error, content);
      return { url: '' };
    }
  },

  // 🔥 解析文件内容：兼容URL字符串、JSON字符串、对象
  parseFileContent(content) {
    try {
      if (!content) return { url: '', fileName: '', fileSize: 0 };

      // 对象格式
      if (typeof content === 'object' && content !== null) {
        const url = content.url || content.file_url || content.fileUrl || '';
        const fileName = content.fileName || content.file_name || '';
        const fileSize = content.fileSize || content.file_size || 0;
        const fileType = content.fileType || content.file_type || '';
        return { url, fileName, fileSize, fileType };
      }

      // JSON字符串
      if (typeof content === 'string') {
        const trimmed = content.trim();
        if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
          try {
            const obj = JSON.parse(trimmed);
            const url = obj.url || obj.file_url || obj.fileUrl || '';
            const fileName = obj.fileName || obj.file_name || '';
            const fileSize = obj.fileSize || obj.file_size || 0;
            const fileType = obj.fileType || obj.file_type || '';
            return { url, fileName, fileSize, fileType };
          } catch (e) {
            // fallthrough to plain URL
          }
        }
        // 纯URL
        return { url: trimmed, fileName: '', fileSize: 0 };
      }

      return { url: '', fileName: '', fileSize: 0 };
    } catch (error) {
      console.error('❌ 解析文件内容失败:', error, content);
      return { url: '', fileName: '', fileSize: 0 };
    }
  },

  // 🔥 解析位置内容：兼容JSON字符串或对象，统一为 {latitude, longitude, address, locationName}
  parseLocationContent(content) {
    try {
      if (!content) return null;
      let obj = content;
      if (typeof content === 'string') {
        const trimmed = content.trim();
        if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
          try {
            obj = JSON.parse(trimmed);
          } catch (e) {
            return null;
          }
        } else {
          // 非JSON字符串，无法解析
          return null;
        }
      }
      const lat = obj.latitude ?? obj.lat;
      const lng = obj.longitude ?? obj.lng;
      const address = obj.address || '';
      const locationName = obj.locationName || obj.name || '位置';
      if (lat == null || lng == null) return null;
      return { latitude: Number(lat), longitude: Number(lng), address, locationName };
    } catch (err) {
      console.error('❌ 解析位置内容失败:', err, content);
      return null;
    }
  },

  // 🔥 提取发送者头像 - 兼容多种字段名，支持缓存
  async extractSenderAvatar(msgData, isSelf) {
    console.log('🔍 开始提取头像，isSelf:', isSelf, 'msgData:', msgData);

    // 如果是自己的消息，使用当前用户头像（已缓存）
    if (isSelf) {
      const userAvatar = this.data.userAvatar || '';
      console.log('👤 使用当前用户头像:', userAvatar);
      return userAvatar;
    }

    // 🔥 如果是对方的消息，优先使用获取到的对方头像（已缓存）
    const targetAvatar = this.data.targetAvatar || '';
    if (targetAvatar) {
      console.log('👥 使用获取到的对方头像:', targetAvatar);
      return targetAvatar;
    }

    // 🔥 尝试多种可能的头像字段名，兼容不同API返回格式
    const possibleAvatarFields = [
      'senderAvatar',      // 标准字段
      'avatar',            // 简化字段
      'userAvatar',        // 用户头像
      'targetAvatar',      // 目标头像（与消息列表一致）
      'fromAvatar',        // 发送者头像
      'user.avatar',       // 嵌套用户对象
      'sender.avatar'      // 嵌套发送者对象
    ];

    console.log('🔍 尝试查找头像字段，可能的字段:', possibleAvatarFields);

    for (const field of possibleAvatarFields) {
      let value;

      // 处理嵌套字段
      if (field.includes('.')) {
        const parts = field.split('.');
        value = msgData;
        for (const part of parts) {
          value = value?.[part];
          if (!value) break;
        }
      } else {
        value = msgData[field];
      }

      console.log(`🔍 检查字段 ${field}:`, value);

      // 如果找到有效的头像URL，缓存并返回
      if (value && typeof value === 'string' && value.length > 0) {
        console.log(`🎯 找到头像字段 ${field}:`, value);
        // 🔥 缓存头像
        const cachedAvatar = await imageCacheManager.cacheAvatar(value);
        return cachedAvatar;
      }
    }

    console.log('⚠️ 未找到有效的头像字段，消息数据:', msgData);
    console.log('⚠️ 消息数据的所有字段:', Object.keys(msgData));
    return ''; // 没有找到头像，返回空字符串
  },

  // 转换消息类型（根据后端实际常量定义）
  convertMsgType(apiMsgType) {
    // 🔥 根据API文档修正映射
    const typeMap = {
      0: 'text',      // 文字消息
      1: 'image',     // 图片消息
      2: 'voice',     // 语音消息
      3: 'video',     // 视频消息
      4: 'file',      // 文件消息
      5: 'location',  // 位置消息
      6: 'emoji',     // 表情消息
      99: 'system'    // 系统消息
    };

    console.log('🔄 转换msgType:', apiMsgType, '->', typeMap[apiMsgType] || 'text');
    return typeMap[apiMsgType] || 'text';
  },

  // 转换消息状态（映射为前端deliveryStatus：sending/sent/delivered/read/...）
  convertStatus(apiStatus) {
    // 后端状态（根据文档）：0=未读(unread)，1=已读(read)，2=撤回(recalled)，3=删除(deleted)
    // 前端 deliveryStatus 需要的是 sent/delivered/read 等
    const normalize = (val) => {
      if (val === undefined || val === null) return 'sent';
      // 数字状态
      if (typeof val === 'number') {
        if (val === 1) return 'read';
        if (val === 0) return 'delivered';
        if (val === 2) return 'recalled';
        if (val === 3) return 'deleted';
        return 'sent';
      }
      // 字符串状态
      const s = String(val).toLowerCase();
      if (s === 'read') return 'read';
      if (s === 'unread') return 'delivered';
      if (s === 'delivered' || s === 'sent') return s;
      if (s === 'recalled' || s === 'deleted' || s === 'failed') return s;
      return 'sent';
    };

    const mapped = normalize(apiStatus);
    console.log('🔄 状态映射 convertStatus:', apiStatus, '->', mapped);
    return mapped;
  },

  // 🔥 新增：解析图片内容（支持OSS URL和Base64两种格式），支持缓存
  async parseImageContent(content) {
    console.log('🖼️ 解析图片内容 - 完整内容:', content);
    console.log('🖼️ 内容类型:', typeof content);
    console.log('🖼️ 内容长度:', content?.length);

    if (!content) {
      console.log('⚠️ 图片内容为空');
      return { type: 'url', url: '' };
    }

    // 🔥 检查是否是错误的文本内容（应该是图片URL）
    if (typeof content === 'string' && !content.startsWith('http') && !content.startsWith('data:')) {
      console.error('❌ 图片消息包含无效内容，可能是后端数据错误:', content);
      return {
        type: 'error',
        url: '',
        error: '图片内容无效',
        originalContent: content
      };
    }

    // 检查是否是Base64格式
    if (content.startsWith('data:image/')) {
      console.log('📷 检测到Base64图片格式');
      return {
        type: 'base64',
        url: content // Base64数据可以直接作为src使用
      };
    }

    // 检查是否是OSS URL格式
    if (content.startsWith('http://') || content.startsWith('https://')) {
      console.log('🌐 检测到OSS URL图片格式');
      // 🔥 缓存聊天图片
      const cachedUrl = await imageCacheManager.preloadImage(content);
      return {
        type: 'url',
        url: cachedUrl
      };
    }

    // 尝试解析JSON格式（可能包含文件信息）
    try {
      const parsed = JSON.parse(content);
      if (parsed.file_url) {
        console.log('📄 检测到JSON图片格式');
        // 🔥 缓存聊天图片
        const cachedUrl = await imageCacheManager.preloadImage(parsed.file_url);
        return {
          type: 'url',
          url: cachedUrl,
          fileName: parsed.file_name,
          fileSize: parsed.file_size,
          fileType: parsed.file_type
        };
      }
    } catch (e) {
      console.log('⚠️ JSON解析失败，当作普通URL处理');
    }

    // 默认当作URL处理
    return {
      type: 'url',
      url: content
    };
  },

  // 判断是否显示时间
  shouldShowTime(timestamp) {
    // 简单实现：每5分钟显示一次时间
    const lastMessage = this.data.messages[this.data.messages.length - 1];
    if (!lastMessage) return true;

    const diff = timestamp - lastMessage.sendTime;
    return diff > 5 * 60 * 1000; // 5分钟
  },

  // 气泡内时间 HH:mm
  formatBubbleTime(timestamp) {
    const d = new Date(timestamp);
    const hh = d.getHours().toString().padStart(2, '0');
    const mm = d.getMinutes().toString().padStart(2, '0');
    return `${hh}:${mm}`;
  },

  // 日期标签：今天/昨天/YYYY/MM/DD
  formatDateLabel(timestamp) {
    const d = new Date(timestamp);
    const today = new Date();
    const yst = new Date();
    yst.setDate(today.getDate() - 1);
    const sameDay = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
    if (sameDay(d, today)) return '今天';
    if (sameDay(d, yst)) return '昨天';
    const y = d.getFullYear();
    const m = (d.getMonth() + 1).toString().padStart(2, '0');
    const day = d.getDate().toString().padStart(2, '0');
    return `${y}/${m}/${day}`;
  },

  // 重新计算日期分隔（仅按日期），返回新数组
  recomputeDateDividers(list) {
    if (!Array.isArray(list)) return [];
    let lastDateKey = '';
    return list.map((m, idx) => {
      const d = new Date(m.timestamp || m.sendTime || 0);
      const key = `${d.getFullYear()}-${d.getMonth()}-${d.getDate()}`;
      const show = key !== lastDateKey;
      const dateText = this.formatDateLabel(d.getTime());
      lastDateKey = key;
      return { ...m, showDateDivider: show, dateText, bubbleTime: m.bubbleTime || this.formatBubbleTime(m.timestamp || m.sendTime || Date.now()) };
    });
  },

  // 便捷设置消息并自动打日期分隔
  setMessagesWithDate(messages) {
    const annotated = this.recomputeDateDividers(messages);
    this.setData({ messages: annotated });
  },

  // 输入变化
  onInputChange(e) {
    const inputText = e.detail.value;
    this.setData({ inputText });

    // 如果正在输入中文，不要发送输入状态
    if (!this.data.isComposing) {
      // 发送输入状态
      if (inputText.length > 0) {
        this.sendTypingStatus(true);
      } else {
        this.sendTypingStatus(false);
      }
    }
  },

  // 处理中文输入法开始
  onCompositionStart(e) {
    this.setData({ isComposing: true });
  },

  // 处理中文输入法结束
  onCompositionEnd(e) {
    this.setData({ isComposing: false });

    // 输入法结束后，更新输入状态
    const inputText = this.data.inputText;
    if (inputText.length > 0) {
      this.sendTypingStatus(true);
    } else {
      this.sendTypingStatus(false);
    }
  },

  // 处理文本框行数变化
  onLineChange(e) {
    console.log('📝 文本框行数变化:', e.detail);
    // 可以在这里处理输入框高度变化的逻辑
    // 例如调整页面布局或滚动位置
  },

  // 🔥 ===== 媒体选择功能 =====

  // 显示媒体选择菜单
  showMediaPicker() {
    console.log('📱 显示媒体选择菜单');

    wx.showActionSheet({
      itemList: ['拍照', '拍摄视频'],
      success: (res) => {
        switch (res.tapIndex) {
          case 0:
            this.takePhoto();
            break;
          case 1:
            this.recordVideo();
            break;
        }
      },
      fail: (error) => {
        if (error.errMsg !== 'showActionSheet:fail cancel') {
          console.error('❌ 显示媒体选择菜单失败:', error);
        }
      }
    });
  },

  // 拍照
  async takePhoto() {
    console.log('📸 开始拍照');

    try {
      const result = await mediaPicker.chooseImages({
        count: 1,
        sourceType: ['camera']
      });

      if (result.success && result.files.length > 0) {
        await this.sendImageMessage(result.files[0]);
      }
    } catch (error) {
      console.error('❌ 拍照失败:', error);
      wx.showToast({
        title: '拍照失败',
        icon: 'none'
      });
    }
  },

  // 从相册选择图片
  async chooseImageFromAlbum() {
    console.log('🖼️ 打开相册选择菜单');

    try {
      // 在相册内二次分流：图片 或 视频
      const tapIndex = await new Promise((resolve) => {
        wx.showActionSheet({
          itemList: ['从相册选择图片', '从相册选择视频'],
          success: (res) => resolve(res.tapIndex),
          fail: (err) => {
            if (err.errMsg !== 'showActionSheet:fail cancel') {
              console.error('❌ 显示相册选择菜单失败:', err);
            }
            resolve(-1);
          }
        });
      });

      if (tapIndex === 0) {
        // 选择图片
        const result = await mediaPicker.chooseImages({
          count: 9,
          sourceType: ['album']
        });
        if (result.success && Array.isArray(result.files) && result.files.length > 0) {
          for (const image of result.files) {
            await this.sendImageMessage(image);
          }
        }
      } else if (tapIndex === 1) {
        // 选择视频
        const result = await mediaPicker.chooseVideo({
          sourceType: ['album'],
          maxDuration: 60
        });
        if (result.success && Array.isArray(result.files) && result.files.length > 0) {
          await this.sendVideoMessage(result.files[0]);
        }
      }
    } catch (error) {
      console.error('❌ 处理相册选择发生异常:', error);
    }
  },

  // 拍摄视频
  async recordVideo() {
    console.log('🎥 开始拍摄视频');

    try {
      const result = await mediaPicker.chooseVideo({
        sourceType: ['camera'],
        maxDuration: 60
      });

      if (result.success && result.files.length > 0) {
        await this.sendVideoMessage(result.files[0]);
      }
    } catch (error) {
      console.error('❌ 拍摄视频失败:', error);
      wx.showToast({
        title: '拍摄视频失败',
        icon: 'none'
      });
    }
  },

  // 从相册选择视频
  async chooseVideoFromAlbum() {
    console.log('🎞️ 从相册选择视频');
    try {
      const result = await mediaPicker.chooseVideo({
        sourceType: ['album'],
        maxDuration: 60
      });
      if (result.success && Array.isArray(result.files) && result.files.length > 0) {
        await this.sendVideoMessage(result.files[0]);
      }
    } catch (error) {
      console.error('❌ 选择视频失败:', error);
      wx.showToast({
        title: '选择视频失败',
        icon: 'none'
      });
    }
  },

  // 🔥 头像加载错误处理
  onAvatarError(e) {
    console.error('❌ 头像加载失败:', e.detail);
    console.log('❌ 失败的头像URL:', e.currentTarget.src);
    console.log('❌ 头像元素信息:', {
      src: e.currentTarget.src,
      dataset: e.currentTarget.dataset,
      id: e.currentTarget.id
    });

    // 🔥 尝试从dataset中获取更多信息
    const dataset = e.currentTarget.dataset;
    console.log('❌ 头像dataset信息:', dataset);
  },

  // 🔥 头像加载成功处理
  onAvatarLoad(e) {
    console.log('✅ 头像加载成功:', e.currentTarget.src);
  },

  // 🔥 ===== 媒体消息发送功能 =====

  // 发送图片消息 - 兼容媒体选择器
  async sendImageMessage(imageFile) {
    console.log('📸 发送图片消息:', imageFile);
    // 预生成临时ID，便于在任何失败路径更新状态
    const clientTempId = 'temp_' + Date.now();

    try {
      // 如果传入的是字符串路径，转换为文件对象格式
      if (typeof imageFile === 'string') {
        await this.uploadAndSendImage(imageFile);
        return;
      }

      // 检查用户信息
      if (!this.data.userInfo) {
        console.error('❌ 用户信息不存在，无法发送图片');
        return;
      }

      // 检查文件大小
      if (imageFile.size > 10 * 1024 * 1024) { // 10MB限制
        wx.showToast({
          title: '图片大小不能超过10MB',
          icon: 'none'
        });
        return;
      }

      // 获取用户ID
      const currentUserId = this.data.userInfo.user?.customId || this.data.userInfo.customId || '';
      if (!currentUserId) {
        console.error('无法获取用户ID');
        wx.showToast({
          title: '用户ID错误',
          icon: 'none'
        });
        return;
      }

      // 创建临时图片消息
      const timestamp = Date.now();
      const tempMessage = {
        messageId: clientTempId,
        senderId: currentUserId,
        targetId: this.data.targetId,
        content: {
          type: 'url',
          url: imageFile.path // 先使用本地路径显示
        },
        msgType: 'image',
        sendTime: timestamp,
        timestamp: timestamp,
        isSelf: true,
        senderName: '我',
        senderAvatar: this.data.userAvatar || '',
        deliveryStatus: 'sending',
        bubbleTime: this.formatBubbleTime(timestamp)
      };

      // 立即添加到消息列表
  const messages = this.data.messages.concat([tempMessage]);
  this.setMessagesWithDate(messages);

      // 滚动到底部
      setTimeout(() => {
        this.scrollToBottom();
      }, 100);

      wx.showLoading({ title: '发送中...' });

      // 上传图片到服务器
      const uploadResult = await apiClient.uploadFile(imageFile.path, 'image', 'message');

      if (uploadResult && uploadResult.code === 0) {
        const imageUrl = uploadResult.data.file_url || uploadResult.data.url;
        console.log('📸 获取到图片URL:', imageUrl);

        if (!imageUrl) {
          throw new Error('上传成功但未获取到图片URL');
        }

        // 更新临时消息的图片URL
        const updatedMessages = this.data.messages.map(msg => {
          if (msg.messageId === tempMessage.messageId) {
            return {
              ...msg,
              content: {
                type: 'url',
                url: imageUrl
              },
              // 上传成功，仅标记为sending，待WebSocket回执更新为sent
              deliveryStatus: 'sending'
            };
          }
          return msg;
        });
        this.setData({ messages: updatedMessages });

        // 🔥 发送图片消息 - 只使用WebSocket
        const success = wsManager.sendChatMessage(
          this.data.targetId,
          imageUrl,
          'image',
          this.data.chatType
        );

        if (!success) {
          this.updateMessageDeliveryStatus(tempMessage.messageId, 'failed');
          throw new Error('WebSocket连接异常，图片发送失败');
        }

        wx.hideLoading();
      } else {
        this.updateMessageDeliveryStatus(tempMessage.messageId, 'failed');
        throw new Error(uploadResult?.message || '图片上传失败');
      }

    } catch (error) {
      wx.hideLoading();
      console.error('❌ 发送图片消息失败:', error);
      // 标记为失败
      this.updateMessageDeliveryStatus(clientTempId, 'failed');
      wx.showToast({
        title: '图片发送失败',
        icon: 'none'
      });
    }
  },

  // 发送视频消息 - 兼容媒体选择器
  async sendVideoMessage(videoFile) {
    console.log('🎥 发送视频消息:', videoFile);
    const clientTempId = 'temp_' + Date.now();

    try {
      // 如果传入的是字符串路径，使用原有方法
      if (typeof videoFile === 'string') {
        await this.uploadAndSendVideo(videoFile);
        return;
      }

      // 检查用户信息
      if (!this.data.userInfo) {
        console.error('❌ 用户信息不存在，无法发送视频');
        return;
      }

      // 检查文件大小
      if (videoFile.size > 100 * 1024 * 1024) { // 100MB限制
        wx.showToast({
          title: '视频大小不能超过100MB',
          icon: 'none'
        });
        return;
      }

      // 获取用户ID
      const currentUserId = this.data.userInfo.user?.customId || this.data.userInfo.customId || '';
      if (!currentUserId) {
        console.error('无法获取用户ID');
        wx.showToast({
          title: '用户ID错误',
          icon: 'none'
        });
        return;
      }

      // 创建临时视频消息
      const timestamp = Date.now();
      const tempMessage = {
        messageId: clientTempId,
        senderId: currentUserId,
        targetId: this.data.targetId,
        content: videoFile.path, // 先使用本地路径显示
        msgType: 'video',
        sendTime: timestamp,
        timestamp: timestamp,
        isSelf: true,
        senderName: '我',
        senderAvatar: this.data.userAvatar || '',
        deliveryStatus: 'sending',
        bubbleTime: this.formatBubbleTime(timestamp)
      };

      // 立即添加到消息列表
  const messages = this.data.messages.concat([tempMessage]);
  this.setMessagesWithDate(messages);

      // 滚动到底部
      setTimeout(() => {
        this.scrollToBottom();
      }, 100);

      wx.showLoading({ title: '发送中...' });

      // 上传视频到服务器
      const uploadResult = await apiClient.uploadFile(videoFile.path, 'video', 'message');

      if (uploadResult && uploadResult.code === 0) {
        const videoUrl = uploadResult.data.file_url || uploadResult.data.url;
        console.log('🎥 获取到视频URL:', videoUrl);

        if (!videoUrl) {
          throw new Error('上传成功但未获取到视频URL');
        }

        // 更新临时消息的视频URL
        const updatedMessages = this.data.messages.map(msg => {
          if (msg.messageId === tempMessage.messageId) {
            return {
              ...msg,
              content: videoUrl,
              // 上传成功，等待WS回执
              deliveryStatus: 'sending'
            };
          }
          return msg;
        });
        this.setData({ messages: updatedMessages });

        // 🔥 发送视频消息 - 只使用WebSocket
        const success = wsManager.sendChatMessage(
          this.data.targetId,
          videoUrl,
          'video',
          this.data.chatType
        );

        if (!success) {
          this.updateMessageDeliveryStatus(tempMessage.messageId, 'failed');
          throw new Error('WebSocket连接异常，视频发送失败');
        }

        wx.hideLoading();
      } else {
        throw new Error(uploadResult?.message || '视频上传失败');
      }

    } catch (error) {
      wx.hideLoading();
      console.error('❌ 发送视频消息失败:', error);
      this.updateMessageDeliveryStatus(clientTempId, 'failed');
      wx.showToast({
        title: '视频发送失败',
        icon: 'none'
      });
    }
  },

  // 🔥 ===== 消息发送功能 =====

  // 发送文本消息 - 优化新会话处理
  async sendTextMessage() {
    const content = this.data.inputText.trim();
    if (!content) return;

    // 检查用户信息
    if (!this.data.userInfo) {
      console.error('用户信息不存在，无法发送消息');
      wx.showToast({
        title: '用户信息错误',
        icon: 'none'
      });
      return;
    }

    // 清空输入框
    this.setData({
      inputText: '',
      showEmojiPanel: false,
      showMorePanel: false
    });

    // 停止输入状态
    this.sendTypingStatus(false);

    // 获取用户ID
    const currentUserId = this.data.userInfo.user?.customId || this.data.userInfo.customId || '';
    if (!currentUserId) {
      console.error('无法获取用户ID');
      wx.showToast({
        title: '用户ID错误',
        icon: 'none'
      });
      return;
    }

    // 创建临时消息
    const timestamp = Date.now();
    const tempMessage = {
      messageId: 'temp_' + timestamp,
      senderId: currentUserId,
      targetId: this.data.targetId,
      content: content,
      msgType: 'text',
      sendTime: timestamp,
      timestamp: timestamp, // 🔥 添加timestamp字段确保排序正确
      isSelf: true,
      senderName: '我',
      senderAvatar: this.data.userAvatar || '', // 🔥 使用用户头像，便于WXML判断
      deliveryStatus: 'sending',
      bubbleTime: this.formatBubbleTime(timestamp)
    };

    // 添加到消息列表
  const messages = this.data.messages.concat([tempMessage]);
  this.setMessagesWithDate(messages);

    // 🔥 确保消息添加后立即滚动到底部
    setTimeout(() => {
      this.scrollToBottom();
    }, 100);

    try {
      // 🔥 检查WebSocket连接状态
      console.log('📡 WebSocket连接状态:', wsManager.isConnected);
      console.log('📤 准备发送消息:', {
        targetId: this.data.targetId,
        content: content,
        msgType: 'text',
        chatType: this.data.chatType
      });

      if (!wsManager.isConnected) {
        console.warn('⚠️ WebSocket未连接，尝试重新连接...');

        // 🔥 使用事件监听方式等待连接
        const connectPromise = new Promise((resolve, reject) => {
          const timeout = setTimeout(() => {
            wsManager.off('connected', onConnected);
            wsManager.off('error', onError);
            reject(new Error('WebSocket连接超时（15秒）'));
          }, 15000); // 增加到15秒超时

          const onConnected = () => {
            clearTimeout(timeout);
            wsManager.off('connected', onConnected);
            wsManager.off('error', onError);
            console.log('✅ WebSocket连接成功');
            resolve();
          };

          const onError = (error) => {
            clearTimeout(timeout);
            wsManager.off('connected', onConnected);
            wsManager.off('error', onError);
            console.error('❌ WebSocket连接失败:', error);
            reject(new Error('WebSocket连接失败'));
          };

          // 监听连接事件
          wsManager.on('connected', onConnected);
          wsManager.on('error', onError);

          // 如果已经连接，直接resolve
          if (wsManager.isConnected) {
            clearTimeout(timeout);
            resolve();
          } else {
            // 开始连接
            wsManager.connect();
          }
        });

        await connectPromise;
      }

      // 🔥 发送消息 - 只使用WebSocket，根据API文档要求
      const success = wsManager.sendChatMessage(
        this.data.targetId,
        content,
        'text',
        this.data.chatType
      );

      if (!success) {
        // WebSocket发送失败，抛出错误
        throw new Error('WebSocket发送消息失败');
      }

      // 更新消息状态为已发送
      this.updateMessageDeliveryStatus(tempMessage.messageId, 'sent');

      // 🔥 如果是新会话，发送第一条消息后刷新会话列表获取正确ID
      if (this.data.isNewConversation) {
        console.log('🔄 新会话发送消息后，重新获取正确的conversationId...');
        setTimeout(() => {
          this.refreshConversationId();
        }, 1000); // 延迟1秒确保后端已处理完成
      }

    } catch (error) {
      console.error('发送消息失败:', error);
      // 更新消息状态为失败
      this.updateMessageDeliveryStatus(tempMessage.messageId, 'failed');

      wx.showToast({
        title: '发送失败',
        icon: 'none'
      });
    }
  },

  // 刷新conversationId（用于新会话发送消息后）
  async refreshConversationId() {
    try {
      const response = await apiClient.getConversations();
      if (response && response.code === 0) {
        const conversations = response.data || [];

        // 查找与当前targetId的会话
        const targetConversation = conversations.find(conv =>
          conv.type === this.data.chatType && conv.targetId === this.data.targetId
        );

        if (targetConversation && targetConversation.id !== this.data.conversationId) {
          console.log('✅ 更新会话ID:', this.data.conversationId, '->', targetConversation.id);
          this.setData({
            conversationId: targetConversation.id,
            isNewConversation: false
          });
        }
      }
    } catch (error) {
      console.error('❌ 刷新conversationId失败:', error);
    }
  },

  // 更新消息发送状态
  updateMessageDeliveryStatus(messageId, status) {
    const messages = this.data.messages.map(msg => {
      if (msg.messageId === messageId) {
        return { ...msg, deliveryStatus: status };
      }
      return msg;
    });
    this.setData({ messages });
  },

  // 发送输入状态
  sendTypingStatus(isTyping) {
    wsManager.sendTypingStatus(this.data.conversationId, isTyping);
  },

  // 发送已读回执
  sendReadReceipt(messageId) {
    wsManager.sendReadReceipt(messageId);
  },

  // 标记所有消息已读（进入聊天页面时调用）
  async markAllMessagesRead() {
    try {
      if (!this.data.conversationId || this.data.conversationId.trim() === '') {
        console.log('⚠️ 会话ID为空，跳过标记已读（可能是新会话）');
        return;
      }

      console.log('📖 标记会话所有消息已读:', this.data.conversationId);

      // 🔥 使用正确的API方法名
      const response = await apiClient.markAllRead(this.data.conversationId);

      // 🔥 兼容后端业务码：可能为 0 或 200 都表示成功
      if (response && (response.code === 0 || response.code === 200)) {
        console.log('✅ 消息已全部标记已读');

        // 更新本地消息状态
        const updatedMessages = this.data.messages.map(msg => ({
          ...msg,
          deliveryStatus: msg.isSelf ? msg.deliveryStatus : 'read'
        }));

        this.setData({
          messages: updatedMessages
        });
      } else {
        console.warn('⚠️ 标记已读响应异常:', response);
      }
    } catch (error) {
      console.error('❌ 标记消息已读失败:', error);
      // 🔥 不显示错误提示，避免影响用户体验
    }
  },

  // 标记消息已读（接收到新消息时调用）
  markMessagesRead() {
    if (this.data.messages.length > 0) {
      const lastMessageId = this.data.messages[this.data.messages.length - 1].messageId;
      this.sendReadReceipt(lastMessageId);
    }
  },

  // 切换输入类型
  toggleInputType() {
    const inputType = this.data.inputType === 'text' ? 'voice' : 'text';
    this.setData({
      inputType,
      showEmojiPanel: false,
      showMorePanel: false
    });
  },

  // 切换表情面板
  toggleEmojiPanel() {
    this.setData({
      showEmojiPanel: !this.data.showEmojiPanel,
      showMorePanel: false
    });
  },

  // 切换更多面板
  toggleMorePanel() {
    this.setData({
      showMorePanel: !this.data.showMorePanel,
      showEmojiPanel: false
    });
  },

  // 阻止事件冒泡
  stopPropagation() {
    // 阻止事件冒泡，防止点击面板内容时关闭面板
  },

  // 🔥 新增：组件方法（不影响现有功能）

  // 媒体预览组件方法
  closeMediaPreview() {
    this.setData({
      mediaPreviewVisible: false,
      mediaPreviewList: [],
      currentMediaIndex: 0
    });
  },

  onMediaIndexChange(e) {
    const { currentIndex } = e.detail;
    this.setData({
      currentMediaIndex: currentIndex
    });
  },

  // 消息操作菜单组件方法
  closeMessageAction() {
    this.setData({
      messageActionVisible: false,
      currentMessage: null,
      isOwnMessage: false
    });
  },

  onMessageAction(e) {
    const { action, data } = e.detail;
    console.log('消息操作:', action, data);

    // 根据操作类型执行相应功能
    switch (action) {
      case 'copy':
        this.copyMessage(this.data.currentMessage);
        break;
      case 'delete':
        this.deleteMessage(this.data.currentMessage);
        break;
      case 'recall':
        this.recallMessage(this.data.currentMessage);
        break;
      case 'reaction':
        // 处理表情回应
        console.log('表情回应:', data);
        break;
      default:
        console.log('未处理的操作:', action);
    }

    this.closeMessageAction();
  },

  // @提醒选择器组件方法
  closeMentionSelector() {
    this.setData({
      mentionSelectorVisible: false
    });
  },

  onMentionSelect(e) {
    const { type, text, userIds } = e.detail;
    console.log('@提醒选择:', type, text, userIds);

    // 将@信息添加到输入框
    if (type === 'all') {
      this.setData({
        inputText: this.data.inputText + '@所有人 '
      });
    } else {
      this.setData({
        inputText: this.data.inputText + `@${text} `
      });
    }

    this.closeMentionSelector();
  },

  // 🎤 ===== 语音消息功能 =====

  // 显示语音录制界面（重命名避免与 data 字段同名造成绑定混淆）
  openVoiceRecorder() {
    console.log('🎤 显示语音录制界面');

    this.setData({
      showVoiceRecorder: true,
      showEmojiPanel: false,
      showMorePanel: false
    });
  },

  // 关闭语音录制界面
  closeVoiceRecorder() {
    console.log('🎤 关闭语音录制界面');

    this.setData({
      showVoiceRecorder: false
    });
  },

  // 语音发送事件处理
  onVoiceSend(e) {
    const voiceData = e.detail;
    console.log('🎤 发送语音消息:', voiceData);

    // 发送语音消息
    this.sendVoiceMessage(voiceData);
  },

  // 发送语音消息
  async sendVoiceMessage(voiceData) {
    // 预分配临时ID，便于错误时标记
    const clientTempId = 'temp_' + Date.now();
    try {
      console.log('📤 发送语音消息:', voiceData);

      // 与文本/图片一致的临时消息结构
      const timestamp = Date.now();
      const currentUserId = this.data.userInfo?.user?.customId || this.data.userInfo?.customId || this.data.userInfo?.id || 'unknown';

      const voiceMessage = {
        messageId: clientTempId,
        conversationId: this.data.conversationId,
        senderId: currentUserId,
        senderName: this.data.userInfo?.nickname || '我',
        senderAvatar: this.data.userAvatar || '',
        targetId: this.data.targetId,
        msgType: 'voice',
        content: {
          url: voiceData.url,
          duration: voiceData.duration,
          size: voiceData.size,
          tempFilePath: voiceData.tempFilePath
        },
        sendTime: timestamp,
        timestamp: timestamp,
        isSelf: true,
        deliveryStatus: 'sending',
        bubbleTime: this.formatBubbleTime(timestamp)
      };

      // 添加到消息列表并滚动到底
  const messages = this.data.messages.concat([voiceMessage]);
  this.setMessagesWithDate(messages);
      setTimeout(() => { this.scrollToBottom(); }, 100);

      // 🔥 使用正确的WebSocket消息格式发送语音消息
      const success = wsManager.sendChatMessage(
        this.data.targetId,
        JSON.stringify(voiceMessage.content),
        'voice',
        this.data.chatType
      );

      if (success) {
        this.updateMessageStatus({ messageId: voiceMessage.messageId, status: 'sent' });
        console.log('✅ 语音消息发送成功');
      } else {
        this.updateMessageStatus({ messageId: voiceMessage.messageId, status: 'failed' });
        console.error('❌ 语音消息发送失败');
        wx.showToast({ title: '发送失败', icon: 'none' });
      }

    } catch (error) {
      console.error('❌ 发送语音消息失败:', error);
      // 标记失败
      this.updateMessageDeliveryStatus(clientTempId, 'failed');
      wx.showToast({ title: '发送失败', icon: 'none' });
    }
  },

  // 选择表情
  selectEmoji(e) {
    const emoji = e.currentTarget.dataset.emoji;
    const inputText = this.data.inputText + emoji;
    this.setData({ inputText });
  },

  // 开始录音
  startRecording(e) {
    console.log('开始录音');
    this.setData({ recording: true });

    // TODO: 实现录音功能
    wx.showToast({
      title: '录音功能开发中',
      icon: 'none'
    });
  },

  // 停止录音
  stopRecording(e) {
    console.log('停止录音');
    this.setData({ recording: false });

    // TODO: 处理录音结果
  },

  // 取消录音
  cancelRecording(e) {
    console.log('取消录音');
    this.setData({ recording: false });
  },

  // 选择图片
  selectImage() {
    wx.chooseImage({
      count: 9,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success: (res) => {
        console.log('选择图片:', res);
        this.uploadAndSendImage(res.tempFilePaths[0]);
      }
    });

    this.setData({ showMorePanel: false });
  },

  // 上传并发送图片
  async uploadAndSendImage(imagePath) {
    try {
      // 获取用户ID
      const currentUserId = this.data.userInfo?.user?.customId || this.data.userInfo?.customId || '';
      if (!currentUserId) {
        console.error('无法获取用户ID');
        wx.showToast({
          title: '用户ID错误',
          icon: 'none'
        });
        return;
      }

      // 创建临时图片消息
      const timestamp = Date.now();
      const tempMessage = {
        messageId: 'temp_' + timestamp,
        senderId: currentUserId,
        targetId: this.data.targetId,
        content: {
          type: 'url',
          url: imagePath // 先使用本地路径显示
        },
        msgType: 'image',
        sendTime: timestamp,
        timestamp: timestamp,
        isSelf: true,
        senderName: '我',
        senderAvatar: this.data.userAvatar || '',
        deliveryStatus: 'sending',
        bubbleTime: this.formatBubbleTime(timestamp)
      };

      // 立即添加到消息列表
  const messages = this.data.messages.concat([tempMessage]);
  this.setMessagesWithDate(messages);

      // 滚动到底部
      setTimeout(() => {
        this.scrollToBottom();
      }, 100);

      wx.showLoading({ title: '发送中...' });

      // 上传图片
      const uploadResult = await apiClient.uploadFile(imagePath, 'image', 'message');

      if (uploadResult && uploadResult.code === 0) {
        const imageUrl = uploadResult.data.file_url || uploadResult.data.url;
        console.log('📸 获取到图片URL:', imageUrl);

        if (!imageUrl) {
          throw new Error('上传成功但未获取到图片URL');
        }

        // 更新临时消息的图片URL
        const updatedMessages = this.data.messages.map(msg => {
          if (msg.messageId === tempMessage.messageId) {
            return {
              ...msg,
              content: {
                type: 'url',
                url: imageUrl
              },
              deliveryStatus: 'sending'
            };
          }
          return msg;
        });
        this.setData({ messages: updatedMessages });

        // 🔥 发送图片消息 - 只使用WebSocket
        const success = wsManager.sendChatMessage(
          this.data.targetId,
          imageUrl,
          'image',
          this.data.chatType
        );

        if (!success) {
          this.updateMessageDeliveryStatus(tempMessage.messageId, 'failed');
          throw new Error('WebSocket连接异常，图片发送失败');
        }

        wx.hideLoading();
      } else {
        throw new Error(uploadResult?.message || '图片上传失败');
      }
    } catch (error) {
      wx.hideLoading();
      console.error('发送图片失败:', error);
      // 兜底：尝试将最后一条sending的自发图片置为failed
      const lastIndex = [...this.data.messages].reverse().findIndex(m => m.isSelf && m.msgType === 'image' && m.deliveryStatus === 'sending');
      if (lastIndex !== -1) {
        const idx = this.data.messages.length - 1 - lastIndex;
        const failed = this.data.messages.map((m, i) => i === idx ? { ...m, deliveryStatus: 'failed' } : m);
        this.setData({ messages: failed });
      }
      wx.showToast({
        title: '发送失败',
        icon: 'none'
      });
    }
  },

  // 选择视频
  selectVideo() {
    wx.chooseVideo({
      sourceType: ['album', 'camera'],
      maxDuration: 60,
      compressed: true,
      success: (res) => {
        console.log('选择视频:', res);
        // TODO: 实现视频上传和发送
        wx.showToast({
          title: '视频功能开发中',
          icon: 'none'
        });
      }
    });

    this.setData({ showMorePanel: false });
  },

  // 选择文件
  selectFile() {
    // 先收起面板
    this.setData({ showMorePanel: false });

    try {
      wx.chooseMessageFile({
        count: 1,
        type: 'file',
        success: async (res) => {
          if (!res || !res.tempFiles || res.tempFiles.length === 0) {
            wx.showToast({ title: '未选择文件', icon: 'none' });
            return;
          }

          const file = res.tempFiles[0];
          const filePath = file.path || file.tempFilePath;
          const fileName = file.name || '文件';
          const fileSize = file.size || 0;
          const readableSize = this.formatFileSize(fileSize);

          // 可选：限制大小 100MB
          if (fileSize > 100 * 1024 * 1024) {
            wx.showToast({ title: '文件不能超过100MB', icon: 'none' });
            return;
          }

          // 获取当前用户ID
          const currentUserId = this.data.userInfo?.user?.customId || this.data.userInfo?.customId || '';
          if (!currentUserId) {
            wx.showToast({ title: '用户信息错误', icon: 'none' });
            return;
          }

          // 创建临时消息
          const timestamp = Date.now();
          const clientTempId = 'temp_' + timestamp;
          const tempMessage = {
            messageId: clientTempId,
            senderId: currentUserId,
            targetId: this.data.targetId,
            content: { url: '' },
            msgType: 'file',
            fileName: fileName,
            fileSize: readableSize,
            sendTime: timestamp,
            timestamp: timestamp,
            isSelf: true,
            senderName: '我',
            senderAvatar: this.data.userAvatar || '',
            deliveryStatus: 'sending',
            bubbleTime: this.formatBubbleTime(timestamp)
          };

          this.setMessagesWithDate(this.data.messages.concat([tempMessage]));
          setTimeout(() => this.scrollToBottom(), 100);

          wx.showLoading({ title: '发送中...' });

          try {
            // 上传文件
            const uploadResult = await apiClient.uploadFile(filePath, 'file', 'message');
            if (uploadResult && uploadResult.code === 0) {
              const fileUrl = uploadResult.data.file_url || uploadResult.data.url;
              if (!fileUrl) throw new Error('上传成功但未返回URL');

              // 更新临时消息为已发送并写入URL
              const updatedMessages = this.data.messages.map(msg => {
                if (msg.messageId === tempMessage.messageId) {
                  return {
                    ...msg,
                    content: { url: fileUrl },
                    deliveryStatus: 'sending'
                  };
                }
                return msg;
              });
              this.setData({ messages: updatedMessages });

              // 通过WebSocket发送
              const payload = { url: fileUrl, file_name: fileName, file_size: fileSize, clientTempId };
              const ok = wsManager.sendChatMessage(
                this.data.targetId,
                JSON.stringify(payload),
                'file',
                this.data.chatType
              );
              if (!ok) throw new Error('WebSocket连接异常，文件发送失败');

              wx.hideLoading();
              // 状态改为等待服务端回执后再置为sent
            } else {
              throw new Error(uploadResult?.message || '文件上传失败');
            }
          } catch (err) {
            console.error('❌ 发送文件失败:', err);
            // 更新为失败
            const failedMessages = this.data.messages.map(msg => {
              if (msg.messageId === tempMessage.messageId) {
                return { ...msg, deliveryStatus: 'failed' };
              }
              return msg;
            });
            this.setData({ messages: failedMessages });
            wx.hideLoading();
            wx.showToast({ title: '发送失败', icon: 'none' });
          }
        },
        fail: (error) => {
          if (error && error.errMsg && !/cancel/.test(error.errMsg)) {
            console.error('❌ 选择文件失败:', error);
            wx.showToast({ title: '选择文件失败', icon: 'none' });
          }
        }
      });
    } catch (e) {
      console.error('❌ 文件选择异常:', e);
      wx.showToast({ title: '选择文件异常', icon: 'none' });
    }
  },

  // 将字节大小格式化成人类可读
  formatFileSize(bytes) {
    try {
      if (!bytes || bytes <= 0) return '0 B';
      const units = ['B', 'KB', 'MB', 'GB', 'TB'];
      const i = Math.floor(Math.log(bytes) / Math.log(1024));
      const value = bytes / Math.pow(1024, i);
      return `${value.toFixed(value >= 100 ? 0 : value >= 10 ? 1 : 2)} ${units[i]}`;
    } catch (e) {
      return `${bytes} B`;
    }
  },

  // 选择位置
  selectLocation() {
    wx.chooseLocation({
      success: async (res) => {
        try {
          console.log('📍 选择位置:', res);
          const { name, address, latitude, longitude } = res || {};

          // 基本校验
          if (latitude == null || longitude == null) {
            wx.showToast({ title: '位置信息无效', icon: 'none' });
            return;
          }

          // 当前用户
          const currentUserId = this.data.userInfo?.user?.customId || this.data.userInfo?.customId || '';
          if (!currentUserId) {
            wx.showToast({ title: '用户信息错误', icon: 'none' });
            return;
          }

          // 构造临时消息
          const timestamp = Date.now();
          const clientTempId = 'temp_' + timestamp;
          const tempMsg = {
            messageId: clientTempId,
            senderId: currentUserId,
            targetId: this.data.targetId,
            msgType: 'location',
            content: { latitude, longitude, address, locationName: name || '位置' },
            locationName: name || '位置',
            locationAddress: address || '',
            latitude,
            longitude,
            sendTime: timestamp,
            timestamp,
            isSelf: true,
            senderName: '我',
            senderAvatar: this.data.userAvatar || '',
            deliveryStatus: 'sending',
            bubbleTime: this.formatBubbleTime(timestamp)
          };

          this.setMessagesWithDate(this.data.messages.concat([tempMsg]));
          setTimeout(() => this.scrollToBottom(), 100);

          // 通过 WebSocket 发送位置消息
          const ok = wsManager.sendLocationMessage(
            this.data.targetId,
            latitude,
            longitude,
            address || '',
            name || '位置',
            this.data.chatType,
            { extra: JSON.stringify({ clientTempId }) }
          );

          if (!ok) {
            this.updateMessageDeliveryStatus(clientTempId, 'failed');
            throw new Error('WebSocket连接异常，位置发送失败');
          }

        } catch (err) {
          console.error('❌ 发送位置失败:', err);
          // 标记失败
          if (clientTempId) this.updateMessageDeliveryStatus(clientTempId, 'failed');
          wx.showToast({ title: '位置发送失败', icon: 'none' });
        }
      },
      fail: (e) => {
        if (e && e.errMsg && !/cancel/.test(e.errMsg)) {
          console.error('❌ 选择位置失败:', e);
          wx.showToast({ title: '选择位置失败', icon: 'none' });
        }
      },
      complete: () => {
        this.setData({ showMorePanel: false });
      }
    });
  },

  // 图片加载错误处理
  onImageError(e) {
    console.error('❌ 图片加载失败:', e.detail);
    const url = e.currentTarget.dataset.url;
    wx.showToast({
      title: '图片加载失败',
      icon: 'none',
      duration: 2000
    });
  },

  // 预览图片 - 支持新的图片格式
  previewImage(e) {
    const url = e.currentTarget.dataset.url;
    const type = e.currentTarget.dataset.type;

    console.log('🖼️ 预览图片:', { url, type });

    if (!url) {
      wx.showToast({
        title: '图片地址无效',
        icon: 'none'
      });
      return;
    }

    // Base64格式需要特殊处理
    if (type === 'base64' || url.startsWith('data:image/')) {
      // 小程序的previewImage可以直接处理Base64
      wx.previewImage({
        current: url,
        urls: [url]
      });
    } else {
      // 普通URL格式
      wx.previewImage({
        current: url,
        urls: [url]
      });
    }
  },

  // 播放音频
  playAudio(e) {
    const message = e.currentTarget.dataset.message;
    console.log('播放音频:', message);
    // TODO: 实现音频播放
    wx.showToast({
      title: '音频播放功能开发中',
      icon: 'none'
    });
  },

  // 显示位置
  showLocation(e) {
    const message = e.currentTarget.dataset.message;
    console.log('📍 打开位置:', message);
    try {
      // 统一解析位置内容（content 可能是 JSON 字符串或对象）
      const parsed = this.parseLocationContent(message.content) || {};
      const lat = message.latitude ?? parsed.latitude;
      const lng = message.longitude ?? parsed.longitude;
      const name = message.locationName || parsed.locationName || '位置';
      const address = message.locationAddress || parsed.address || '';

      if (lat == null || lng == null) {
        wx.showToast({ title: '无效位置', icon: 'none' });
        return;
      }

      wx.openLocation({
        latitude: Number(lat),
        longitude: Number(lng),
        name: name,
        address: address,
        scale: 16
      });
    } catch (err) {
      console.error('❌ 打开位置失败:', err);
      wx.showToast({ title: '打开位置失败', icon: 'none' });
    }
  },

  // 显示消息菜单
  showMessageMenu(e) {
    const message = e.currentTarget.dataset.message;
    const itemList = [];

    // 撤回的消息只能删除
    if (message.isRecalled) {
      itemList.push('删除');
    } else {
      // 普通消息的菜单选项
      if (message.msgType === 'text') {
        itemList.push('复制');
      }
      itemList.push('删除');

      if (message.isSelf) {
        // 检查是否可以撤回（2分钟内）
        const canRecall = this.canRecallMessage(message);
        if (canRecall) {
          itemList.push('撤回');
        }
      }
    }

    wx.showActionSheet({
      itemList: itemList,
      success: (res) => {
        const action = itemList[res.tapIndex];
        switch (action) {
          case '复制':
            this.copyMessage(message);
            break;
          case '删除':
            this.deleteMessage(message);
            break;
          case '撤回':
            this.recallMessage(message);
            break;
        }
      }
    });
  },

  // 复制消息
  copyMessage(message) {
    if (message.msgType === 'text') {
      wx.setClipboardData({
        data: message.content,
        success: () => {
          wx.showToast({
            title: '已复制',
            icon: 'success'
          });
        }
      });
    }
  },

  // 删除消息
  deleteMessage(message) {
    wx.showModal({
      title: '确认删除',
      content: '确定要删除这条消息吗？',
      success: (res) => {
        if (res.confirm) {
          const messages = this.data.messages.filter(msg => msg.messageId !== message.messageId);
          this.setMessagesWithDate(messages);
        }
      }
    });
  },

  // 撤回消息
  async recallMessage(message) {
    // 检查撤回时间限制
    if (!this.canRecallMessage(message)) {
      wx.showToast({
        title: '超过2分钟无法撤回',
        icon: 'none'
      });
      return;
    }

    wx.showModal({
      title: '确认撤回',
      content: '确定要撤回这条消息吗？',
      success: async (res) => {
        if (res.confirm) {
          try {
            // 显示加载状态
            wx.showLoading({
              title: '撤回中...',
              mask: true
            });

            // 检查WebSocket连接状态
            if (!wsManager || !wsManager.isConnected) {
              throw new Error('网络连接异常，请检查网络后重试');
            }

            // 通过WebSocket发送撤回消息
            const result = await wsManager.recallMessage(message.messageId);

            // 撤回成功，本地立即更新消息状态为已撤回
            this.updateMessageToRecalled(message.messageId);

            wx.showToast({
              title: '已撤回',
              icon: 'success'
            });
          } catch (error) {
            console.error('撤回消息失败:', error);
            wx.showToast({
              title: error.message || '撤回失败',
              icon: 'none'
            });
          } finally {
            wx.hideLoading();
          }
        }
      }
    });
  },

  // 检查是否可以撤回消息
  canRecallMessage(message) {
    if (!message.isSelf) return false;
    if (message.msgType === 'system' || message.isRecalled) return false;

    // 检查时间限制（2分钟 = 120秒）
    const now = Date.now();
    const messageTime = message.timestamp || message.createTime || now;
    const timeDiff = (now - messageTime) / 1000; // 转换为秒

    return timeDiff <= 120; // 2分钟内可撤回
  },

  // 更新消息为已撤回状态
  updateMessageToRecalled(messageId) {
    const messages = this.data.messages.map(msg => {
      if (msg.messageId === messageId) {
        return {
          ...msg,
          isRecalled: true,
          content: '你撤回了一条消息',
          originalContent: msg.content, // 保存原始内容用于调试
          recallTime: Date.now()
        };
      }
      return msg;
    });
    this.setData({ messages });
  },

  // 重发消息
  async resendMessage(e) {
    const message = e.currentTarget.dataset.message;
    if (!message) return;
    console.log('🔁 重发消息:', message);

    // 标记为发送中
    this.updateMessageDeliveryStatus(message.messageId, 'sending');

    try {
      // 确保WS已连接，必要时尝试快速重连
      if (!wsManager || !wsManager.isConnected) {
        console.warn('⚠️ WebSocket未连接，尝试重连以重新发送...');
        const tryConnect = new Promise((resolve, reject) => {
          let done = false;
          const to = setTimeout(() => { if (!done) { done = true; cleanup(); reject(new Error('WS重连超时')); } }, 8000);
          const onConn = () => { if (!done) { done = true; cleanup(); resolve(); } };
          const onErr = (err) => { if (!done) { done = true; cleanup(); reject(err || new Error('WS重连失败')); } };
          const cleanup = () => { try { wsManager.off('connected', onConn); wsManager.off('error', onErr); clearTimeout(to); } catch (e) {} };
          try { wsManager.on('connected', onConn); wsManager.on('error', onErr); wsManager.connect(); } catch (e) { cleanup(); reject(e); }
        });
        await tryConnect;
      }

      let ok = false;
      switch (message.msgType) {
        case 'text':
          ok = wsManager.sendChatMessage(this.data.targetId, message.content, 'text', this.data.chatType);
          break;
        case 'image': {
          const url = message.content?.url || message.content;
          ok = wsManager.sendChatMessage(this.data.targetId, url, 'image', this.data.chatType);
          break;
        }
        case 'video': {
          const url = message.content?.url || message.content;
          ok = wsManager.sendChatMessage(this.data.targetId, url, 'video', this.data.chatType);
          break;
        }
        case 'voice': {
          const payload = typeof message.content === 'string' ? message.content : JSON.stringify(message.content || {});
          ok = wsManager.sendChatMessage(this.data.targetId, payload, 'voice', this.data.chatType);
          break;
        }
        case 'file': {
          const payload = JSON.stringify({ url: message.content?.url || '', file_name: message.fileName, file_size: message.fileSize });
          ok = wsManager.sendChatMessage(this.data.targetId, payload, 'file', this.data.chatType);
          break;
        }
        case 'location': {
          const lat = message.latitude ?? message.content?.latitude;
          const lng = message.longitude ?? message.content?.longitude;
          const address = message.locationAddress || message.content?.address || '';
          const name = message.locationName || message.content?.locationName || '位置';
          ok = wsManager.sendLocationMessage(this.data.targetId, lat, lng, address, name, this.data.chatType);
          break;
        }
        default:
          ok = false;
      }

      if (!ok) throw new Error('网络异常，发送失败');
      // 成功由服务端回执最终置为sent，这里不强行改
    } catch (err) {
      console.error('❌ 重发失败:', err);
      this.updateMessageDeliveryStatus(message.messageId, 'failed');
      wx.showToast({ title: '发送失败', icon: 'none' });
    }
  },

  // 将消息置为失败并可选记录原因
  markMessageFailed(messageId, reason) {
    const messages = this.data.messages.map(m => m.messageId === messageId ? { ...m, deliveryStatus: 'failed', errorReason: reason || '' } : m);
    this.setData({ messages });
  },

  // 🔥 加载更多消息 - 仅在用户向上滚动时触发
  loadMoreMessages() {
    console.log('🔄 用户向上滚动，触发加载更多历史消息');
    console.log('🔍 当前状态检查:', {
      hasMore: this.data.hasMore,
      loadingMessages: this.data.loadingMessages,
      lastMessageId: this.data.lastMessageId,
      messagesCount: this.data.messages.length
    });

    // 🔥 检查是否还有更多消息
    if (!this.data.hasMore) {
      console.log('⚠️ 没有更多历史消息了');
      return;
    }

    // 🔥 检查是否正在加载中
    if (this.data.loadingMessages) {
      console.log('⚠️ 正在加载中，忽略重复请求');
      return;
    }

    // 🔥 检查是否有lastMessageId用于分页
    if (!this.data.lastMessageId) {
      console.log('⚠️ 缺少lastMessageId，无法加载更多');
      this.setData({ hasMore: false });
      return;
    }

    console.log('✅ 开始加载更多历史消息，lastMessageId:', this.data.lastMessageId);

    // 🔥 直接调用loadMessages，不在这里设置loadingMessages状态
    // loadMessages方法内部会处理状态管理
    this.loadMessages(true); // 传递true表示是加载更多
  },

  // 🔥 滚动事件处理 - 控制滚动到底部按钮显示
  onScroll(e) {
    const { scrollTop, scrollHeight } = e.detail;
    const windowHeight = this.data.windowHeight - 200; // 减去输入框高度

    // 计算距离底部的距离
    const distanceFromBottom = scrollHeight - scrollTop - windowHeight;

    // 如果距离底部超过一个屏幕高度，显示滚动到底部按钮
    const shouldShow = distanceFromBottom > windowHeight;

    if (this.data.showScrollToBottom !== shouldShow) {
      this.setData({
        showScrollToBottom: shouldShow
      });
    }
  },

  // 🔥 滚动到底部 - 参考Flutter app的实现
  scrollToBottom() {
    if (this.data.messages.length === 0) return;

    const lastMessage = this.data.messages[this.data.messages.length - 1];
    if (!lastMessage) return;

    console.log('📍 自动滚动到最新消息，消息ID:', lastMessage.messageId);

    // 🔥 参考Flutter的animateTo(maxScrollExtent)实现
    // 方法1：使用scrollIntoView精确定位到最后一条消息
    const scrollIntoViewId = 'msg-' + lastMessage.messageId;

    this.setData({
      scrollIntoView: scrollIntoViewId,
      scrollTop: 999999, // 🔥 同时设置一个大值确保滚动到底部
      showScrollToBottom: false // 🔥 滚动到底部后隐藏按钮
    });

    // 🔥 延迟再次滚动，确保DOM完全渲染（模仿Flutter的延迟机制）
    setTimeout(() => {
      this.setData({
        scrollIntoView: scrollIntoViewId,
        scrollTop: 999999
      });
    }, 100);

    // 🔥 最后的保障：强制滚动到底部
    setTimeout(() => {
      this.setData({
        scrollTop: 999999
      });
    }, 300);
  },

  // 显示聊天菜单
  showChatMenu() {
    const itemList = ['清空聊天记录', '查找聊天记录'];

    if (this.data.chatType === 0) {
      itemList.push('视频通话', '语音通话');
    } else {
      itemList.push('群聊信息');
    }

    wx.showActionSheet({
      itemList: itemList,
      success: (res) => {
        console.log('选择菜单项:', res.tapIndex);
        wx.showToast({
          title: '功能开发中',
          icon: 'none'
        });
      }
    });
  },

  // 下载文件
  downloadFile(e) {
    const message = e.currentTarget.dataset.message;
    console.log('📄 下载文件:', message);

    if (!message.content || !message.content.url) {
      wx.showToast({
        title: '文件地址无效',
        icon: 'none'
      });
      return;
    }

    wx.showModal({
      title: '下载文件',
      content: `确定要下载文件 "${message.fileName || '未知文件'}" 吗？`,
      success: (res) => {
        if (res.confirm) {
          wx.downloadFile({
            url: message.content.url,
            success: (downloadRes) => {
              if (downloadRes.statusCode === 200) {
                wx.openDocument({
                  filePath: downloadRes.tempFilePath,
                  success: () => {
                    console.log('✅ 文件打开成功');
                  },
                  fail: (err) => {
                    console.error('❌ 文件打开失败:', err);
                    wx.showToast({
                      title: '文件打开失败',
                      icon: 'none'
                    });
                  }
                });
              }
            },
            fail: (err) => {
              console.error('❌ 文件下载失败:', err);
              wx.showToast({
                title: '文件下载失败',
                icon: 'none'
              });
            }
          });
        }
      }
    });
  },

  // 查看名片
  viewCard(e) {
    const message = e.currentTarget.dataset.message;
    console.log('👤 查看名片:', message);

    wx.showModal({
      title: '联系人名片',
      content: `姓名: ${message.cardName || '未知'}\n电话: ${message.cardPhone || '未知'}`,
      showCancel: true,
      cancelText: '关闭',
      confirmText: '添加联系人',
      success: (res) => {
        if (res.confirm) {
          // TODO: 实现添加联系人功能
          wx.showToast({
            title: '添加联系人功能开发中',
            icon: 'none'
          });
        }
      }
    });
  },

  // 切换主题
  toggleTheme() {
    const next = this.data.themeClass === 'theme-dark' ? 'theme-light' : 'theme-dark';
    const query = wx.createSelectorQuery();
    query.select('.theme-toggle').boundingClientRect();
    query.selectViewport().boundingClientRect();
    query.exec((res) => {
      const btnRect = res && res[0];
      const vpRect = res && res[1];
  // 兜底：左上角区域，和按钮在左侧的位置一致
  let cx = 24;
  let cy = (this.data.statusBarHeight || 0) + 16;
      if (btnRect) {
        cx = btnRect.left + btnRect.width / 2;
        cy = btnRect.top + btnRect.height / 2;
      }
      // 计算到四角的最大距离，得到覆盖半径
      const w = vpRect ? vpRect.width : (this.data.systemInfo?.windowWidth || 375);
      const h = vpRect ? vpRect.height : (this.data.systemInfo?.windowHeight || this.data.windowHeight || 667);
      const dx = Math.max(cx, w - cx);
      const dy = Math.max(cy, h - cy);
      const radius = Math.ceil(Math.sqrt(dx * dx + dy * dy)) + 12;
      const diameter = radius * 2;
      const left = Math.round(cx - radius);
      const top = Math.round(cy - radius);

      // 开启过渡与遮罩
      this.setData({
        isThemeTransitioning: true,
        showThemeOverlay: true,
        overlayPlaying: false,
        overlayTo: next,
        overlayX: cx,
        overlayY: cy,
        overlayDiameter: diameter,
        overlayLeft: left,
        overlayTop: top
      });

      // 下一帧启动遮罩动画，并切换主题变量
      setTimeout(() => {
        this.setData({ overlayPlaying: true, themeClass: next });
        try { wx.setStorageSync('theme', next); } catch (e) { console.warn('保存主题失败', e); }
      }, 16);

      // 动画结束后收尾
      setTimeout(() => {
        this.setData({ showThemeOverlay: false, overlayPlaying: false, isThemeTransitioning: false });
      }, 420);
    });
  },
});