import BaseModel from './BaseModel';
import { index, getModelForClass, prop, DocumentType, modelOptions } from '@typegoose/typegoose';

export class PrivateChatRec {
  @prop({ required: true, default: '' })
  targetRoleId: string; // 聊天玩家 roleId
  @prop({ required: false })
  lastReadTime: Date; // 最后查看时间，用来检查未读消息数
  @prop({ required: true })
  lastChatTime: Date; // 最后聊天时间
  @prop({ required: true, default: 0 })
  unreadCnt: number; // 未读消息数
  @prop({ required: true })
  isTop: boolean; // 是否置顶
  @prop({ required: true })
  setTopTime: Date; // 置顶时间
}

/**
  * 记录聊天信息，包含配置、最近聊天等
**/
@modelOptions({ schemaOptions: { id: false } })
@index({ roleId: 1 })
export default class ChatInfo extends BaseModel {
  @prop({ required: true, default: '' })
  roleId: string; // 消息发送者 roleId
  @prop({ required: true, default: '' })
  roleName: string; // 消息发送者名称

  @prop({ required: true, type: String, default: [] })
  sources: [string]; // 打开的消息来源，主要用于系统通知筛选
  @prop({ required: true, type: String, default: [] })
  BSChannels: [string]; // 弹幕打开的频道，BS：bullet screen
  @prop({ required: true, type: String, default: [] })
  BSSources: [string]; // 弹幕打开的消息来源
  @prop({ required: true, default: '' })
  bubbleId: string; // 气泡编号
  @prop({ required: true, type: PrivateChatRec, default: [], _id: false })
  recentPrivateChats: PrivateChatRec[]; // 最近聊天列表

  public static async createInfo(data: ChatInfoParam) {
    const roleId = data.roleId!;
    const docData = new ChatInfoModel();
    const result: ChatInfoType = await ChatInfoModel.findOneAndUpdate({ roleId }, { ...docData.toJSON(), ...data }, { upsert: true, new: true }).select('-_id').lean();
    return result;
  }

  public static async findInfo(roleId: string) {
    let result: ChatInfoType = await ChatInfoModel.findOne({ roleId }).select('-_id').lean();
    return result;
  }

  public static async updateInfo(data: ChatInfoParam) {
    const roleId = data.roleId!;
    const result: ChatInfoType = await ChatInfoModel.findOneAndUpdate({ roleId }, { $set: { ...data } }, { new: true }).select('-_id').lean();
    return result;
  }

  public static async updateReadInfo(roleId: string, targetRoleId: string, time: Date) {
    const result: ChatInfoType = await ChatInfoModel
      .findOneAndUpdate(
        { roleId, 'recentPrivateChats.targetRoleId': targetRoleId },
        { 'recentPrivateChats.$.lastReadTime': time, 'recentPrivateChats.$.unreadCnt': 0 },
        { new: true })
      .select('-_id').lean();
    return result;
  }

  public static async setTop(roleId: string, targetRoleId: string, isTop: boolean, time: Date) {
    const result: ChatInfoType = await ChatInfoModel
      .findOneAndUpdate(
        { roleId, 'recentPrivateChats.targetRoleId': targetRoleId },
        { 'recentPrivateChats.$.isTop': isTop, 'recentPrivateChats.$.setTopTime': time },
        { new: true })
      .select('-_id').lean();
    return result;
  }

  public static async delMsg(roleId: string, targetRoleId: string) {
    const result: ChatInfoType = await ChatInfoModel
      .findOneAndUpdate(
        { roleId },
        { $pull: { recentPrivateChats: { targetRoleId } } },
        { new: true })
      .select('-_id').lean();
    return result;
  }
}

export const ChatInfoModel = getModelForClass(ChatInfo);

export interface ChatInfoType extends Pick<DocumentType<ChatInfo>, keyof ChatInfo> {};
export type ChatInfoParam = Partial<ChatInfoType>;
