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

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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.page.PageResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.controller.req.CommentPageReq;
import com.ruoyi.controller.req.CommentReq;
import com.ruoyi.controller.req.DialoguePageReq;
import com.ruoyi.controller.req.WorksCommentReq;
import com.ruoyi.controller.resp.*;
import com.ruoyi.enums.message.InteractionMessageEnums;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.frequency.news.entity.News;
import com.ruoyi.frequency.news.mapper.NewsMapper;
import com.ruoyi.frequency.vote.entity.Vote;
import com.ruoyi.frequency.votecomment.entity.VoteComment;
import com.ruoyi.frequency.works.entity.Works;
import com.ruoyi.frequency.workscomment.entity.WorksComment;
import com.ruoyi.message.frequency.interactionmessagerecord.service.InteractionMessageRecordService;
import com.ruoyi.post.controller.req.DeleteCommentReq;
import com.ruoyi.response.ResponseData;
import com.ruoyi.vo.UserInfo;
import com.ruoyi.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.frequency.comment.mapper.CommentMapper;
import com.ruoyi.frequency.comment.entity.Comment;
import com.ruoyi.frequency.comment.service.CommentService;

/**
 * 评论(新闻)Service业务层处理
 *
 * @author liwenlong
 * @date 2024-04-15
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment>  implements CommentService
{
    @Autowired
    private CommentMapper commentMapper;

    /**
     * 查询评论(新闻)
     *
     * @param id 评论(新闻)主键
     * @return 评论(新闻)
     */
    @Override
    public Comment selectCommentById(Long id)
    {
        return commentMapper.selectCommentById(id);
    }

    /**
     * 查询评论(新闻)列表
     *
     * @param comment 评论(新闻)
     * @return 评论(新闻)
     */
    @Override
    public List<Comment> selectCommentList(Comment comment)
    {
        List<Comment> comments = commentMapper.selectCommentList(comment);
        if (!comments.isEmpty()) {
            Set<UserVo> userVoSet = comments.stream().map(s -> new UserVo(s.getUserType(), s.getUserId())).collect(Collectors.toSet());
            Set<UserVo> parentUserVoSet = comments.stream().map(s -> new UserVo(s.getParentUserType(), s.getParentUserId())).collect(Collectors.toSet());

            userVoSet.addAll(parentUserVoSet);

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

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

    /**
     * 新增评论(新闻)
     *
     * @param comment 评论(新闻)
     * @return 结果
     */
    @Override
    public int insertComment(Comment comment)
    {
        comment.setCreateData();
        return commentMapper.insert(comment);
    }

    /**
     * 修改评论(新闻)
     *
     * @param comment 评论(新闻)
     * @return 结果
     */
    @Override
    public int updateComment(Comment comment)
    {
        comment.setUpdateData();
        return commentMapper.updateComment(comment);
    }



    @Autowired
    private UserService userService;

    @Override
    public ResponseData<CommentResp> comment(CommentReq req, UserVo userVo) {
        //评论
        Comment comment = new Comment(req,userVo);

        //新闻-->评论
        if (ObjectUtil.isEmpty(req.getParentId()) || ObjectUtil.equal(0L,req.getParentId())){
            //顶级评论id
            comment.setTopId(comment.getId());
        }else {
            //查询上级评论
            Comment parentComment = this.getById(req.getParentId());

            //评论用户
            comment.setParentUserId(parentComment.getUserId())
                    .setParentUserType(parentComment.getUserType());

            comment.setTopId(parentComment.getTopId());

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

        this.save(comment);

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

        //修改评论数(只要针对这个新闻下的评论 新闻评论数都要+1)
        newsMapper.updateNews(new News().setId(comment.getLinkId()).setCommentNum(1));
        //新闻评论 所有上级评论数+1
        if (ObjectUtil.equal(2,type)){
            //上级评论ids
            List<String> pids = Arrays.stream(comment.getParentIds().split(",")).collect(Collectors.toList());

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

            this.baseMapper.updateCommentBatch(comments);
        }

        //返回结果
        CommentResp commentResp = baseMapper.getCommentResp(comment.getId(),userVo);

        if (commentResp != null){

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

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

        //关联id
        Long linkId = null;

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

        if (ObjectUtil.equal(0L,req.getParentId())){
            return;
        }

        //回复评论
        Comment comment = this.getById(req.getParentId());
        linkId = comment.getLinkId();
        sendUserVo = new UserVo(comment.getUserType(),comment.getUserId());

        //互动消息
        interactionMessageRecordService.addInteractionMessage(userVo,sendUserVo,PublicCommon.InteractionMessage.评论,linkId,isPush, enums);

    }

    @Autowired
    private NewsMapper newsMapper;

    private void updateCommentNum(Long objectId, Integer type, Integer num) {
        switch (type){
            case 1:
                newsMapper.updateNews(new News().setId(objectId).setCommentNum(num));
                break;
            case 2:
                this.updateComment(new Comment().setId(objectId).setCommentNum(num));
                break;
            default:
                throw new IllegalStateException("Unexpected value: " + type);
        }
    }

    @Override
    public ResponseData<PageResult<Page<CommentPageResp>>> commentPage(CommentPageReq req, UserVo userVo) {
        //筛去拉黑与被拉黑用户
        List<UserVo> blockUserList = userService.blockUserList(userVo);
        req.setBlockUserList(blockUserList);

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

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

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

            userVoSet.addAll(parentUserVoSet);

            List<CommentPageResp>  commentList = twoCommentList(req,userVo,page);

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


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

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

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

            commentList.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<CommentPageResp>> map = commentList.stream().collect(Collectors.groupingBy(CommentPageResp::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));
    }

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

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

    private List<CommentPageResp> twoCommentList(CommentPageReq req, UserVo userVo, Page<CommentPageResp> page) {

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

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

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

    @Override
    public ResponseData deleteComment(DeleteCommentReq req, UserVo userVo) {
        boolean update = this.lambdaUpdate().set(Comment::getDelFlag, PublicCommon.删除)
                .eq(Comment::getUserType,userVo.getUserType())
                .eq(Comment::getUserId, userVo.getUserId())
                .eq(Comment::getId, req.getId())
                .eq(Comment::getDelFlag, PublicCommon.启用).update();

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

    private void afterDeleteComment(Long objectId) {

        Comment comment = this.getById(objectId);

        //1 新闻 2 新闻评论
        Integer type = ObjectUtil.equal(0L,comment.getParentId())?1: 2;

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

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

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


        //修改评论数
        newsMapper.updateNews(new News().setId(comment.getLinkId()).setCommentNum(num));
    }

    /**
     * 批量删除评论(新闻)
     *
     * @param ids 需要删除的评论(新闻)主键
     * @return 结果
     */
    @Override
    public int deleteCommentByIds(Long[] ids, Integer delFlag) {

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

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

    @Override
    public ResponseData<CommentResp> commentDetail(Long id, UserVo userVo) {
        CommentResp commentResp = baseMapper.getCommentResp(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<CommentPageResp>>> commentDialoguePage(DialoguePageReq req, UserVo userVo) {
        Page<CommentPageResp> page =  this.baseMapper.commentDialoguePage(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));
    }
}
