package com.sckw.message.service;

import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.page.PageRes;
import com.sckw.core.model.vo.TableBottom;
import com.sckw.core.model.vo.TableStatisticRes;
import com.sckw.core.model.vo.TableTop;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.message.enums.MsgStatusEnum;
import com.sckw.message.model.KwmMessage;
import com.sckw.message.model.KwmMessageUser;
import com.sckw.message.model.dto.MessageListDTO;
import com.sckw.message.model.dto.SelectMessagesDTO;
import com.sckw.message.model.dto.UserMsgCenterLatestMsgDTO;
import com.sckw.message.model.dto.UserMsgCenterReqDTO;
import com.sckw.message.model.vo.req.DeleteMessagesReqVO;
import com.sckw.message.model.vo.req.ReadMessagesReqVO;
import com.sckw.message.model.vo.req.StatisticsMessagesReqVO;
import com.sckw.message.model.vo.res.KwmMessageListResVO;
import com.sckw.message.model.vo.res.MessagesStatisticsResVO;
import com.sckw.message.model.vo.res.UserCenterMsgVO;
import com.sckw.message.model.vo.res.UserMsgCenterResVO;
import com.sckw.stream.enums.MessageEnum;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import com.sckw.system.api.model.pojo.DeptInfoPojo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @desc: 消息相关service
 * @author: yzc
 * @date: 2023-06-09 10:58
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class MessageService {

    private final KwmMessageService kwmMessageService;
    private final KwmMessageUserService kwmMessageUserService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;


    /**
     * @param reqVO
     * @return void
     * @desc: 更新消息已读
     * @author: yzc
     * @date: 2023-06-09 14:20
     */
    @Transactional(rollbackFor = Exception.class)
    public void read(ReadMessagesReqVO reqVO) {
        List<Long> ids = StringUtils.splitStrToList(reqVO.getIds(), Long.class);
        List<KwmMessageUser> msgList = kwmMessageUserService.getByMsgIds(ids);
        if (!Objects.equals(ids.size(), msgList.size())) {
            throw new BusinessException("无权限读取消息！");
        }
        kwmMessageUserService.readByMsgIds(ids);
    }

    /**
     * @param reqVO
     * @return void
     * @desc: 删除消息
     * @author: yzc
     * @date: 2023-06-09 14:20
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(DeleteMessagesReqVO reqVO) {
        Long userId = LoginUserHolder.getUserId();
        List<Long> msgIds = kwmMessageUserService.getMsgIdsByUserId(userId);
        if (CollectionUtils.isEmpty(msgIds)) {
            return;
        }
        List<Long> ids = reqVO.getMsgIds();
        //msgIds不为空直接删除用户消息
        if (CollectionUtils.isNotEmpty(ids)) {
            List<Long> list = ids.stream().filter(msgIds::contains).toList();
            kwmMessageUserService.delByUserAndMsgIds(userId, list);
        } else {
            //msgIds为空，根据category及type查找删除用户消息
            List<KwmMessage> messageList = kwmMessageService.getList(msgIds, reqVO.getCategory(), reqVO.getType(), null);
            if (CollectionUtils.isEmpty(messageList)) {
                return;
            }
            List<Long> delMsgIds = messageList.stream().map(KwmMessage::getId).toList();
            kwmMessageUserService.delByUserAndMsgIds(userId, delMsgIds);
        }
    }

    /**
     * @param dto
     * @return java.util.List<com.sckw.message.model.KwmMessage>
     * @desc: 分页查询消息列表
     * @author: yzc
     * @date: 2023-06-13 9:05
     */
    public PageRes select(SelectMessagesDTO dto) {
        PageHelper.startPage(dto.getPage(), dto.getPageSize());
        //当前登录人是企业管理员则查看全部消息，否则只查看对应用户消息
        Integer isMain = LoginUserHolder.getIsMain();
        if (Objects.equals(isMain, 1)) {
            dto.setEntId(LoginUserHolder.getEntId());
        } else {
            dto.setUserId(LoginUserHolder.getUserId());
        }
        List<MessageListDTO> list = kwmMessageService.findPage(dto);
        PageInfo<MessageListDTO> pageInfo = new PageInfo<>(list);
        if (CollectionUtils.isEmpty(list)) {
            return PageRes.build(pageInfo, list);
        }
        Map<String, String> categoryMap, statusMap;
        Map<String, Map<String, String>> dictMap = remoteSystemService.queryDictByType(
                Arrays.asList(DictTypeEnum.MSG_CATEGORY.getType(), DictTypeEnum.MSG_STATUS.getType()));
        if (CollectionUtils.isNotEmpty(dictMap)) {
            categoryMap = dictMap.get(DictTypeEnum.MSG_CATEGORY.getType());
            statusMap = dictMap.get(DictTypeEnum.MSG_STATUS.getType());
        } else {
            categoryMap = new HashMap<>();
            statusMap = new HashMap<>();
        }
        String clientType = LoginUserHolder.getClientType();
        List<Long> userIds = list.stream().map(MessageListDTO::getCreateBy).toList();
        Map<Long, UserCacheResDto> map = remoteSystemService.queryUserCacheMapByIds(userIds);
        List<KwmMessageListResVO> result = new ArrayList<>(list.size());
        list.forEach(e -> {
            UserCacheResDto user = map.get(e.getCreateBy());
            KwmMessageListResVO res = BeanUtils.copyProperties(e, KwmMessageListResVO.class);
            if (Objects.nonNull(e.getUrl())) {
                Map<String, Object> urlMap = JSONObject.parse(e.getUrl());
                res.setUrl(Objects.isNull(urlMap.get(clientType)) ? null : urlMap.get(clientType).toString());
            }
            res.setStatusLabel(statusMap.get(String.valueOf(e.getStatus())));
            res.setCategoryLabel(categoryMap.get(e.getCategory()));
            if (Objects.nonNull(user)) {
                res.setCreateByName(user.getName());
                EntCacheResDto entInfo = user.getEntInfo();
                if (Objects.nonNull(entInfo)) {
                    //司机有企业信息，没有部门信息
                    List<DeptInfoPojo> deptInfo = entInfo.getDeptInfo();
                    res.setCreateByDept(CollectionUtils.isEmpty(deptInfo) ? "司机" : deptInfo.get(0).getName());
                }
            }
            result.add(res);
        });
        return PageRes.build(pageInfo, result);
    }

    /**
     * @param category
     * @return com.sckw.message.model.vo.res.MessagesStatisticsResVO
     * @desc: 消息统计
     * @author: yzc
     * @date: 2023-06-13 10:19
     */
    public List<MessagesStatisticsResVO> statistics(String category) {
        //获取用户未删除消息
        List<KwmMessageUser> messageUsers = kwmMessageUserService.getByUserId(LoginUserHolder.getUserId());
        Map<Long, KwmMessageUser> map = messageUsers.stream().collect(Collectors.toMap(KwmMessageUser::getMsgId, e -> e, (k1, k2) -> k1));
        if (CollectionUtils.isEmpty(map)) {
            return Collections.emptyList();
        }
        List<Long> msgIds = map.keySet().stream().toList();
        //根据消息ids获取message详情
        List<KwmMessage> messages = kwmMessageService.statistics(msgIds, category);
        if (CollectionUtils.isEmpty(messages)) {
            return Collections.emptyList();
        }
        //设置用户消息状态及创建时间
        messages.forEach(e -> {
            KwmMessageUser kwmMessageUser = map.get(e.getId());
            e.setStatus(kwmMessageUser.getStatus());
            e.setCreateTime(kwmMessageUser.getCreateTime());
        });
        //消息按状态升序、创建时间降序排序，无category按category分组，有category按type分组
        Map<String, List<KwmMessage>> collect;
        if (StringUtils.isNotBlank(category)) {
            collect = messages.stream().sorted(Comparator.comparingInt(KwmMessage::getStatus)
                    .thenComparing(KwmMessage::getCreateTime, Comparator.reverseOrder())).collect(Collectors.groupingBy(KwmMessage::getType));
        } else {
            collect = messages.stream().sorted(Comparator.comparingInt(KwmMessage::getStatus)
                    .thenComparing(KwmMessage::getCreateTime, Comparator.reverseOrder())).collect(Collectors.groupingBy(KwmMessage::getCategory));
        }
        //组装响应参数：消息分组第一条、统计未读数量
        List<MessagesStatisticsResVO> list = new ArrayList<>(collect.size());
        collect.values().forEach(e -> {
            KwmMessage message = e.get(0);
            long count = e.stream().filter(m -> Global.UN_READ.equals(m.getStatus())).count();
            MessagesStatisticsResVO messagesStatistics = BeanUtils.copyProperties(message, MessagesStatisticsResVO.class);
            messagesStatistics.setUnReadNum((int) count);
            list.add(messagesStatistics);
        });
        return list;
    }

    /**
     * @param id
     * @return com.sckw.message.model.KwmMessage
     * @desc: 获取消息详情
     * @author: yzc
     * @date: 2023-06-13 15:19
     */
    @Transactional(rollbackFor = Exception.class)
    public KwmMessage detail(Long id) {
        List<Long> ids = Collections.singletonList(id);
        List<KwmMessageUser> msgList = kwmMessageUserService.getByMsgIds(ids);
        if (CollectionUtils.isEmpty(msgList)) {
            return KwmMessage.builder().build();
        }
        KwmMessageUser kwmMessageUser = msgList.get(0);
        KwmMessage message = kwmMessageService.getById(kwmMessageUser.getMsgId());
        if (Objects.nonNull(message.getUrl())) {
            String clientType = LoginUserHolder.getClientType();
            Map<String, Object> urlMap = JSONObject.parse(message.getUrl());
            message.setUrl(Objects.isNull(urlMap.get(clientType)) ? null : urlMap.get(clientType).toString());
        }
        //更新用户消息为已读状态
        kwmMessageUserService.readByMsgIds(ids);
        return message;
    }

    /**
     * @desc: 消息列表统计
     * @author: yzc
     * @date: 2023-08-22 11:48
     * @Param params:
     * @return: com.sckw.core.model.vo.TableStatisticRes
     */
    public TableStatisticRes statistics(StatisticsMessagesReqVO params) {
        TableStatisticRes res = new TableStatisticRes();
        SelectMessagesDTO dto = BeanUtils.copyProperties(params, SelectMessagesDTO.class);
        //当前登录人是企业管理员则查看全部消息，否则只查看对应用户消息
        if (Objects.equals(LoginUserHolder.getIsMain(), 1)) {
            dto.setEntId(LoginUserHolder.getEntId());
        } else {
            dto.setUserId(LoginUserHolder.getUserId());
        }
        List<TableTop> statistics = kwmMessageService.statistics(dto);
        Map<Integer, Integer> map = statistics.stream().
                collect(Collectors.toMap(TableTop::getValue, TableTop::getTotal, (k1, k2) -> k1));
        List<TableTop> tableTops = new ArrayList<>();
        int totalCount = 0;
        List<MsgStatusEnum> enums = MsgStatusEnum.getSortList();
        for (MsgStatusEnum e : enums) {
            Integer count = map.get(e.getCode());
            int total = Objects.isNull(count) ? 0 : count;
            TableTop tableTop = new TableTop();
            tableTop.setName(e.getMsg()).setValue(e.getCode()).setTotal(total);
            tableTops.add(tableTop);
            totalCount = totalCount + total;
        }
        TableTop all = new TableTop();
        all.setName("全部").setTotal(totalCount);
        tableTops.add(0, all);
        TableBottom tableBottom = new TableBottom();
        tableBottom.setTotal(totalCount);
        res.setTableTops(tableTops).setTableBottom(tableBottom);
        return res;
    }

    /**
     * @desc: 用户消息中心获取
     * @author: yzc
     * @date: 2023-09-07 17:41
     * @return: com.sckw.message.model.vo.res.UserMsgCenterResVO
     */
    public UserMsgCenterResVO userMsgCenter() {
        UserMsgCenterReqDTO dto = new UserMsgCenterReqDTO();
        boolean isMain = Objects.equals(LoginUserHolder.getIsMain(), 1);
        dto.setEntId(isMain ? LoginUserHolder.getEntId() : null);
        dto.setUserId(isMain ? null : LoginUserHolder.getUserId());
        //获取消息列表
        List<UserCenterMsgVO> msgList = kwmMessageUserService.userMsgCenter(dto);
        int size = msgList.size();
        boolean flag = size < 5;
        Set<MessageEnum> excludeEnums = new HashSet<>();
        String clientType = LoginUserHolder.getClientType();
        msgList.forEach(e -> {
            dto.setStatus(e.getStatus()).setType(e.getType());
            UserMsgCenterLatestMsgDTO msg = kwmMessageUserService.getLatestMsg(dto);
            if (Objects.nonNull(msg.getUrl())) {
                Map<String, Object> urlMap = JSONObject.parse(msg.getUrl());
                e.setUrl(Objects.isNull(urlMap.get(clientType)) ? null : urlMap.get(clientType).toString());
            }
            e.setId(msg.getId()).setTitle(msg.getTitle())
                    .setContent(msg.getContent())
                    .setCreateTime(msg.getCreateTime());
            if (flag) {
                MessageEnum messageEnum = MessageEnum.getEnumByCategoryAndType(msg.getCategory(), msg.getType());
                if (Objects.nonNull(messageEnum)) {
                    excludeEnums.add(messageEnum);
                }
            }
        });
        //补齐默认消息
        if (flag) {
            List<MessageEnum> enums = MessageEnum.getEnums(isMain, 5 - size, excludeEnums);
            enums.forEach(e -> {
                UserCenterMsgVO vo = new UserCenterMsgVO();
                vo.setTitle(e.getTitle()).setContent("暂无" + e.getTitle());
                msgList.add(vo);
            });
        }
        //统计总未读消息条数
        Long unReadNum = kwmMessageUserService.count(dto.getEntId(), dto.getUserId(), 0);
        UserMsgCenterResVO result = new UserMsgCenterResVO();
        result.setMsgList(msgList).setTotalUnReadNum(unReadNum);
        return result;
    }
}
