
package com.tmerclub.cloud.im.service.impl;

import cn.hutool.core.date.DateUtil;
import com.tmerclub.cloud.api.auth.bo.UidInfoBO;

import com.tmerclub.cloud.api.multishop.bo.EsShopDetailBO;
import com.tmerclub.cloud.api.multishop.feign.ShopUserFeignClient;
import com.tmerclub.cloud.api.multishop.vo.ShopUserVO;
import com.tmerclub.cloud.api.platform.feign.SysUserFeignClient;
import com.tmerclub.cloud.api.platform.vo.SysUserVO;
import com.tmerclub.cloud.api.user.vo.UserApiVO;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.im.constants.*;
import com.tmerclub.cloud.im.mapper.ImMsgBizUserHistoryMapper;
import com.tmerclub.cloud.im.model.ImMsgBizUser;
import com.tmerclub.cloud.im.model.ImMsgBizUserHistory;
import com.tmerclub.cloud.im.service.ImMsgBizEmployeeRecentService;
import com.tmerclub.cloud.im.service.ImMsgBizUserHistoryService;
import com.tmerclub.cloud.im.service.ImMsgBizUserService;
import com.tmerclub.cloud.im.vo.MessageInfoVO;
import com.tmerclub.cloud.im.vo.MsgItemVO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 店铺和用户历史聊天记录表
 *
 * @author tmerclub
 * @date 2021-08-25 13:58:56
 */
@Service
public class ImMsgBizUserHistoryServiceImpl implements ImMsgBizUserHistoryService {

    @Autowired
    private ImMsgBizUserHistoryMapper imMsgBizUserHistoryMapper;

    @Autowired
    private ImMsgBizUserService imMsgBizUserService;

    @Autowired
    private ImMsgBizEmployeeRecentService imMsgBizEmployeeRecentService;

    @DubboReference
    private SysUserFeignClient sysUserFeignClient;

    @DubboReference
    private ShopUserFeignClient shopUserFeignClient;

    @Override
    public PageVO<ImMsgBizUserHistory> pageBySendTypeBizIdUserId(PageDTO pageDTO, Integer sendType, Long bizId, Long employeeId, Long userId) {
        PageVO<ImMsgBizUserHistory> page = PageUtil.doPage(pageDTO, () -> imMsgBizUserHistoryMapper.listBySendTypeBizIdUserId(sendType, bizId, employeeId, userId));
        List<Long> employeeIds = page.getList().stream().map(ImMsgBizUserHistory::getEmployeeId).collect(Collectors.toList());
        Map<Long, String> nickNameMap;
        // 查询平台的客服昵称
        if (Objects.equals(sendType, SendType.PLATFORM)) {
            List<SysUserVO> sysUserList = sysUserFeignClient.getImSysUserList(employeeIds);
            nickNameMap = sysUserList.stream().collect(Collectors.toMap(SysUserVO::getSysUserId, SysUserVO::getNickName));
        } else if (Objects.equals(sendType, SendType.SHOP)) {
            List<ShopUserVO> sysUserList = shopUserFeignClient.getImShopUserList(employeeIds);
            nickNameMap = sysUserList.stream().collect(Collectors.toMap(ShopUserVO::getShopUserId, ShopUserVO::getNickName));
        } else {
            nickNameMap = new HashMap<>(0);
        }
        for (ImMsgBizUserHistory imMsgBizUserHistory : page.getList()) {
            if (!nickNameMap.containsKey(imMsgBizUserHistory.getEmployeeId())) {
                continue;
            }
            imMsgBizUserHistory.setNickName(nickNameMap.get(imMsgBizUserHistory.getEmployeeId()));
        }
        return page;
    }

    @Override
    public ImMsgBizUserHistory getById(Long id) {
        return imMsgBizUserHistoryMapper.getById(id);
    }

    @Override
    public ImMsgBizUserHistory getByParam(ImMsgBizUserHistory imMsgBizUserHistory) {
        return imMsgBizUserHistoryMapper.getByParam(imMsgBizUserHistory);
    }

    @Override
    public void save(ImMsgBizUserHistory imMsgBizUserHistory) {
        imMsgBizUserHistoryMapper.save(imMsgBizUserHistory);
    }

    @Override
    public void update(ImMsgBizUserHistory imMsgBizUserHistory) {
        imMsgBizUserHistoryMapper.update(imMsgBizUserHistory);
    }

    @Override
    public void deleteById(Long id) {
        imMsgBizUserHistoryMapper.deleteById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ImMsgBizUserHistory saveHistory(Integer sendType, Long bizId, Long userId, Long employeeId, Integer type, String content, Integer whoSend) {
        ImMsgBizUser imMsgBizUser = imMsgBizUserService.getBySendTypeBizIdUserId(sendType, bizId, userId);
        if (Objects.isNull(imMsgBizUser)) {
            imMsgBizUser = new ImMsgBizUser();
            imMsgBizUser.setSendType(sendType);
            imMsgBizUser.setBizId(bizId);
            imMsgBizUser.setUserId(userId);
            imMsgBizUser.setBizUnreadNum(0);
            imMsgBizUser.setUserUnreadNum(0);
            imMsgBizUser.setCreateTime(new Date());
            imMsgBizUser.setUpdateTime(new Date());
            imMsgBizUserService.save(imMsgBizUser);
        }
        ImMsgBizUserHistory imMsgBizUserHistory = new ImMsgBizUserHistory();
        imMsgBizUserHistory.setImMsgBizUserId(imMsgBizUser.getId());
        imMsgBizUserHistory.setSendType(sendType);
        imMsgBizUserHistory.setBizId(bizId);
        imMsgBizUserHistory.setUserId(userId);
        imMsgBizUserHistory.setEmployeeId(employeeId);
        imMsgBizUserHistory.setType(type);
        imMsgBizUserHistory.setContent(content);
        imMsgBizUserHistory.setWhoSend(whoSend);
        if (Objects.equals(whoSend, WhoSend.EMPLOYEE)) {
            imMsgBizUserHistory.setUserUnread(MsgRead.UNREAD);
            imMsgBizUserHistory.setEmployeeUnread(MsgRead.READ);
        } else if (Objects.equals(whoSend, WhoSend.USER)) {
            imMsgBizUserHistory.setUserUnread(MsgRead.READ);
            imMsgBizUserHistory.setEmployeeUnread(MsgRead.UNREAD);
        }
        imMsgBizUserHistory.setCreateTime(new Date());
        imMsgBizUserHistory.setUpdateTime(new Date());
        imMsgBizUserHistory.setReadRange(0);
        this.save(imMsgBizUserHistory);
        return imMsgBizUserHistory;
    }

    @Override
    public MsgItemVO getUserPlatformMsgItem(UserApiVO user, ImMsgBizUserHistory imMsgBizUserHistory) {
        MsgItemVO msgItem = new MsgItemVO();
        msgItem.setChatType(imMsgBizUserHistory.getSendType());
        msgItem.setUserId(user.getUserId());
        msgItem.setUserHeadUrl(user.getPic());
        msgItem.setUserName(user.getNickName());
        msgItem.setNickName(imMsgBizUserHistory.getNickName());
        msgItem.setShopId(imMsgBizUserHistory.getBizId());
        msgItem.setShopName(imMsgBizUserHistory.getNickName());
        msgItem.setItemId(imMsgBizUserHistory.getId());
        msgItem.setEmployeeId(imMsgBizUserHistory.getEmployeeId());
        // todo 东8区，不应该写死"+8"后续优化
        msgItem.setTimeStr(DateUtil.format(imMsgBizUserHistory.getCreateTime(), "yyyy/MM/dd HH:mm"));
        msgItem.setTimestamp(imMsgBizUserHistory.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
        msgItem.setContent(imMsgBizUserHistory.getContent());
        msgItem.setSource(imMsgBizUserHistory.getWhoSend());
        msgItem.setType(imMsgBizUserHistory.getType());
        msgItem.setUserUnread(imMsgBizUserHistory.getUserUnread());
        msgItem.setEmployeeUnread(imMsgBizUserHistory.getEmployeeUnread());
        msgItem.setCreateTime(imMsgBizUserHistory.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        msgItem.setUpdateTime(imMsgBizUserHistory.getUpdateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        return msgItem;
    }

    @Override
    public MsgItemVO getUserShopMsgItem(EsShopDetailBO shopDetail, UserApiVO user, ImMsgBizUserHistory imMsgBizUserHistory) {
        MsgItemVO msgItem = new MsgItemVO();
        msgItem.setChatType(imMsgBizUserHistory.getSendType());
        msgItem.setUserId(user.getUserId());
        msgItem.setUserHeadUrl(user.getPic());
        msgItem.setUserName(user.getNickName());
        msgItem.setNickName(imMsgBizUserHistory.getNickName());
        msgItem.setShopLogo(shopDetail.getShopLogo());
        msgItem.setShopId(shopDetail.getShopId());
        msgItem.setShopName(shopDetail.getShopName());
        msgItem.setItemId(imMsgBizUserHistory.getId());
        msgItem.setEmployeeId(imMsgBizUserHistory.getEmployeeId());
        // todo 东8区，不应该写死"+8"后续优化
        msgItem.setTimestamp(imMsgBizUserHistory.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().toInstant(ZoneOffset.of("+8")).toEpochMilli());
        msgItem.setTimeStr(DateUtil.format(imMsgBizUserHistory.getCreateTime(), "yyyy/MM/dd HH:mm"));
        msgItem.setType(imMsgBizUserHistory.getType());
        msgItem.setContent(imMsgBizUserHistory.getContent());
        msgItem.setSource(imMsgBizUserHistory.getWhoSend());
        msgItem.setUserUnread(imMsgBizUserHistory.getUserUnread());
        msgItem.setEmployeeUnread(imMsgBizUserHistory.getEmployeeUnread());
        msgItem.setCreateTime(imMsgBizUserHistory.getCreateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
        msgItem.setUpdateTime(imMsgBizUserHistory.getUpdateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());

        return msgItem;
    }

    @Override
    public PageVO<MsgItemVO> getUserPlatformHistory(SysUserVO sysUser, MessageInfoVO messageInfo, Long bizId, Long userId, UserApiVO user) {
        PageDTO pageDTO = new PageDTO();
        if (Objects.nonNull(messageInfo.getCurrent()) && Objects.nonNull(messageInfo.getSize())) {
            pageDTO.setPageSize(messageInfo.getSize());
            pageDTO.setPageNum(messageInfo.getCurrent());
        }
        PageVO<ImMsgBizUserHistory> history = this.pageBySendTypeBizIdUserId(pageDTO, messageInfo.getSendType(), bizId, null, userId);
        List<ImMsgBizUserHistory> imMsgBizUserHistories = history.getList();

        List<MsgItemVO> msgItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (ImMsgBizUserHistory imMsgBizUserHistory : imMsgBizUserHistories) {
            MsgItemVO msgItem = this.getUserPlatformMsgItem(user, imMsgBizUserHistory);
            msgItems.add(msgItem);
        }
        return getPageVO(history, msgItems);
    }

    private static PageVO<MsgItemVO> getPageVO(PageVO<ImMsgBizUserHistory> history, List<MsgItemVO> msgItems) {
        PageVO<MsgItemVO> msgItemPage = new PageVO<>();
        BeanUtils.copyProperties(history, msgItemPage);
        msgItemPage.setList(msgItems);
        return msgItemPage;
    }

    @Override
    public PageVO<MsgItemVO> getUserShopHistory(EsShopDetailBO shopDetail, MessageInfoVO messageInfo, Long bizId, Long userId, UserApiVO user) {
        PageDTO pageDTO = new PageDTO();
        if (Objects.nonNull(messageInfo.getCurrent()) && Objects.nonNull(messageInfo.getSize())) {
            pageDTO.setPageNum(messageInfo.getCurrent());
            pageDTO.setPageSize(messageInfo.getSize());
        }
        PageVO<ImMsgBizUserHistory> history = this.pageBySendTypeBizIdUserId(pageDTO, messageInfo.getSendType(), bizId, null, userId);
        List<ImMsgBizUserHistory> imMsgBizUserHistories = history.getList();
        List<MsgItemVO> msgItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (ImMsgBizUserHistory imMsgBizUserHistory : imMsgBizUserHistories) {
            MsgItemVO msgItem = this.getUserShopMsgItem(shopDetail, user, imMsgBizUserHistory);
            msgItems.add(msgItem);
        }
        return getPageVO(history, msgItems);
    }

    @Override
    public PageVO<MsgItemVO> getShopUserHistory(UidInfoBO uidInfoBO, MessageInfoVO messageInfo, UserApiVO user, EsShopDetailBO shopDetail) {
        PageDTO pageDTO = new PageDTO();
        if (Objects.nonNull(messageInfo.getCurrent()) && Objects.nonNull(messageInfo.getSize())) {
            pageDTO.setPageNum(messageInfo.getCurrent());
            pageDTO.setPageSize(messageInfo.getSize());
        }
        PageVO<ImMsgBizUserHistory> history = this.pageBySendTypeBizIdUserId(pageDTO, SendType.SHOP, uidInfoBO.getTenantId(), uidInfoBO.getUserId(), user.getUserId());
        List<ImMsgBizUserHistory> imMsgBizUserHistories = history.getList();
        // 获取转接前的聊天记录(当天转接的记录+当前用户是自己负责才进行查询)
        imMsgBizUserHistories.sort(Comparator.comparing(ImMsgBizUserHistory::getId, Comparator.reverseOrder()));
        List<MsgItemVO> msgItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (ImMsgBizUserHistory imMsgBizUserHistory : imMsgBizUserHistories) {
            MsgItemVO msgItem = this.getUserShopMsgItem(shopDetail, user, imMsgBizUserHistory);
            msgItems.add(msgItem);
        }
        return getPageVO(history, msgItems);
    }
    @Override
    public PageVO<MsgItemVO> getPlatformUserHistory(UidInfoBO uidInfoBO, MessageInfoVO messageInfo, UserApiVO user, SysUserVO sysUser) {
        PageDTO pageDTO = new PageDTO();
        if (Objects.nonNull(messageInfo.getCurrent()) && Objects.nonNull(messageInfo.getSize())) {
            pageDTO.setPageNum(messageInfo.getCurrent());
            pageDTO.setPageSize(messageInfo.getSize());
        }
        PageVO<ImMsgBizUserHistory> history = this.pageBySendTypeBizIdUserId(pageDTO, SendType.PLATFORM, Admin.ID, uidInfoBO.getUserId(), user.getUserId());
        List<ImMsgBizUserHistory> imMsgBizUserHistories = history.getList();
        imMsgBizUserHistories.sort(Comparator.comparing(ImMsgBizUserHistory::getId, Comparator.reverseOrder()));
        // 获取消息历史包含的用户昵称
        List<MsgItemVO> msgItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (ImMsgBizUserHistory imMsgBizUserHistory : imMsgBizUserHistories) {
            MsgItemVO msgItem = this.getUserPlatformMsgItem(user, imMsgBizUserHistory);
            msgItems.add(msgItem);
        }
        return getPageVO(history, msgItems);


    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int markUserPlatformRead(Long userId) {
        ImMsgBizUser imMsgBizUser = imMsgBizUserService.getBySendTypeBizIdUserId(SendType.PLATFORM, Admin.ID, userId);
        // 更新用户未读消息的数量，且用户未读消息更新为已读并返回更新数量
        return updateUserHistory(imMsgBizUser);
    }

    private int updateUserHistory(ImMsgBizUser imMsgBizUser) {
        // 更改用户所有未读消息为已读状态
        int updateNum = imMsgBizUserHistoryMapper.updateUnreadHistoryByUserId(imMsgBizUser.getId(), imMsgBizUser.getUserId());
        // 更新用户未读消息数量
        imMsgBizUserService.updateUserUnreadHistor(imMsgBizUser.getId(), MsgRead.UNREAD, WhoSend.EMPLOYEE);
        return updateNum;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int markUserShopRead(Long bizId, Long userId) {
        ImMsgBizUser imMsgBizUser = imMsgBizUserService.getBySendTypeBizIdUserId(SendType.SHOP, bizId, userId);
        // 更新用户未读消息的数量，且用户未读消息更新为已读并返回更新数量
        return updateUserHistory(imMsgBizUser);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer markUserReadBySendType(Integer sendType, MessageInfoVO messageInfo, UidInfoBO uidInfoBO, Long userId) {
        // 获取平台、店铺客服信息
        ImMsgBizUser imMsgBizUser = imMsgBizUserService.getBySendTypeBizIdUserId(sendType, uidInfoBO.getTenantId(), userId);
        // 更改平台、店铺客服所有未读消息为已读状态
        int updateNum = imMsgBizUserHistoryMapper.updateUnreadHistoryByShopId(imMsgBizUser.getId(), imMsgBizUser.getUserId());
        if (updateNum > 0) {
            // 更新平台、店铺未读消息数
            imMsgBizUserService.updateShopUserUnreadMsgNum(imMsgBizUser.getId(), MsgRead.UNREAD, WhoSend.USER);
        }
        // 更新客服未读条数
        imMsgBizEmployeeRecentService.updateEmployeeUnreadMsgNum(sendType, imMsgBizUser.getId(), uidInfoBO.getTenantId(), uidInfoBO.getUserId(), userId);
        return updateNum;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ImMsgBizUserHistory saveUserPlatformHistory(MessageInfoVO messageInfo, Long bizId, Long userId, Long employeeId) {
        ImMsgBizUserHistory imMsgBizUserHistory = this.saveHistory(messageInfo.getSendType(), bizId, userId, employeeId, messageInfo.getMsgType(), messageInfo.getContent(), WhoSend.USER);
        imMsgBizUserService.updateBizUserLastMsg(imMsgBizUserHistory);
        imMsgBizEmployeeRecentService.updateEmployeeRecent(imMsgBizUserHistory);
        return imMsgBizUserHistory;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ImMsgBizUserHistory saveUserShopHistory(MessageInfoVO messageInfo, Long bizId, Long userId, Long employeeId) {
        ImMsgBizUserHistory imMsgBizUserHistory = this.saveHistory(messageInfo.getSendType(), bizId, userId, employeeId, messageInfo.getMsgType(), messageInfo.getContent(), WhoSend.USER);
        imMsgBizUserService.updateBizUserLastMsg(imMsgBizUserHistory);
        imMsgBizEmployeeRecentService.updateEmployeeRecent(imMsgBizUserHistory);
        return imMsgBizUserHistory;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ImMsgBizUserHistory saveShopUserHistory(MessageInfoVO messageInfo, UidInfoBO uidInfoBO) {
        ImMsgBizUserHistory imMsgBizUserHistory = this.saveHistory(SendType.SHOP, uidInfoBO.getTenantId(), messageInfo.getToId(), uidInfoBO.getUserId(), messageInfo.getMsgType(), messageInfo.getContent(), WhoSend.EMPLOYEE);
        imMsgBizUserService.updateBizUserLastMsg(imMsgBizUserHistory);
        imMsgBizEmployeeRecentService.updateEmployeeRecent(imMsgBizUserHistory);
        return imMsgBizUserHistory;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ImMsgBizUserHistory savePlatformUserHistory(MessageInfoVO messageInfo, UidInfoBO uidInfoBO) {
        ImMsgBizUserHistory imMsgBizUserHistory = this.saveHistory(SendType.PLATFORM, Admin.ID, messageInfo.getToId(), uidInfoBO.getUserId(), messageInfo.getMsgType(), messageInfo.getContent(), WhoSend.EMPLOYEE);
        imMsgBizUserService.updateBizUserLastMsg(imMsgBizUserHistory);
        imMsgBizEmployeeRecentService.updateEmployeeRecent(imMsgBizUserHistory);
        return imMsgBizUserHistory;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ImMsgBizUserHistory saveShopChangeEmployeeReply(UidInfoBO uidInfoBO, ShopUserVO shopUserVO, UserApiVO user) {
        String content = "系统：转接成功：" + shopUserVO.getNickName() + "客服为您服务";
        ImMsgBizUserHistory imMsgBizUserHistory = this.saveHistory(SendType.SHOP, uidInfoBO.getTenantId(), user.getUserId(), shopUserVO.getShopUserId(), MsgType.TEXT, content, WhoSend.EMPLOYEE);
        // 多保存一份转接前客服的转接聊天记录
//        imMsgBizUserHistory.setEmployeeId(uidInfoBO.getUserId());
//        imMsgBizUserHistory.setReadRange(1);
//        this.save(imMsgBizUserHistory);
        imMsgBizUserHistory.setEmployeeId(shopUserVO.getShopUserId());

        imMsgBizUserService.updateBizUserLastMsg(imMsgBizUserHistory);
        imMsgBizEmployeeRecentService.updateEmployeeRecent(imMsgBizUserHistory);
        return imMsgBizUserHistory;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ImMsgBizUserHistory savePlatformChangeEmployeeReply(UidInfoBO uidInfoBO, SysUserVO sysUser3, UserApiVO user) {
        String content = "系统：转接成功：" + sysUser3.getNickName() + "客服为您服务";
        ImMsgBizUserHistory imMsgBizUserHistory = this.saveHistory(SendType.PLATFORM, Admin.ID, user.getUserId(), sysUser3.getSysUserId(), MsgType.TEXT, content, WhoSend.EMPLOYEE);
//        // 多保存一份转接前客服的转接聊天记录
//        imMsgBizUserHistory.setEmployeeId(uidInfoBO.getUserId());
//        imMsgBizUserHistory.setReadRange(1);
//        this.save(imMsgBizUserHistory);
        imMsgBizUserHistory.setEmployeeId(sysUser3.getSysUserId());

        imMsgBizUserService.updateBizUserLastMsg(imMsgBizUserHistory);
        imMsgBizEmployeeRecentService.updateEmployeeRecent(imMsgBizUserHistory);
        return imMsgBizUserHistory;
    }
}
