package com.ruoyi.frequency.votecomment.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.common.page.PageResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.controller.req.DialoguePageReq;
import com.ruoyi.controller.req.VoteCommentPageReq;
import com.ruoyi.controller.req.VoteCommentReq;
import com.ruoyi.controller.resp.CommentNum;
import com.ruoyi.controller.resp.VoteCommentPageResp;
import com.ruoyi.controller.resp.VoteCommentResp;
import com.ruoyi.enums.message.InteractionMessageEnums;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.frequency.vote.entity.Vote;
import com.ruoyi.frequency.vote.mapper.VoteMapper;
import com.ruoyi.frequency.vote.service.VoteService;
import com.ruoyi.frequency.votecomment.entity.VoteComment;
import com.ruoyi.frequency.votecomment.mapper.VoteCommentMapper;
import com.ruoyi.frequency.votecomment.service.VoteCommentService;
import com.ruoyi.message.frequency.interactionmessagerecord.service.InteractionMessageRecordService;
import com.ruoyi.post.controller.req.DeleteCommentReq;
import com.ruoyi.response.ResponseData;
import com.ruoyi.utils.BusinessUtil;
import com.ruoyi.vo.UserInfo;
import com.ruoyi.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 帖子评论Service业务层处理
 *
 * @author liwenlong
 * @date 2023-10-09
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class VoteCommentServiceImpl extends ServiceImpl<VoteCommentMapper, VoteComment> implements VoteCommentService {
    @Autowired
    private VoteCommentMapper voteCommentMapper;

    /**
     * 查询帖子评论
     *
     * @param id 帖子评论主键
     * @return 帖子评论
     */
    @Override
    public VoteComment selectVoteCommentById(Long id) {
        VoteComment voteComment = voteCommentMapper.selectVoteCommentById(id);

        if (voteComment != null) {
            Set<UserVo> userVoSet = new HashSet<>();
            userVoSet.add(new UserVo(voteComment.getUserType(), voteComment.getUserId()));
            userVoSet.add(new UserVo(voteComment.getParentUserType(), voteComment.getParentUserId()));

            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, null);

            voteComment.setUserInfo(userMap.get(new UserVo(voteComment.getUserType(), voteComment.getUserId())));
            voteComment.setParentUserInfo(userMap.get(new UserVo(voteComment.getParentUserType(), voteComment.getParentUserId())));
        }

        return voteComment;
    }

    /**
     * 查询帖子评论列表
     *
     * @param voteComment 帖子评论
     * @return 帖子评论
     */
    @Override
    public List<VoteComment> selectVoteCommentList(VoteComment voteComment) {
        List<VoteComment> voteComments = voteCommentMapper.selectVoteCommentList(voteComment);

        if (!voteComments.isEmpty()) {
            Set<UserVo> userVoSet = voteComments.stream().map(s -> new UserVo(s.getUserType(), s.getUserId())).collect(Collectors.toSet());
            Set<UserVo> parentUserVoSet = voteComments.stream().map(s -> new UserVo(s.getParentUserType(), s.getParentUserId())).collect(Collectors.toSet());

            userVoSet.addAll(parentUserVoSet);

            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, null);

            voteComments.stream().forEach(s -> {
                s.setUserInfo(userMap.get(new UserVo(s.getUserType(), s.getUserId())));
                s.setParentUserInfo(userMap.get(new UserVo(s.getParentUserType(), s.getParentUserId())));
            });
        }

        return voteComments;
    }

    /**
     * 新增帖子评论
     *
     * @param voteComment 帖子评论
     * @return 结果
     */
    @Override
    public int insertVoteComment(VoteComment voteComment) {
        voteComment.setCreateTime(DateUtils.getNowDate());
        return voteCommentMapper.insertVoteComment(voteComment);
    }

    /**
     * 修改帖子评论
     *
     * @param voteComment 帖子评论
     * @return 结果
     */
    @Override
    public int updateVoteComment(VoteComment voteComment) {
        voteComment.setUpdateTime(DateUtils.getNowDate());
        return voteCommentMapper.updateVoteComment(voteComment);
    }

    /**
     * 修改帖子评论
     *
     * @param voteComment 帖子评论
     * @return 结果
     */
    @Override
    public int updateVoteCommentLikeNum(VoteComment voteComment, Integer num) {
        return voteCommentMapper.updateVoteCommentLikeNum(voteComment.getId(), num);
    }

    /**
     * 批量删除帖子评论
     *
     * @param ids 需要删除的帖子评论主键
     * @return 结果
     */
    @Override
    public int deleteVoteCommentByIds(Long[] ids) {
        this.lambdaUpdate().set(VoteComment::getDelFlag, PublicCommon.删除).in(VoteComment::getId, ids).update();
        return ids.length;
    }

    /**
     * 删除帖子评论信息
     *
     * @param id 帖子评论主键
     * @return 结果
     */
    @Override
    public int deleteVoteCommentById(Long id) {
        this.lambdaUpdate().set(VoteComment::getDelFlag, PublicCommon.删除).eq(VoteComment::getId, id).update();
        return 1;
    }

    @Autowired
    private UserService userService;

    @Autowired
    private VoteService voteService;

    @Override
    public ResponseData voteComment(VoteCommentReq req, UserVo userVo) {

        //帖子评论
        VoteComment voteComment = new VoteComment(req, userVo);


        //帖子-->评论
        if (ObjectUtil.isEmpty(req.getParentId()) || ObjectUtil.equal(0L, req.getParentId())) {
            //顶级评论id
            voteComment.setTopId(voteComment.getId());

        } else {
            //查询上级评论
            VoteComment parentVoteComment = this.getById(req.getParentId());

            //评论用户
            voteComment.setParentUserId(parentVoteComment.getUserId())
                    .setParentUserType(parentVoteComment.getUserType());

            voteComment.setTopId(parentVoteComment.getTopId());

            //上级id
            if (ObjectUtil.isNotEmpty(parentVoteComment.getParentIds())) {
                voteComment.setParentIds(parentVoteComment.getParentIds() + "," + parentVoteComment.getId());
            } else {
                voteComment.setParentIds(parentVoteComment.getId() + "");
            }

        }

        this.save(voteComment);

        //1 帖子 2 帖子评论
        Integer type = ObjectUtil.equal(0L, req.getParentId()) || ObjectUtil.isEmpty(req.getParentId()) ? 1 : 2;

        //修改评论数(只要针对这个投票下的评论 投票评论数都要+1)
        voteMapper.updateVote(new Vote().setId(voteComment.getVoteId()).setCommentNum(1));
        //投票评论 所有上级评论数+1
        if (ObjectUtil.equal(2, type)) {
            //上级评论ids
            List<String> pids = Arrays.stream(voteComment.getParentIds().split(",")).collect(Collectors.toList());

            List<VoteComment> voteComments = pids.stream().map(id -> {
                        VoteComment comment = new VoteComment().setId(Long.valueOf(id)).setCommentNum(1);
                        comment.setUpdateTime(DateUtils.getNowDate());
                        return comment;
                    }
            ).collect(Collectors.toList());

            this.baseMapper.updateVoteCommentBatch(voteComments);
        }


        //返回结果
        VoteCommentResp commentResp = baseMapper.getVoteCommentResp(voteComment.getId(), userVo);

        if (commentResp != null) {

            UserVo parentUserVo = new UserVo(voteComment.getParentUserType(), voteComment.getParentUserId());

            Set<UserVo> userVoSet = CollectionUtil.newHashSet(userVo, parentUserVo);
            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, userVo);

            commentResp.setUserInfo(userMap.get(userVo));

            commentResp.setParentUserInfo(userMap.get(parentUserVo));
        }

        //推送消息
        pushMessage(req, userVo, true);
        return ResponseData.success(commentResp);
    }

    @Autowired
    private InteractionMessageRecordService interactionMessageRecordService;

    /**
     * 推送消息
     *
     * @param req
     * @param userVo
     * @param isPush
     */
    private void pushMessage(VoteCommentReq req, UserVo userVo, Boolean isPush) {

        InteractionMessageEnums enums = ObjectUtil.equal(0L, req.getParentId()) ? InteractionMessageEnums.COMMENT_POST : InteractionMessageEnums.REPLY_POST_COMMENT;

        //帖子id
        Long voteId = null;

        //接收消息用户
        UserVo sendUserVo = null;

        if (ObjectUtil.equal(0L, req.getParentId())) {
            //评论帖子
            voteId = req.getVoteId();
            //帖子
            Vote vote = voteService.getById(voteId);
        } else {
            //回复评论
            VoteComment voteComment = this.getById(req.getParentId());
            voteId = voteComment.getVoteId();
            sendUserVo = new UserVo(voteComment.getUserType(), voteComment.getUserId());
        }
        //互动消息
        interactionMessageRecordService.addInteractionMessage(userVo, sendUserVo, PublicCommon.InteractionMessage.评论, voteId, isPush, enums);

    }

    @Override
    public ResponseData voteCommentPage(VoteCommentPageReq req, UserVo userVo) {

        //筛去拉黑与被拉黑用户
        List<UserVo> blockUserList = userService.blockUserList(userVo);
        req.setBlockUserList(blockUserList);

        //筛去屏蔽用户
        List<UserVo> shieldUserList = userService.shieldUserList(userVo);
        req.setShieldUserList(shieldUserList);

        Page<VoteCommentPageResp> page = this.baseMapper.voteCommentPage(new Page<>(req.getPageNo(), req.getPageSize()), req, userVo);

        if (!page.getRecords().isEmpty()) {
            Set<UserVo> userVoSet = page.getRecords().stream().map(votePageResp -> new UserVo(votePageResp.getUserType(), votePageResp.getUserId())).collect(Collectors.toSet());
            Set<UserVo> parentUserVoSet = page.getRecords().stream().map(votePageResp -> new UserVo(votePageResp.getParentUserType(), votePageResp.getParentUserId())).collect(Collectors.toSet());

            userVoSet.addAll(parentUserVoSet);

            List<VoteCommentPageResp> voteCommentList = twoCommentList(req, userVo, page);

            voteCommentList.stream().forEach(votePageResp -> {
                userVoSet.add(new UserVo(votePageResp.getUserType(), votePageResp.getUserId()));
                userVoSet.add(new UserVo(votePageResp.getParentUserType(), votePageResp.getParentUserId()));
            });


            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, userVo);

            List<UserVo> userVoList = CollectionUtil.addAllIfNotContains(blockUserList, shieldUserList);

            Map<Long, Integer> commentNumMap = getCommentNumMap(userVoList, page.getRecords());

            voteCommentList.stream().forEach(resp -> {
                resp.setUserInfo(userMap.get(new UserVo(resp.getUserType(), resp.getUserId())));
                resp.setParentUserInfo(userMap.get(new UserVo(resp.getParentUserType(), resp.getParentUserId())));
            });
            //获取二级评论
            Map<Long, List<VoteCommentPageResp>> map = voteCommentList.stream().collect(Collectors.groupingBy(VoteCommentPageResp::getParentId));
            ;


            page.getRecords().stream().forEach(resp -> {
                resp.setUserInfo(userMap.get(new UserVo(resp.getUserType(), resp.getUserId())));
                resp.setParentUserInfo(userMap.get(new UserVo(resp.getParentUserType(), resp.getParentUserId())));
                if (commentNumMap.get(resp.getId()) != null) {
                    resp.setCommentNum(resp.getCommentNum() - commentNumMap.get(resp.getId()));
                }

                //二级评论
                resp.setChildrenList(map.get(resp.getId()));
            });
        }

        return ResponseData.success(new PageResult<>(page));
    }

    /**
     * 获取二级评论ID
     *
     * @param req
     * @param userVo
     * @param page
     * @return
     */
    private List<VoteCommentPageResp> twoCommentList(VoteCommentPageReq req, UserVo userVo, Page<VoteCommentPageResp> page) {

        Map<Long, List<VoteCommentPageResp>> map = new HashMap<>();

        if (ObjectUtil.isEmpty(req.getParentId())) {
            //一级评论ID
            List<Long> parentIds = page.getRecords().stream().map(VoteCommentPageResp::getId).collect(Collectors.toList());

            if (CollectionUtil.isEmpty(parentIds)) {
                return new ArrayList<>();
            }
            //查询二级评论
            List<VoteCommentPageResp> voteCommentList = this.baseMapper.voteCommentList(req, userVo, parentIds);

            return voteCommentList;
        }
        return new ArrayList<>();
    }

    private Map<Long, Integer> getCommentNumMap(List<UserVo> userVoList, List<VoteCommentPageResp> respList) {

        if (userVoList.size() == 0) {
            return new HashMap<>();
        }
        List<Long> commentIds = respList.stream().map(VoteCommentPageResp::getId).collect(Collectors.toList());
        //查询用户对应评论的数量 key一级评论id value 隐藏数量
        List<CommentNum> commentNums = voteCommentMapper.selectCommentNumList(commentIds, userVoList);

        Map<Long, Integer> commentNumMap = new HashMap<>();
        commentNums.stream().forEach(s -> {
            commentNumMap.put(s.getVoteId(), s.getCommentNum());
        });
        return commentNumMap;
    }

    @Override
    public ResponseData deleteComment(DeleteCommentReq req, UserVo userVo) {

        boolean update = this.lambdaUpdate().set(VoteComment::getDelFlag, PublicCommon.删除)
                .eq(VoteComment::getUserType, userVo.getUserType())
                .eq(VoteComment::getUserId, userVo.getUserId())
                .eq(VoteComment::getId, req.getId())
                .eq(VoteComment::getDelFlag, PublicCommon.启用).update();

        if (update) {
            afterDeleteComment(req.getId());
        }
        return ResponseData.success();
    }

    private void afterDeleteComment(Long objectId) {

        VoteComment voteComment = this.getById(objectId);

        //1 投票 2 评论
        Integer type = ObjectUtil.equal(0L, voteComment.getParentId()) ? 1 : 2;

        Integer num = -(voteComment.getCommentNum() + 1);
        //帖子评论 上级数量
        if (ObjectUtil.equal(2, type)) {
            //当前评论上级ids
            List<String> pids = Arrays.stream(voteComment.getParentIds()
                    .split(",")).collect(Collectors.toList());
            num = -1 * pids.size();

            //上级评论数都要减去当前删除评论数 + 1(本身评论)
            List<VoteComment> voteComments = pids.stream().map(id -> {
                VoteComment comment = new VoteComment().setId(Long.valueOf(id)).setCommentNum(-1 * (voteComment.getCommentNum() + 1));
                comment.setUpdateTime(DateUtils.getNowDate());
                return comment;
            }).collect(Collectors.toList());

            this.baseMapper.updateVoteCommentBatch(voteComments);

        }
        this.lambdaUpdate().set(VoteComment::getDelFlag, PublicCommon.删除)
                .like(VoteComment::getParentIds, objectId)
                .eq(VoteComment::getDelFlag, PublicCommon.启用).update();


        //修改评论数
        voteMapper.updateVote(new Vote().setId(voteComment.getVoteId()).setCommentNum(num));
    }

    @Override
    public int deleteCommentByIds(Long[] ids, Integer delFlag) {

        if (PublicCommon.删除.equals(delFlag)) {
            for (Long objectId : ids) {
                afterDeleteComment(objectId);
            }
        }

        this.lambdaUpdate().set(VoteComment::getDelFlag, delFlag).in(VoteComment::getId, ids).update();
        return 1;
    }

    @Autowired
    private BusinessUtil businessUtil;


    @Autowired
    private VoteMapper voteMapper;

    /**
     * 修改评论数
     *
     * @param objectId 评论主体id
     * @param type     1投票 2 投票评论
     * @param num
     */
    private void updateVoteCommentNum(Long objectId, Integer type, Integer num) {

        switch (type) {
            case 1:
                voteMapper.updateVote(new Vote().setId(objectId).setCommentNum(num));
                break;
            case 2:
                this.updateVoteComment(new VoteComment().setId(objectId).setCommentNum(num));
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + type);
        }
    }


    @Override
    public Map<Long, Integer> commentNumMap(List<Long> voteIds, List<UserVo> userVoList, Long parentId) {

        List<CommentNum> commentNums = voteCommentMapper.selectVoteCommentNumList(voteIds, userVoList, parentId);

        Map<Long, Integer> commentNumMap = new HashMap<>();
        commentNums.stream().forEach(s -> {
            commentNumMap.put(s.getVoteId(), s.getCommentNum());
        });

        return commentNumMap;
    }

    @Override
    public ResponseData<VoteCommentResp> voteCommentDetail(Long id, UserVo userVo) {
        //返回结果
        VoteCommentResp commentResp = baseMapper.getVoteCommentResp(id, userVo);

        if (commentResp != null) {

            UserVo parentUserVo = new UserVo(commentResp.getParentUserType(), commentResp.getParentUserId());
            UserVo user = new UserVo(commentResp.getUserType(), commentResp.getUserId());

            Set<UserVo> userVoSet = CollectionUtil.newHashSet(user, parentUserVo);
            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, userVo);

            commentResp.setUserInfo(userMap.get(user));

            commentResp.setParentUserInfo(userMap.get(parentUserVo));
        }

        return ResponseData.success(commentResp);
    }

    @Override
    public ResponseData<PageResult<Page<VoteCommentPageResp>>> voteCommentDialoguePage(DialoguePageReq req, UserVo userVo) {
        Page<VoteCommentPageResp> page = this.baseMapper.voteCommentDialoguePage(new Page<>(req.getPageNo(), req.getPageSize()), req, userVo);

        if (!page.getRecords().isEmpty()) {
            Set<UserVo> userVoSet = page.getRecords().stream().map(votePageResp -> new UserVo(votePageResp.getUserType(), votePageResp.getUserId())).collect(Collectors.toSet());
            Set<UserVo> parentUserVoSet = page.getRecords().stream().map(votePageResp -> new UserVo(votePageResp.getParentUserType(), votePageResp.getParentUserId())).collect(Collectors.toSet());

            userVoSet.addAll(parentUserVoSet);

            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, userVo);

            page.getRecords().stream().forEach(resp -> {
                resp.setUserInfo(userMap.get(new UserVo(resp.getUserType(), resp.getUserId())));
                resp.setParentUserInfo(userMap.get(new UserVo(resp.getParentUserType(), resp.getParentUserId())));
            });
        }

        return ResponseData.success(new PageResult<>(page));
    }


}
