/**
 * 聊天室管理器
 * 封装聊天室相关操作，包括进入房间、离开房间、发送消息、接收消息、管理未读数等
 */
import { chatConfig } from '@/config/chat.js';
import { sendWebSocketMessage, isWebSocketConnected } from '@/utils/ws/initWebSocket.js';
import { getChatRegisterInfoApi, getMessagesByRoomIdApi } from '@/api/chat.js';
import { getMessagePreview } from '@/utils/chat/messagePreview.js';

function unwrapMessagesPayload(res) {
  if (res == null) return null;
  if (res.result !== undefined && res.result !== null) return res.result;
  if (res.data && res.data.result !== undefined && res.data.result !== null) return res.data.result;
  if (res.data && typeof res.data === 'object') return res.data;
  return res;
}

/** 房间 ID 归一化，便于 WS 与列表接口字段比较 */
export function normalizeRoomId(id) {
  return String(id == null ? '' : id).trim();
}

/** 仅在工作台 / 在线接诊列表为栈顶页时派发列表增量，减少后台页无意义合并 */
function shouldEmitDoctorImListUpdate() {
  const pages = typeof getCurrentPages === 'function' ? getCurrentPages() : [];
  const cur = pages && pages.length ? pages[pages.length - 1] : null;
  const route = cur && cur.route ? cur.route : '';
  return (
    route === 'pages/workbench/index' ||
    route === 'subPackages/sub_online_reception/pages/list'
  );
}

/**
 * 聊天室管理器类
 */
class ChatRoomManager {
  constructor() {
    // 当前房间ID
    this.currentRoomId = null;
    
    // 最后一条消息ID（用于分页加载）
    this.lastMessageId = 0;
    
    // 未读数（按房间ID存储）
    this.unreadCounts = {};
    
    // 消息缓存（按房间ID存储）
    this.roomMessages = {};
    
    // 消息处理器列表
    this.messageHandlers = [];
  }
  
  /**
   * 进入聊天室
   * @param {string} roomId - 房间ID
   * 职责：设置当前房间，重置未读数，保存到本地存储
   */
  enterRoom(roomId) {
    const id = normalizeRoomId(roomId);
    if (!id) {
      console.warn('房间ID不能为空');
      return;
    }

    this.currentRoomId = id;
    uni.setStorageSync('currentRoomId', id);
    this.resetUnreadCount(id);

    console.log('进入聊天室:', id);
  }
  
  /**
   * 离开聊天室
   * 职责：清空当前房间，移除本地存储
   */
  leaveRoom() {
    this.currentRoomId = null;
    uni.removeStorageSync('currentRoomId');
    console.log('离开聊天室');
  }
  
  /**
   * 获取当前房间ID
   * @returns {string|null} 当前房间ID
   */
  getCurrentRoomId() {
    return this.currentRoomId || uni.getStorageSync('currentRoomId');
  }
  
  /**
   * 增加未读数
   * @param {string} roomId - 房间ID
   * 职责：如果房间不是当前房间，则增加未读数并通知
   */
  increaseUnreadCount(roomId) {
    const key = normalizeRoomId(roomId);
    if (!key) return;

    if (normalizeRoomId(this.getCurrentRoomId()) === key) {
      return;
    }

    this.unreadCounts[key] = (this.unreadCounts[key] || 0) + 1;
    this.notifyUnreadChange();
  }
  
  /**
   * 重置未读数
   * @param {string} roomId - 房间ID
   * 职责：将指定房间的未读数重置为0并通知
   */
  resetUnreadCount(roomId) {
    const key = normalizeRoomId(roomId);
    if (this.unreadCounts[key]) {
      this.unreadCounts[key] = 0;
      this.notifyUnreadChange();
    }
  }
  
  /**
   * 获取未读数
   * @param {string} roomId - 房间ID
   * @returns {number} 未读数
   */
  getUnreadCount(roomId) {
    const key = normalizeRoomId(roomId);
    return this.unreadCounts[key] || 0;
  }
  
  /**
   * 获取所有未读数总和
   * @returns {number} 总未读数
   */
  getAllUnreadCount() {
    return Object.values(this.unreadCounts).reduce((sum, count) => sum + count, 0);
  }
  
  /**
   * 格式化未读数显示
   * @param {string} roomId - 房间ID
   * @returns {string} 格式化后的未读数
   */
  getFormattedUnreadCount(roomId) {
    const count = this.getUnreadCount(roomId);
    return chatConfig.formatUnreadCount(count);
  }
  
  /**
   * 通知未读数变化
   * 职责：触发未读数更新事件
   */
  notifyUnreadChange() {
    uni.$emit('unread-message-update', {
      total: this.getAllUnreadCount(),
      byRoom: { ...this.unreadCounts }
    });
  }
  
  /**
   * 添加消息到房间
   * @param {string} roomId - 房间ID
   * @param {Object} message - 消息对象
   * 职责：将消息添加到指定房间的消息列表
   */
  addMessageToRoom(roomId, message) {
    const key = normalizeRoomId(roomId);
    if (!key || !message) return;

    if (!this.roomMessages[key]) {
      this.roomMessages[key] = [];
    }

    // 检查消息是否已存在（避免重复）
    const existingIndex = this.roomMessages[key].findIndex(m => m.id === message.id);
    if (existingIndex !== -1) {
      this.roomMessages[key][existingIndex] = message;
    } else {
      this.roomMessages[key].push(message);
    }
  }
  
  /**
   * 获取房间消息列表
   * @param {string} roomId - 房间ID
   * @returns {Array} 消息列表
   */
  getRoomMessages(roomId) {
    const key = normalizeRoomId(roomId);
    return this.roomMessages[key] || [];
  }
  
  /**
   * 加载房间消息
   * @param {string} roomId - 房间ID
   * @param {number} lastMessageId - 最后一条消息ID（可选，用于分页）
   * @returns {Promise<Array>} 消息列表
   */
  async loadRoomMessages(roomId, lastMessageId = 0) {
    const key = normalizeRoomId(roomId);
    if (!key) {
      console.warn('房间ID不能为空');
      return [];
    }

    try {
      const res = await getMessagesByRoomIdApi({
        room_id: key,
        last_message_id: lastMessageId || 0
      });

      const payload = unwrapMessagesPayload(res);
      if (payload && typeof payload === 'object') {
        const rawList = payload.list;
        const list = Array.isArray(rawList) ? rawList : rawList != null ? [rawList] : [];
        const messages = this.processMessages(list);
        this.lastMessageId = payload.last_message_id || 0;

        // 如果是首次加载，替换消息列表；否则追加到前面
        if (lastMessageId === 0) {
          this.roomMessages[key] = messages;
        } else {
          this.roomMessages[key] = [...messages, ...(this.roomMessages[key] || [])];
        }

        uni.$emit('load-room-message', lastMessageId === 0 ? 1 : 0);
        return messages;
      }
      
      return [];
    } catch (error) {
      console.error('加载房间消息失败:', error);
      return [];
    }
  }
  
  /**
   * 处理消息数据
   * @param {Array|Object} messages - 消息数据（数组或单个消息）
   * @returns {Array|Object} 处理后的消息
   */
  processMessages(messages) {
    if (!Array.isArray(messages)) {
      return this.processSingleMessage(messages);
    }
    
    return messages.map((item) => {
      const result = {
        id: item.id,
        sender_user_id: item.sender_user_id,
        receiver_user_id: item.receiver_user_id,
        message_type: item.message_type,
        message_content: item.message_content,
        duration: item.duration,
        room_id: item.room_id,
        created_at: item.created_at || item.send_time,
        created_at_text: item.created_at_text || this.formatTime(item.send_time || item.created_at),
        timestamp: item.send_time || item.created_at
      };
      
      // 如果是挂号消息（type=10），异步加载详细信息
      if (item.message_type === 10) {
        this.loadRegisterInfo(result);
      }
      
      return result;
    });
  }
  
  /**
   * 处理单个消息
   * @param {Object} message - 消息对象
   * @returns {Object} 处理后的消息
   */
  processSingleMessage(message) {
    return {
      id: message.id,
      sender_user_id: message.sender_user_id,
      receiver_user_id: message.receiver_user_id,
      message_type: message.message_type,
      message_content: message.message_content,
      duration: message.duration,
      room_id: message.room_id,
      created_at: message.created_at || message.send_time,
      created_at_text: message.created_at_text || this.formatTime(message.send_time || message.created_at),
      timestamp: message.send_time || message.created_at
    };
  }
  
  /**
   * 格式化时间（HH:mm），时间戳支持秒或毫秒
   * @param {number} timestamp
   * @returns {string}
   */
  formatTime(timestamp) {
    if (timestamp === undefined || timestamp === null || timestamp === '') return '';
    const n = Number(timestamp);
    if (Number.isNaN(n)) return '';
    const ms = n > 1e12 ? n : n * 1000;
    const date = new Date(ms);
    const hours = date.getHours().toString().padStart(2, '0');
    const minutes = date.getMinutes().toString().padStart(2, '0');
    return `${hours}:${minutes}`;
  }
  
  /**
   * 加载挂号信息（异步）
   * @param {Object} message - 消息对象
   * 职责：为挂号消息加载详细信息
   */
  loadRegisterInfo(message) {
    const parsedContent = this.parseMessageContent(message.message_content);
    if (parsedContent._loaded || !parsedContent.id) return;
    
    getChatRegisterInfoApi({ 
      id: parsedContent.id, 
      message_id: message.id || '' 
    }).then((res) => {
      const info = res && (res.result != null ? res.result : res.data && res.data.result);
      if (res && info) {
        const resultWithFlag = { ...info, _loaded: true };
        const roomId = message.room_id;
        const roomMessages = this.roomMessages[roomId];
        
        if (roomMessages) {
          const index = roomMessages.findIndex(m => m.id === message.id);
          if (index !== -1) {
            roomMessages[index].message_content = JSON.stringify(resultWithFlag);
            uni.$emit('message-updated', { roomId, messageId: message.id });
          }
        }
      }
    }).catch(error => {
      console.error('加载挂号信息失败:', error);
    });
  }
  
  /**
   * 解析消息内容
   * @param {string|Object} content - 消息内容
   * @returns {Object|string} 解析后的内容
   */
  parseMessageContent(content) {
    try {
      return typeof content === 'object' ? content : JSON.parse(content);
    } catch (e) {
      return content;
    }
  }
  
  /**
   * 通过 WebSocket 发送消息（request_type: send_message）。
   * 在线接诊聊天页（sub_online_reception/pages/chat.vue）主路径已改为 Go IM `POST /api/send-to-user`（与 websocket 配置同基址），
   * 此处保留供其它仍走 WS 直发的场景；新页面发聊天消息请优先使用 HTTP API。
   * @param {Object} messageData - 消息数据
   * @param {string} messageData.room_id - 房间ID
   * @param {string} messageData.sender_user_id - 发送者ID
   * @param {string} messageData.receiver_user_id - 接收者ID
   * @param {number|string} messageData.message_type - 消息类型
   * @param {string} messageData.message_content - 消息内容
   * @param {number} messageData.duration - 语音时长（可选）
   * @returns {boolean} 是否发送成功
   */
  sendMessage(messageData) {
    if (!isWebSocketConnected()) {
      console.error('WebSocket未连接，无法发送消息');
      return false;
    }
    
    // 确保消息类型是数字
    let messageType = messageData.message_type;
    if (typeof messageType === 'string') {
      messageType = chatConfig.getMessageType(messageType);
    }
    
    const message = {
      request_type: 'send_message',
      room_id: messageData.room_id,
      sender_user_id: messageData.sender_user_id,
      receiver_user_id: messageData.receiver_user_id,
      message_type: messageType,
      message_content: messageData.message_content || '',
      duration: messageData.duration || 0
    };
    
    return sendWebSocketMessage(message);
  }
  
  /**
   * 注册消息处理器
   * @param {Function} handler - 消息处理函数
   * 职责：注册消息处理器，当收到WebSocket消息时调用
   */
  onMessage(handler) {
    if (typeof handler !== 'function') {
      console.warn('消息处理器必须是函数');
      return;
    }
    
    this.messageHandlers.push(handler);
  }
  
  /**
   * 移除消息处理器
   * @param {Function} handler - 消息处理函数
   */
  offMessage(handler) {
    const index = this.messageHandlers.indexOf(handler);
    if (index !== -1) {
      this.messageHandlers.splice(index, 1);
    }
  }
  
  /**
   * 处理收到的WebSocket消息
   * @param {Object} data - WebSocket消息数据
   * 职责：处理收到的消息，更新未读数，调用注册的处理器
   */
  handleWebSocketMessage(data) {
    // 只处理聊天消息
    if (data.request_type !== 'receive_message' && !data.room_id) {
      return;
    }

    const roomId = normalizeRoomId(data.room_id);
    if (!roomId) return;

    const dataNorm = { ...data, room_id: roomId };

    // 处理消息
    const message = this.processSingleMessage(dataNorm);

    // 添加到房间消息列表
    this.addMessageToRoom(roomId, message);

    const currentNorm = normalizeRoomId(this.getCurrentRoomId());
    const incrementUnread = currentNorm !== roomId;

    // 如果不是当前房间，增加未读数
    if (incrementUnread) {
      this.increaseUnreadCount(roomId);
    }

    // 调用所有注册的处理器
    this.messageHandlers.forEach(handler => {
      try {
        handler(message, roomId);
      } catch (error) {
        console.error('消息处理器执行失败:', error);
      }
    });

    const lastMessageTime =
      dataNorm.send_time != null && dataNorm.send_time !== ''
        ? dataNorm.send_time
        : dataNorm.created_at != null && dataNorm.created_at !== ''
          ? dataNorm.created_at
          : message.timestamp != null && message.timestamp !== ''
            ? message.timestamp
            : message.created_at;

    const unreadForRoom = this.getUnreadCount(roomId);

    if (shouldEmitDoctorImListUpdate()) {
      uni.$emit('doctor-im-room-update', {
        roomId,
        last_message_preview: getMessagePreview(dataNorm),
        last_message_time: lastMessageTime,
        incrementUnread,
        unreadForRoom
      });
    }
  }
  
  /**
   * 清空房间消息缓存
   * @param {string} roomId - 房间ID（可选，不传则清空所有）
   */
  clearRoomCache(roomId = null) {
    if (roomId) {
      const key = normalizeRoomId(roomId);
      if (key) delete this.roomMessages[key];
    } else {
      this.roomMessages = {};
    }
  }
}

// 导出单例
export const chatRoomManager = new ChatRoomManager();
