import API from '@/api'
import { getWsUrl } from '@/util/contract.js'
import WsManager from '@/util/wsManager.js'
import {
  decryptoMsg,
  dealErrorMsg,
  noticeManager,
  getUserOpt,
  setUserOpt
} from '@/util/util.js'
import axios from 'axios'
import Message from '@/store/db/Message.js'

var socket = null

const actions = {
  /**
   * @des 获取群基础信息
   * @param {Object} store
   * @param {Object} params
   */
  async getGroupInfo ({ commit, state }, params) {
    API.group.getGroupInfo2({ group_id: state.groupId }, info => {
      if (info.data.code === 0) {
        let data = info.data.data
        let pinMsg = data.pinMsg
        let group = data.group
        let members = data.members
        let eosInfo = data.eosInfo
        let isJoin = data.members.some((item) => {
          return state.userId == item.user_id
        })
        let _members = {}

        pinMsg && (pinMsg.visible = true)
        members.forEach(n => {
          if (!n.user_id) return
          _members[n.user_id] = n
        })

        commit('setGroupInfo', {
          userCounts: members.length,
          groupName: group.group_title,
          shareName: group.group_name,
          members: _members,
          membersArray: members,
          membersNum: data.group.member_num,
          userInfo: data.userInfo,
          groupNotice: group.group_notice,
          url: group.url,
          inviteUrl: group.invite_url,
          sessionInfo: data.sessionInfo || {
            is_mute: 0,
            is_pin: 0,
            pin_time_int: 0
          },
          isJoin,
          coverPhoto: group.cover_photo,
          adminList: data.adminList,
          blockList: data.blockList,
          pinMsg: pinMsg || {},
          creator: group.creator,
          eosInfo: eosInfo
        })
      }
    })
  },
  /**
   * @des 获取最新消息【from indexeddb】【群聊&私聊】
   * @param {Object} store
   * @param {Object} params
   */
  async commonGetNewMsgFromDb (store, params = {}) {
    // 先读取indexDB的数据，来渲染
    let { rootState, state } = store
    const objMessage = new Message()
    let data = await objMessage.getMsg(params.isPrivate ? rootState.curSession : state.groupId)

    setUserOpt('lastShowMsgUid', 0)
    if (data && data.list.length > 0) {
      params.fromdb = true
      actions._renderMsg(store, data, params)
      return true
    } else {
      return false
    }
  },
  /**
   * @des 获取最新消息【不需要登录】【群聊&私聊】
   * @param {Object} store
   * @param {Object} params
   */
  async commonGetNewMsg (store, params = {}) {
    let { rootState, state } = store
    let msg
    // 然后再请求网上的数据，来渲染
    if (params.isPrivate) {
      msg = await API.person.getNewMsg({
        session_id: rootState.curSession,
        client_hash: state.endHash
      }).catch(() => {})
    } else {
      msg = await API.group.getNewMsg({
        group_id: state.groupId,
        client_hash: state.endHash
      }).catch(() => {})
    }

    if (msg && msg.data.code === 0 && msg.data.data.list.length > 0) {
      params.fromdb = false

      actions._renderMsg(store, msg.data.data, params)
    }

    return msg.data
  },
  /**
   * @des 获取历史消息【不需要登录】【群聊&私聊】
   * @param {Object} store
   * @param {Object} params
   */
  async commonGetHistoryMsg (store, params = {}) {
    let { commit, state, rootState } = store
    let his = localStorage.getItem(params.hash) // 先从本地缓存中获取记录
    let cacheData = {}
    let status = '' // 请求状态
    if (his && state.useCache) {
      cacheData = JSON.parse(his)
    } else {
      // 本地缓存中没有记录，从接口获取
      let msg
      if (params.isPrivate) {
        msg = await API.person
          .getHistoryMsg({
            session_id: rootState.curSession,
            client_hash: state.startHash
          })
          .catch(() => {})
      } else {
        msg = await API.group.getHistoryMsg({
          group_id: state.groupId,
          client_hash: state.startHash
        }).catch(() => {})
      }

      if (msg && msg.data.code === 0 && msg.data.data.list.length > 0) {
        cacheData = msg.data.data
      }
    }

    if (cacheData.list && cacheData.list.length > 0) {
      commit('setHash', {
        startHash: cacheData.list[0].hash
      })
      params.fromHistory = true
      this._renderMsg(store, cacheData, params)

      status = 'done'
    } else {
      commit('setHash', {
        startHash: null
      })

      status = 'end'
    }

    return status
  },
  /**
   * 发送消息【群聊&私聊】
   * @param {Object} data
   * @param {Object} params
   */
  commonDoSendMsg ({ dispatch, commit, state, rootState }, params = {}) {
    return new Promise(async (resolve, reject) => {
      let res
      if (params.isPrivate) {
        res = await API.person.sendMsg({
          session_id: rootState.curSession,
          msg_type: params.type,
          msg: params.msg
        })
      } else {
        res = await API.group.sendMsg({
          group_id: state.groupId,
          msg_type: params.type,
          msg: params.msg
        }).catch(err => {
          if (params.createTime) {
            dealErrorMsg(state, params.createTime)
          }
          reject(err)
        })
      }

      let data = res.data
      if (data.code === 0) {
        if (params.createTime) {
          let createTime = params.createTime
          data.data.content = decryptoMsg(data.data.content)
          let list = state.chatList
          for (let i = list.length - 1; i >= 0; i--) {
            let listItem = list[i]
            if (listItem.createTime === createTime) {
              commit('updataChatItem', {
                index: i,
                hash: data.data.hash,
                isCommfirm: true
              })
              break
            }
          }
        } else {
          // 针对用户第一次发言
          commit('updateMembers', data.data.userMap)
          data.data.content = decryptoMsg(data.data.content)
          commit('addChatItem', data.data)
        }
        commit('setHash', {
          endHash: data.data.hash
        })
        commit('updateSessionLastMsgNoDecode', Object.assign(data.data, { group_id: state.groupId }))
        resolve(data.data)
      } else {
        if (params.createTime) {
          dealErrorMsg(state, params.createTime)
        }
      }
    })
  },
  /**
   * @des 消息渲染
   * @param {Boolean} params.isPrivate 是否私聊
   * @param {Boolean} params.fromdb 是否来自indexdb
   * @param {Boolean} params.fromHistory 是否来自历史记录
   */
  _renderMsg ({ commit, state, rootState }, data, params) {
    let list = []

    // 更新聊天userMap
    commit('setGroupMembers', Object.assign(data.userMap, state.members))

    // 解密数据&&计算头像信息
    let lastShowMsgUid = params.fromHistory ? 0 : (getUserOpt('lastShowMsgUid') || 0)
    data.list.forEach(n => {
      let member = state.members[n.from]

      if (!member) return
      // 退群消息只能显示给管理员/自己
      if (n.msg_type == 5 && n.ext_info && n.ext_info.event_type == 'leave_group') {
        if (rootState.userId != n.from && !state.adminList.some(item => item == rootState.userId)) {
          return
        }
      }

      // 解密数据
      if (n.msg_type == 4) {
        // 针对红包类型
        n.msg = typeof n.msg == 'string' ? JSON.parse(decryptoMsg(n.msg)) : n.msg
      } else {
        n.msg = decryptoMsg(n.msg)
      }

      // 显示信息
      list.push({
        name: member.nick_name || member.user_name || 'unknown',
        content: n.msg,
        userId: n.from,
        timestamp: n.create_time_int,
        avatar: member.cover_photo || '',
        hash: n.hash,
        type: n.from == state.userId ? 'me' : 'you',
        msg_type: n.msg_type,
        ext: n.ext ? n.ext : null,
        ext_info: n.ext_info ? n.ext_info : null,
        isShowFullInfo: n.from != lastShowMsgUid
      })
      if (n.msg_type == 5) lastShowMsgUid = 0
      lastShowMsgUid = n.msg_type == 5 ? 0 : n.from
    })

    if (params.fromHistory) {
      // 历史记录
      commit('addHistoryList', list)
    } else {
      // 最新聊天
      setUserOpt('lastShowMsgUid', lastShowMsgUid)
      if (state.chatList.length) {
        commit('setHash', {
          endHash: list[list.length - 1] ? list[list.length - 1].hash : ''
        })
      } else {
        commit('setHash', {
          endHash: list[list.length - 1] ? list[list.length - 1].hash : '',
          startHash: list[0] ? list[0].hash : ''
        })
      }

      let itemData = params.newMsg ? { list: list, newMsg: params.newMsg, fromdb: params.fromdb } : { list: list, fromdb: params.fromdb }
      commit('addChatItem', itemData)
    }
  },
  /**
   * @des 群聊 获取最新消息【from indexeddb】
   * @param {Object} store
   * @param {Object} params
   */
  async getNewMsgFromDb (store, params = {}) {
    params.isPrivate = false
    return actions.commonGetNewMsgFromDb(store, params)
  },
  /**
   * @des 群聊 获取最新消息【不需要登录】
   * @param {Object} store
   * @param {Object} params
   */
  async getNewMsg (store, params = {}) {
    params.isPrivate = false
    return actions.commonGetNewMsg(store, params)
  },
  async getPrivateNewMsgFromDb (store, params = {}) {
    params.isPrivate = true
    return actions.commonGetNewMsgFromDb(store, params)
  },
  /**
   * @des 私聊 获取最新消息【不需要登录】
   * @param {Object} store
   * @param {Object} params
   */
  async getPrivateNewMsg (store, params = {}) {
    params.isPrivate = true
    return actions.commonGetNewMsg(store, params)
  },
  /**
   * @des 群聊 获取历史消息【不需要登录】
   * @param {Object} store
   * @param {Object} params
   */
  async getHistoryMsg (store, params = {}) {
    return actions.commonGetHistoryMsg(store, params)
  },
  /**
   * @des 私聊 获取历史消息【不需要登录】
   * @param {Object} store
   * @param {Object} params
   */
  async getPrivateHistoryMsg (store, params = {}) {
    params.isPrivate = true
    return actions.commonGetHistoryMsg(store, params)
  },
  /**
   * 发送群聊消息
   * @param {Object} data
   * @param {Object} params
   */
  doSendMsg (store, params = {}) {
    params.isPrivate = false
    return actions.commonDoSendMsg(store, params)
  },
  /**
   * 发送聊天文件
   * @param {Object} data
   * @param {Object} params
   */
  async doSendFile ({ commit, state, rootState }, params = {}) {
    return new Promise((resolve, reject) => {
      let userId = rootState.userId
      let token = rootState.token

      let formData = new FormData()
      formData.append('res', params.res)
      formData.append('user_id', userId)
      formData.append('token', token)

      // 私聊群聊参数调整
      if (state.groupId) {
        formData.append('group_id', state.groupId)
      } else {
        let arr = rootState.curSession.split('-')
        let toUser

        if (arr[0] == rootState.userId) toUser = arr[1]
        else toUser = arr[0]

        formData.append('to_user', toUser)
      }

      let sendUrl = state.groupId ? 'group/sendFile' : 'person/sendFile'
      axios({
        url: [API.host, sendUrl].join(''),
        method: 'post',
        data: formData,
        headers: { 'Content-Type': 'multipart/form-data' }
      })
        .then(({ data }) => {
          if (data.code === 0) {
            if (params.createTime) {
              let createTime = params.createTime
              data.data.content = decryptoMsg(data.data.content)
              let list = state.chatList
              list.forEach(item => {
                if (item.createTime === createTime) {
                  item.res = undefined
                  item.content = data.data.content
                  item.hash = data.data.hash
                  item.loading = false
                  item.fail = false

                  if (!item.ext_info) item.ext_info = {}
                  item.ext_info.cover_url = data.data.ext_info && data.data.ext_info.cover_url
                }
              })
            } else {
              // 针对用户第一次发言
              commit('updateMembers', data.data.userMap)
              data.data.content = decryptoMsg(data.data.content)
              commit('addChatItem', data.data)
            }

            commit('setHash', {
              endHash: data.data.hash
            })
            commit('updateSessionLastMsgNoDecode', Object.assign(data.data, { group_id: state.groupId || rootState.curSession }))
            resolve(data.data)
          } else {
            if (params.createTime) {
              dealErrorMsg(state, params.createTime)
            }
          }
        })
        .catch(err => {
          if (params.createTime) {
            dealErrorMsg(state, params.createTime)
          }
          reject(err)
        })
    })
  },
  /**
   * 发送私聊消息
   * @param {Object} data
   * @param {Object} params
   */
  doSendPrivateMsg (store, params = {}) {
    params.isPrivate = true
    return actions.commonDoSendMsg(store, params)
  },
  /**
   * 链接websocket
   * @param {Object} data
   * @param {Object} params
   */
  initSocket ({ commit, state, rootState, rootGetters, dispatch }, params = {}) {
    if (!window.WebSocket) {
      console.error('Error: WebSocket is not supported .')
      return
    }

    let host = `${getWsUrl()}/?user_id=${rootState.userId}&token=${
      rootState.token
    }`
    if (socket) {
      socket.destroy()
      socket = null
    }

    socket = new WsManager(host, {
      autoConnect: true, // 自动连接
      reconnection: true, // 断开自动重连
      reconnectionDelay: 5000, // 重连间隔时间，单位秒
      keepAliveContent: JSON.stringify({ act: 'alive', player: name }) // 心跳包内容
    })

    socket.on('open', res => {})

    socket.on('message', e => {
      let _data = JSON.parse(e)
      let channel = _data.channel
      let data = _data.data
      let muteList = rootGetters.muteList // 免打扰列表

      // 群聊
      if (channel.match('chat:group')) {
        let isMute = muteList.some(v => {
          return v.session_id == data.group_id
        })
        if (data.type === 'msg') {
          if (rootState.curSession == data.group_id) {
            // 当前会话需要加载新消息
            dispatch('getNewMsg', { newMsg: true })

            if (data.from != rootState.userId) commit('addUnreadNums')
          }

          if (!isMute) {
            noticeManager.showNotification(data)
          }
        }
        if (data.type === 'update') {
        }
        if (data.type === 'add_admin') {
        }
        if (data.type === 'remove_admin') {
        }
        if (data.type === 'repeal') {
          commit('repealChatItem', data)
          // 左侧会话
          data.msg_type = -1
          commit('updateSessionLastmsg', data)
        }
        if (data.type === 'block') {
          commit('updateGroupBlockList', {
            type: 'add',
            id: data.to
          })
        }
        if (data.type === 'unblock') {
          commit('updateGroupBlockList', {
            type: 'delete',
            id: data.to
          })
        }

        if (data.type === 'leave' && data.group_id == state.groupId) {
          if (data.user_info.user_id == rootState.userId) return // 本人-不走这个ws

          // 本人退出刷新群信息
          if (data.user_id == rootState.userId) {
            dispatch('getGroupInfo')
          } else {
            commit('updateMembersArray', {
              type: 'del',
              userInfo: data.user_info
            })
          }
        }

        if (data.type === 'join' && data.group_id == state.groupId) {
          if (data.user_info.user_id == rootState.userId) return

          data.joinMsg = (data.user_info.nick_name || data.user_info.name) + '加入群组'

          commit('updateMembers', {
            [data.user_info.user_id]: data.user_info
          })
          commit('updateMembersArray', {
            type: 'add',
            userInfo: data.user_info
          })
          // commit('addChatItem', data)
        }

        if (data.type === 'pin_msg' && data.group_id == state.groupId) {
          commit('updateGroupPinMsg', data.pinMsg)
        }

        if (data.type === 'unpin_msg' && data.group_id == state.groupId) {
          commit('updateGroupPinMsg', null)
        }

        if (data.type === 'new_redpack' && rootState.curSession == data.group_id) {
          commit('addPacketItem', data)

          commit('updateSessionLastmsg', data)
        }

        if (data.type === 'grab_redpack' && rootState.curSession == data.group_id) {
          if (data.from == rootState.userId || data.to == rootState.userId) {
            commit('addPacketTip', data)
            commit('updateSessionLastmsg', data)
          }
        }
      }

      // 私聊
      if (channel.match('chat:person')) {
        if (!rootState.curSession) return
        let curId = +data.to > +data.from ? `${data.from}-${data.to}` : `${data.to}-${data.from}`
        let isMute = muteList.some(v => {
          return v.session_id == curId
        })
        if (data.type === 'msg') {
          if (rootState.curSession == curId) {
            // 当前会话需要加载新消息
            dispatch('getPrivateNewMsg')

            if (data.from != rootState.userId) commit('addUnreadNums')
          }

          // 如果在隐藏tab就需要 通知
          if (!isMute) {
            noticeManager.showNotification(data)
          }
        }
        if (data.type === 'repeal') {
          commit('repealChatItem', data)
          let sessionId = data.from > data.to ? `${data.to}-${data.from}` : `${data.from}-${data.to}`
          data.group_id = sessionId
          data.msg_type = -1
          commit('updateSessionLastmsg', data)
        }
        // if (data.type === 'new_redpack' && rootGetters.otherUserId == data.from) {
        if (data.type === 'new_redpack') {
          commit('addPacketItem', data)
        }
        if (data.type === 'grab_redpack' && rootGetters.otherUserId == data.from) {
          if (data.from == rootState.userId || data.to == rootState.userId) {
            commit('addPacketTip', data)
          }
        }

        if (data.type === 'join_group') {
          commit('updateMembers', {
            [rootState.userInfo.user_id]: rootState.userInfo
          })
          commit('updateMembersArray', {
            type: 'add',
            userInfo: rootState.userInfo
          })
          // commit('addChatItem', data)
        }

        if (data.type === 'leave_group') {
          commit('updateMembersArray', {
            type: 'del',
            userInfo: rootState.userInfo
          })
          // commit('addChatItem', data)
          dispatch('getGroupInfo')
        }
      }

      // 有新session 更新sessionList-自己退群不做处理
      let isLeaveGroup = data.msg_type == 5 && data.ext_info.event_type == 'leave_group'
      if (!isLeaveGroup && (data.type === 'msg' || data.type === 'new_redpack')) {
        let sessionList = rootState.chat.sessionList
        let curId
        if (data.group_id) {
          curId = data.group_id
        } else {
          curId = +data.to > +data.from ? `${data.from}-${data.to}` : `${data.to}-${data.from}`
        }
        let isInSession = sessionList.some(v => {
          return v.session_id == curId
        })

        let baseObj = {
          session_id: curId,
          cont: decryptoMsg(data.content),
          unread: rootState.userId == data.from ? 0 : 1,
          update_time_int: data.timestamp,
          timestamp: data.timestamp
        }

        if (!isInSession) {
          if (!data.group_id) {
            // 私聊要拿对方的头像
            API.user.getOtherInfo({
              target_id: rootState.userId === data.from ? data.to : data.from
            }).then(({ data }) => {
              let obj = {
                cover_photo: data.data.cover_photo,
                is_group: '0',
                name: data.data.nick_name
              }
              commit('addSessionItem', Object.assign(obj, baseObj))
            })
          } else {
            API.group.getGroupInfo({
              group_id: data.group_id
            }).then(({ data }) => {
              let group = data.data.group
              let obj = {
                cover_photo: group.cover_photo,
                is_group: '1',
                is_auth: group.is_auth,
                name: group.group_title
              }
              commit('addSessionItem', Object.assign(obj, baseObj))
            })
          }
        }

        if (data.from != rootState.userId) {
          commit('setSessionItemUnread', Object.assign({ curSession: rootState.curSession }, baseObj))
        }
        commit('updateSessionLastmsg', Object.assign(data, { sessionId: curId }))
      }
    })
  },
  /**
   * 撤回消息
   * @param {Object} params
   * {index:number, session_id:string, hash:string}
   */
  async doRepealGroupMsg ({ dispatch, commit, state }, params = {}) {
    try {
      await API.group.repealGroupMsg({
        group_id: state.groupId,
        hash: params.hash
      })
    } catch (error) {}
  },
  /**
   * 封禁群用户
   */
  async doBlockUser ({ state }, params = {}) {
    try {
      await API.group.blockUser({
        group_id: state.groupId,
        block_id: params.id
      })
    } catch (error) {}
  },
  /**
   * 解禁用户
   */
  async doUnBlockUser ({ state }, params = {}) {
    try {
      await API.group.unblockUser({
        group_id: state.groupId,
        block_id: params.id
      })
    } catch (error) {}
  },
  /**
   * 更新置顶
   */
  async doPinMsg ({ state }, params = {}) {
    try {
      await API.group.pinMsg({
        group_id: state.groupId,
        hash: params.hash
      })
    } catch (error) {}
  },
  /**
   * 取消置顶
   */
  async doUnpinMsg ({ state }, params = {}) {
    try {
      await API.group.unpinMsg({
        group_id: state.groupId,
        hash: params.hash
      })
    } catch (error) {}
  },
  /**
   * 加入群组
   */
  async joinGroup ({ state, commit }, params = {}) {
    try {
      await API.group.joinGroup({
        group_id: state.groupId
      })
      commit('updateJoin', true)
      commit('changeHotGroupStatus', {
        groupId: state.groupId,
        isJoin: 1
      })
    } catch (error) {}
  }
}

export default actions
