import { MESSAGE_TYPE_MAP } from './config';
import { formatTime, isJsonStr } from './helper';

const INSERT_TIME_DURATION = 1 * 60 * 60;

export interface UserInfo {
  uid: string;
  avatar: string;
  nick: string;

  isOwner: boolean;
  laddergrade?: string;

  cardInfo?: {
    phone?: string | number;
    wx_account?: string | number;
    qq_account?: string | number;
  }
}

export interface RawMessageItem {
  time: number;

  from: string;
  to: string;

  payload?: {
    text: string;
  };
  ID?: string;
  isCustomFail: boolean;

  isPeerRead: boolean;
  isRevoked: boolean;
}

export interface ParsedMessageItemContent {
  text: string;

  title?: string;
  link?: string;
  picUrl?: string;

  phone?: string | number;
  wechat?: string | number;
  qq?: string | number;
}

export interface ParsedMessageItem {
  id: string;
  time: string;
  timeStamp: number;
  msgType: string;

  parsedText: Record<string, any>;

  from: string;
  to: string;
  isPeerRead: boolean;
  isCustomFail: boolean;

  avatar: string;
  nick: string;
  uid: string;
  isMine: boolean;

  isOwner: boolean;
  laddergrade?: string;
  content: ParsedMessageItemContent;
  isRevoked: boolean;
}


function formatMessageContent(message: string, userInfo?: UserInfo): ParsedMessageItemContent {
  if (!isJsonStr(message)) {
    return { text: message };
  }
  let info: {
    title?: string;
    content?: string;
    jumpUrl?: string;
    picUrl?: string;
  } = {};

  try {
    info = JSON.parse(message);
  } catch (e) {
    return { text: message };
  }

  return {
    title: info.title || '',
    text: info.content || '',
    link: info.jumpUrl || '',
    picUrl: info.picUrl || '',

    phone: userInfo?.cardInfo?.phone || '',
    wechat: userInfo?.cardInfo?.wx_account || '',
    qq: userInfo?.cardInfo?.qq_account || '',
  };
}

function addTimeMsg(list: Array<{
  timeStamp: number;
  msgType: string;
  id: string;
  content: {
    text: string;
  }
}>, lastTime: number) {
  if (!list.length) return;

  let recentTime = list[list.length - 1].timeStamp;
  if (lastTime) {
    recentTime = lastTime;
  }

  // 倒序插入，如果从前往后插，index会变
  for (let i = list.length - 1;i >= 0;i--) {
    const item = list[i];

    if (recentTime > item.timeStamp + INSERT_TIME_DURATION) {
      const nextTime = list[i + 1].timeStamp;

      list.splice(i + 1, 0, {
        msgType: MESSAGE_TYPE_MAP.TIME,
        id: `id-time-${i + 1}-${nextTime}`,
        timeStamp: nextTime,
        content: {
          text: formatTime(nextTime),
        },
      });

      recentTime = item.timeStamp;
    }
  }
  // 在第一个之前插入时间tag
  // 如果传入lastTime，说明是接收信息，则只有在这条消息超过 INSERT_TIME_DURATION 后才再次插入tag
  if (!lastTime || list?.[0]?.timeStamp > lastTime + INSERT_TIME_DURATION) {
    list.splice(0, 0, {
      msgType: MESSAGE_TYPE_MAP.TIME,
      id: `id-time-0-${list[0].id}`,
      timeStamp: list[0].timeStamp,
      content: {
        text: formatTime(list[0].timeStamp),
      },
    });
  }
}


function deleteRevokedMessages<T extends {
  isRevoked?: boolean;
}>(list: Array<T>) {
  return list = list.filter(item => !item.isRevoked);
}


export function baseFormatMessageDetailList(
  list: Array<RawMessageItem>,
  myInfo: UserInfo,
  oppositeInfo: UserInfo,
  lastTimeStampTag: number,
): ParsedMessageItem[] {
  let mList = list as unknown as ParsedMessageItem[];
  mList = deleteRevokedMessages(mList) as unknown as ParsedMessageItem[];

  mList = (mList as unknown as RawMessageItem[])
    .map((item) => {
      const { time, from, to, payload, isPeerRead, ID: id, isCustomFail, isRevoked } = item;
      const { text = '' } = payload || {};
      const isMine = from === myInfo.uid;
      const uid = isMine ? myInfo.uid : oppositeInfo.uid;

      let parsedText = {};
      if (text && isJsonStr(text)) {
        try {
          parsedText = JSON.parse(text);
        } catch (e) {
          parsedText = {};
        }
      }

      return {
        id: `id-${id}`,
        time: formatTime(time as unknown as number),
        timeStamp: (time as unknown as number),
        msgType: MESSAGE_TYPE_MAP.MESSAGE_TEXT,

        parsedText,

        from,
        to,
        isPeerRead,
        isCustomFail,

        avatar: isMine ? myInfo.avatar : oppositeInfo.avatar,
        nick: isMine ? myInfo.nick : oppositeInfo.nick,
        uid,
        isMine,

        isOwner: isMine ? myInfo.isOwner : oppositeInfo.isOwner,
        laddergrade: isMine ? myInfo.laddergrade : oppositeInfo.laddergrade,
        content: formatMessageContent(text, isMine ? myInfo : oppositeInfo),
        isRevoked,
      };
    });

  addTimeMsg(mList, lastTimeStampTag);
  return mList;
}


