package com.sckw.message.service;

import com.sckw.core.model.constant.Global;
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.model.FindMessagePageParam;
import com.sckw.message.model.KwmMessage;
import com.sckw.message.model.KwmMessageUser;
import com.sckw.message.model.vo.req.DeleteMessagesReqVO;
import com.sckw.message.model.vo.req.FindMessagesReqVO;
import com.sckw.message.model.vo.req.ReadMessagesReqVO;
import com.sckw.message.model.vo.req.SelectMessagesReqVO;
import com.sckw.message.model.vo.res.MessagesStatisticsResVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
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;


    /**
     * @param params
     * @return java.util.List<com.sckw.message.model.KwmMessage>
     * @desc: 查询消息列表
     * @author: yzc
     * @date: 2023-06-09 14:21
     */
    public List<KwmMessage> selectMessages(FindMessagesReqVO params) {
        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();
        List<KwmMessage> list = kwmMessageService.getList(msgIds, params.getCategory(), params.getType(), null);
        list.forEach(e -> {
            KwmMessageUser messageUser = map.get(e.getId());
            e.setStatus(messageUser.getStatus());
            e.setCreateTime(messageUser.getCreateTime());
            e.setUpdateTime(messageUser.getUpdateTime());
            e.setUpdateBy(messageUser.getUpdateBy());
        });
        return list;
    }

    /**
     * @param reqVO
     * @return void
     * @desc: 更新消息已读
     * @author: yzc
     * @date: 2023-06-09 14:20
     */
    @Transactional(rollbackFor = Exception.class)
    public void read(ReadMessagesReqVO 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.readByUserAndMsgIds(userId, list);
        } else {
            //msgIds为空根据category及type更新用户消息为已读
            List<KwmMessage> messageList = kwmMessageService.getList(msgIds, reqVO.getCategory(), reqVO.getType(), 0);
            if (CollectionUtils.isEmpty(messageList)) {
                return;
            }
            List<Long> updateMsgIds = messageList.stream().map(KwmMessage::getId).toList();
            kwmMessageUserService.readByUserAndMsgIds(userId, updateMsgIds);
        }
    }

    /**
     * @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 reqVO
     * @return java.util.List<com.sckw.message.model.KwmMessage>
     * @desc: 分页查询消息列表
     * @author: yzc
     * @date: 2023-06-13 9:05
     */
    public List<KwmMessage> select(SelectMessagesReqVO reqVO) {
        FindMessagePageParam findMessagePageParam = FindMessagePageParam.builder().userId(LoginUserHolder.getUserId())
                .category(reqVO.getCategory()).type(reqVO.getType()).build();
        return kwmMessageService.findPage(findMessagePageParam);
    }

    /**
     * @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) {
        Long userId = LoginUserHolder.getUserId();
        KwmMessageUser messageUser = kwmMessageUserService.getByMsgIdAndUserId(id, userId);
        if (Objects.isNull(messageUser)) {
            return KwmMessage.builder().build();
        }
        KwmMessage message = kwmMessageService.getById(id);
        List<Long> ids = Collections.singletonList(id);
        //更新用户消息为已读状态
        kwmMessageUserService.readByUserAndMsgIds(userId, ids);
        return message;
    }
}
