package com.ruoyi.post.frequency.postcomment.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.resp.CommentNum;
import com.ruoyi.enums.message.InteractionMessageEnums;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.message.frequency.interactionmessagerecord.service.InteractionMessageRecordService;
import com.ruoyi.post.controller.req.DeleteCommentReq;
import com.ruoyi.post.controller.req.PostCommentPageReq;
import com.ruoyi.post.controller.req.PostCommentReq;
import com.ruoyi.post.controller.resp.PostCommentPageResp;
import com.ruoyi.post.controller.resp.PostCommentResp;
import com.ruoyi.post.controller.vo.SelectedComment;
import com.ruoyi.post.frequency.post.entity.Post;
import com.ruoyi.post.frequency.post.mapper.PostMapper;
import com.ruoyi.post.frequency.post.service.PostService;
import com.ruoyi.post.frequency.postcomment.entity.PostComment;
import com.ruoyi.post.frequency.postcomment.mapper.PostCommentMapper;
import com.ruoyi.post.frequency.postcomment.service.PostCommentService;
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 PostCommentServiceImpl extends ServiceImpl<PostCommentMapper, PostComment> implements PostCommentService {
    @Autowired
    private PostCommentMapper postCommentMapper;

    /**
     * 查询帖子评论
     *
     * @param id 帖子评论主键
     * @return 帖子评论
     */
    @Override
    public PostComment selectPostCommentById(Long id) {
        PostComment postComment = postCommentMapper.selectPostCommentById(id);

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

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

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

        return postComment;
    }

    /**
     * 查询帖子评论列表
     *
     * @param postComment 帖子评论
     * @return 帖子评论
     */
    @Override
    public List<PostComment> selectPostCommentList(PostComment postComment) {
        List<PostComment> postComments = postCommentMapper.selectPostCommentList(postComment);

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

            userVoSet.addAll(parentUserVoSet);

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

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

        return postComments;
    }

    /**
     * 新增帖子评论
     *
     * @param postComment 帖子评论
     * @return 结果
     */
    @Override
    public int insertPostComment(PostComment postComment) {
        postComment.setCreateTime(DateUtils.getNowDate());
        return postCommentMapper.insertPostComment(postComment);
    }

    /**
     * 修改帖子评论
     *
     * @param postComment 帖子评论
     * @return 结果
     */
    @Override
    public int updatePostComment(PostComment postComment) {
        postComment.setUpdateTime(DateUtils.getNowDate());
        return postCommentMapper.updatePostComment(postComment);
    }

    /**
     * 修改帖子评论
     *
     * @param postCommentList 帖子评论
     * @return 结果
     */
    @Override
    public int updatePostCommentBatch(List<PostComment> postCommentList) {
        postCommentList.stream().forEach(postComment -> {
            postComment.setUpdateTime(DateUtils.getNowDate());
        });

        return postCommentMapper.updatePostCommentNumBatch(postCommentList);
    }


    /**
     * 修改帖子评论
     *
     * @param postComment 帖子评论
     * @return 结果
     */
    @Override
    public int updatePostCommentLikeNum(PostComment postComment, Integer num) {
        return postCommentMapper.updatePostCommentLikeNum(postComment.getId(), num);
    }

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

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

    @Autowired
    private UserService userService;

    @Autowired
    private PostService postService;

    @Override
    public ResponseData postComment(PostCommentReq req, UserVo userVo) {

        //帖子评论
        PostComment postComment = new PostComment(req, userVo);


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

            Post post = postService.getById(req.getPostId());
        } else {
            //查询上级评论
            PostComment parentPostComment = this.getById(req.getParentId());

            //评论用户
            postComment.setParentUserId(parentPostComment.getUserId())
                    .setParentUserType(parentPostComment.getUserType());

            postComment.setTopId(parentPostComment.getTopId());

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

        }

        this.save(postComment);

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

        //修改评论数(只要针对这个贴子下的评论 帖子评论数都要+1)
        postMapper.updateNumPost(postComment.getPostId(), PublicCommon.Post.评论数, 1);
        //修改热度时间
        postMapper.update(new Post().setTrendsTime(new Date()), new LambdaUpdateWrapper<Post>().eq(Post::getId, postComment.getPostId()));

        //帖子评论 所有上级评论数+1
        if (ObjectUtil.equal(2, type)) {
            //上级评论ids
            List<String> pids = Arrays.stream(postComment.getParentIds().split(",")).collect(Collectors.toList());

            List<PostComment> postComments = pids.stream().map(id -> new PostComment().setId(Long.valueOf(id)).setCommentNum(1)).collect(Collectors.toList());

            this.updatePostCommentBatch(postComments);
        }

        //返回结果
        PostCommentResp commentResp = baseMapper.getPostCommentResp(postComment.getId(), userVo);

        if (commentResp != null) {

            UserVo parentUserVo = new UserVo(postComment.getParentUserType(), postComment.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(PostCommentReq req, UserVo userVo, Boolean isPush) {

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

        //帖子id
        Long postId = null;

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

        if (ObjectUtil.equal(0L, req.getParentId())) {
            //评论帖子
            postId = req.getPostId();
            //帖子
            Post post = postService.getById(postId);
            sendUserVo = new UserVo(post.getUserType(), post.getUserId());
        } else {
            //回复评论
            PostComment postComment = this.getById(req.getParentId());
            postId = postComment.getPostId();
            sendUserVo = new UserVo(postComment.getUserType(), postComment.getUserId());
        }
        //互动消息
        interactionMessageRecordService.addInteractionMessage(userVo, sendUserVo, PublicCommon.InteractionMessage.评论, postId, isPush, enums);

    }

    @Override
    public ResponseData postCommentPage(PostCommentPageReq req, UserVo userVo) {

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

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

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

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

            userVoSet.addAll(parentUserVoSet);

            List<PostCommentPageResp> postCommentList = twoCommentList(req, userVo, page);

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


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

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

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

            postCommentList.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<PostCommentPageResp>> map = postCommentList.stream().collect(Collectors.groupingBy(PostCommentPageResp::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<PostCommentPageResp> twoCommentList(PostCommentPageReq req, UserVo userVo, Page<PostCommentPageResp> page) {

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

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

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

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

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

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

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

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

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

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

    private void afterDeleteComment(Long objectId) {

        PostComment postComment = this.getById(objectId);

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

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

            //上级评论数都要减去当前删除评论数 + 1(本身评论)
            List<PostComment> postComments = pids.stream().map(id -> new PostComment().setId(Long.valueOf(id)).setCommentNum(-1 * (postComment.getCommentNum() + 1))).collect(Collectors.toList());

            this.updatePostCommentBatch(postComments);

        }
        //删除当前评论所有下级评论
        this.lambdaUpdate().set(PostComment::getDelFlag, PublicCommon.删除)
                .like(PostComment::getParentIds, objectId)
                .eq(PostComment::getDelFlag, PublicCommon.启用).update();


        //修改评论数
        postMapper.updateNumPost(postComment.getPostId(), PublicCommon.Post.评论数, num);
    }


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

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

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

    @Autowired
    private BusinessUtil businessUtil;

    @Override
    public Map<Long, SelectedComment> getSelectedCommentMap(List<Long> commentIds, UserVo userVo) {

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

        if (CollectionUtil.isEmpty(commentIds)) {
            return map;
        }

        List<PostComment> postComments = this.lambdaQuery().in(PostComment::getId, commentIds).eq(PostComment::getParentId, 0L).eq(PostComment::getDelFlag, PublicCommon.启用).list();

        Set<UserVo> userVoSet = postComments.stream().map(postComment -> new UserVo(postComment.getUserType(), postComment.getUserId())).collect(Collectors.toSet());

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

        postComments.stream().forEach(postComment -> {
            map.put(postComment.getId(), new SelectedComment(2, postComment, userMap.get(new UserVo(postComment.getUserType(), postComment.getUserId()))));
        });

        return map;
    }

    @Override
    public Map<Long, SelectedComment> getSelectedNewCommentMap(List<Long> postIds, UserVo userVo) {
        Map<Long, SelectedComment> map = new HashMap<>();

        if (CollectionUtil.isEmpty(postIds)) {
            return map;
        }

        List<PostComment> postComments = postCommentMapper.selectedNewCommentList(postIds);

        Set<UserVo> userVoSet = postComments.stream().map(postComment -> new UserVo(postComment.getUserType(), postComment.getUserId())).collect(Collectors.toSet());

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

        postComments.stream().forEach(postComment -> {
            map.put(postComment.getPostId(), new SelectedComment(1, postComment, userMap.get(new UserVo(postComment.getUserType(), postComment.getUserId()))));
        });

        return map;
    }


    @Autowired
    private PostMapper postMapper;

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

        switch (type) {
            case 1:
                postMapper.updateNumPost(objectId, PublicCommon.Post.评论数, num);
                break;
            case 2:
                this.updatePostComment(new PostComment().setId(objectId).setCommentNum(num));
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + type);
        }
    }


    @Override
    public ResponseData<PostCommentResp> postCommentDetail(Long id, UserVo userVo) {
        //返回结果
        PostCommentResp commentResp = baseMapper.getPostCommentResp(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<PostCommentPageResp>>> postCommentDialoguePage(DialoguePageReq req, UserVo userVo) {
        Page<PostCommentPageResp> page = this.baseMapper.postCommentDialoguePage(new Page<>(req.getPageNo(), req.getPageSize()), req, userVo);

        if (!page.getRecords().isEmpty()) {
            Set<UserVo> userVoSet = page.getRecords().stream().map(postPageResp -> new UserVo(postPageResp.getUserType(), postPageResp.getUserId())).collect(Collectors.toSet());
            Set<UserVo> parentUserVoSet = page.getRecords().stream().map(postPageResp -> new UserVo(postPageResp.getParentUserType(), postPageResp.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));
    }

}
