package org.dromara.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.ObjectUtils;
import org.dromara.common.core.utils.DateUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.domain.communityNews.CommentContent;
import org.dromara.domain.communityNews.CommentIndex;
import org.dromara.domain.communityNews.CommunityNews;
import org.dromara.domain.communityNews.bo.CommentIndexBo;
import org.dromara.domain.communityNews.vo.CommentChildrenVo;
import org.dromara.domain.communityNews.vo.CommentIndexShVo;
import org.dromara.domain.communityNews.vo.CommentIndexVo;
import org.dromara.domain.communityNews.vo.CommentIndexVoOld;
import org.dromara.mapper.CommentContentMapper;
import org.dromara.mapper.CommentIndexMapper;
import org.dromara.mapper.CommunityNewsMapper;
import org.dromara.service.ICommentIndexService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.List;
import java.util.Map;

import static org.dromara.common.core.constant.Constants.*;

/**
 * 社区资讯评论Service业务层处理
 *
 * @author boman
 * @date 2025-04-11
 */
@RequiredArgsConstructor
@Service
public class CommentIndexServiceImpl implements ICommentIndexService {

    private final CommentIndexMapper baseMapper;
    private final CommentContentMapper commentContentMapper;
    private final CommunityNewsMapper communityNewsMapper;
    /**
     * 查询社区资讯评论
     *
     * @param commentId 主键
     * @return 社区资讯评论
     */
    @Override
    public CommentIndexVo queryById(Long commentId) {
        return baseMapper.selectVoById(commentId);
    }

    /**
     * 分页查询社区资讯评论列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 社区资讯评论分页列表
     */
    @Override
    public TableDataInfo<CommentIndexVo> queryPageList(CommentIndexBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<CommentIndex> lqw = buildQueryWrapper(bo);
        Page<CommentIndexVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询社区资讯评论-----审核列表
     */
    @Override
    public TableDataInfo<CommentIndexShVo> commentSh(CommentIndexShVo commentIndexShVo, PageQuery pageQuery) {
        Page<CommentIndexShVo> result = baseMapper.commentSh(pageQuery.build(), commentIndexShVo);
        return TableDataInfo.build(result);
    }

    /**
     * 根据查询所有一级评论组带子集总数组装成前端所需要的数据结构 带分页
     *
     * @param commentIndex
     * @return
     */
    @Override
    public TableDataInfo<CommentIndexVoOld> getRootComment(CommentIndex commentIndex, PageQuery pageQuery) {
        Page<CommentIndexVoOld> parentComment = baseMapper.getRootComment(pageQuery.build(), commentIndex);
        Long userId = LoginHelper.getUserId();
        List<CommentIndexVoOld> rootComment = parentComment.getRecords();
        if (rootComment != null && rootComment.size() > 0) {
            //要判断所有评论当前人员是否点赞过
            //该用户点赞回复的key
            String myLikeTwoKey = TWO_MY_LIKE + userId;
            List<Long> communityIdList = RedisUtils.getCacheList(myLikeTwoKey);
            if (communityIdList != null && communityIdList.size() > 0) {
                for (CommentIndexVoOld commentIndexVo : rootComment) {
                    if (communityIdList.contains(commentIndexVo.getId())) {
                        commentIndexVo.setIsLike("Y");
                    }
                }
            }
            for (CommentIndexVoOld commentIndexVo : rootComment) {
                //是否是自己的评论
                if (commentIndexVo.getCommentUser().getId().equals(userId)) {
                    commentIndexVo.setIsMyself("Y");
                }
            }
        }
        return TableDataInfo.build(parentComment);
    }

    /**
     * 根据parent_id查询所有评论组装成前端所需要的子集数据结构 带分页
     */
    @Override
    public TableDataInfo<CommentChildrenVo> getParentComment(CommentIndex commentIndex, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        Page<CommentChildrenVo> parentComment = baseMapper.getParentComment(pageQuery.build(), commentIndex);
        List<CommentChildrenVo> allComment = parentComment.getRecords();
        //要判断所有评论当前人员是否点赞过
        if (allComment != null && allComment.size() > 0) {
            //要判断所有评论当前人员是否点赞过
            //该用户点赞回复的key
            String myLikeTwoKey = TWO_MY_LIKE + userId;
            List<Long> communityIdList = RedisUtils.getCacheList(myLikeTwoKey);
            if (communityIdList != null && communityIdList.size() > 0) {
                for (CommentChildrenVo commentChildrenVo : allComment) {
                    if (communityIdList.contains(commentChildrenVo.getId())) {
                        commentChildrenVo.setIsLike("Y");
                    }
                }
            }
            for (CommentChildrenVo commentChildrenVo : allComment) {
                //是否是自己的评论
                if (commentChildrenVo.getCommentUser().getId().equals(userId)) {
                    commentChildrenVo.setIsMyself("Y");
                }
            }
        }
        return TableDataInfo.build(parentComment);
    }


    /**
     * 查询符合条件的社区资讯评论列表
     *
     * @param bo 查询条件
     * @return 社区资讯评论列表
     */
    @Override
    public List<CommentIndexVo> queryList(CommentIndexBo bo) {
        LambdaQueryWrapper<CommentIndex> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<CommentIndex> buildQueryWrapper(CommentIndexBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<CommentIndex> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(CommentIndex::getCommentId);
        lqw.eq(bo.getCommunityId() != null, CommentIndex::getCommunityId, bo.getCommunityId());
        lqw.eq(StringUtils.isNotBlank(bo.getCommunityType()), CommentIndex::getCommunityType, bo.getCommunityType());
        lqw.eq(StringUtils.isNotBlank(bo.getCommunityTitle()), CommentIndex::getCommunityTitle, bo.getCommunityTitle());
        lqw.eq(bo.getIsRoot() != null, CommentIndex::getIsRoot, bo.getIsRoot());
        lqw.eq(bo.getParentId() != null, CommentIndex::getParentId, bo.getParentId());
        lqw.eq(bo.getUserId() != null, CommentIndex::getUserId, bo.getUserId());
        lqw.like(StringUtils.isNotBlank(bo.getNickName()), CommentIndex::getNickName, bo.getNickName());
        lqw.eq(StringUtils.isNotBlank(bo.getAvatar()), CommentIndex::getAvatar, bo.getAvatar());
        lqw.eq(bo.getToUserId() != null, CommentIndex::getToUserId, bo.getToUserId());
        lqw.like(StringUtils.isNotBlank(bo.getToNickName()), CommentIndex::getToNickName, bo.getToNickName());
        lqw.eq(StringUtils.isNotBlank(bo.getToAvatar()), CommentIndex::getToAvatar, bo.getToAvatar());
        lqw.eq(StringUtils.isNotBlank(bo.getToRoot()), CommentIndex::getToRoot, bo.getToRoot());
        lqw.eq(bo.getContentId() != null, CommentIndex::getContentId, bo.getContentId());
        lqw.eq(StringUtils.isNotBlank(bo.getCommentContent()), CommentIndex::getCommentContent, bo.getCommentContent());
        return lqw;
    }

    /**
     * 新增社区资讯评论
     *
     * @param bo 社区资讯评论
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(CommentIndexBo bo) {
        CommentIndex commentIndex = MapstructUtils.convert(bo, CommentIndex.class);
        validEntityBeforeSave(commentIndex);
        boolean flag = true;
        //有社区资讯ID才能新增评论
        Long communityId = commentIndex.getCommunityId();
        if (communityId != null) {
            Long userId = commentIndex.getUserId();
            //需要插入评论内容表
            CommentContent commentContent = new CommentContent();
            commentContent.setUserId(userId);
            commentContent.setCommentContent(commentIndex.getCommentContent());
            commentContentMapper.insert(commentContent);
            commentIndex.setCreateTime(DateUtils.getNowDate());
            commentIndex.setContentId(commentContent.getContentId());
            flag = baseMapper.insert(commentIndex) > 0;
            //再把评论内容表更新上资讯评论表id
            commentContent.setCommentId(commentIndex.getCommentId());
            commentContentMapper.updateById(commentContent);
            //记录该社区资讯评论的数量
            String communityCommentCountKey = COMMUNITY_COMMENT_COUNT + communityId;
            Integer communityCommentCount = RedisUtils.getCacheObject(communityCommentCountKey);
            if (communityCommentCount == null) {
                RedisUtils.setCacheObject(communityCommentCountKey, 1);
            } else {
                //评论数量+1
                RedisUtils.setCacheObject(communityCommentCountKey, communityCommentCount + 1);
            }
        }
        return flag;
    }

    /**
     * 修改社区资讯评论
     *
     * @param bo 社区资讯评论
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(CommentIndexBo bo) {
        CommentIndex update = MapstructUtils.convert(bo, CommentIndex.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(CommentIndex entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除社区资讯评论信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 逻辑删除社区资讯评论
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteCommentIndexByCommentId(Long commentId) {
        //todo 管理员能删除评论
        //只能删除自己的评论
        CommentIndex commentIndex = baseMapper.selectById(commentId);
        Boolean flag = false;
        int result = 0;
        int communityCommentCount = 0;
        Long userId = LoginHelper.getUserId();
        //查找出所有parent_id = commentId的commentId
        if (commentIndex != null && commentIndex.getUserId().equals(userId)) {
            //社区资讯id
            Long communityId = commentIndex.getCommunityId();
            commentIndex.setDelFlag(Y);
            flag = baseMapper.updateById(commentIndex) > 0;
            CommentContent commentContent = new CommentContent();
            commentContent.setCommentId(commentId);
            commentContent.setDelFlag(Y);
            //删除评论内容表数据
            commentContentMapper.updateById(commentContent);
            //如果是根评论删除，删除所有子评论
            if (1 == commentIndex.getIsRoot()) {
                //查找出所有parent_id = commentId的commentId
                //commentIdList = commentIndexMapper.selectCommentIdListByCommentId(commentId);
                int i = baseMapper.update(commentIndex, new LambdaUpdateWrapper<CommentIndex>().eq(CommentIndex::getParentId, commentId));
                result = result + i;
                //删除评论内容表子集数据
                commentContentMapper.deleteCommentContentByCommentId(commentId);
            }
            //删除该资讯的评论数量
            String communityCommentCountKey = COMMUNITY_COMMENT_COUNT + communityId;
            communityCommentCount = RedisUtils.getCacheObject(communityCommentCountKey);
            if (communityCommentCount != 0) {
                //删除所有的评论数量 = 根评论数量+子评论数量
                communityCommentCount = communityCommentCount - result;
                if (communityCommentCount < 0) {
                    communityCommentCount = 0;
                }
                RedisUtils.setCacheObject(communityCommentCountKey, communityCommentCount);
            }
            //删除社区资讯评论点赞的数量永久key key=two_like_count:{评论id} value = 该评论的点赞数量
            RedisUtils.deleteObject(TWO_LIKE_COUNT + commentId);
            //社区资讯回复点赞的人员集合的key
            RedisUtils.deleteObject(TWO_LIKE + commentId);
            //对应用户点赞的回复key=two_my_like:{用户id} value = [评论id]
            List<Long> commentIdList = RedisUtils.getCacheList(TWO_MY_LIKE + userId);
            if (commentIdList != null && commentIdList.size() > 0) {
                commentIdList.remove(commentId);
            }
            RedisUtils.deleteObject(TWO_MY_LIKE + userId);
            if (commentIdList != null && commentIdList.size() > 0) {
                RedisUtils.setCacheList(TWO_MY_LIKE + userId, commentIdList);
            }
/*            //删除该资讯点赞的数量需要知道所有评论的id
            //首先获取该文章资讯的总点赞数量
            Integer likeCount = redisCache.getCacheObject(ONE_LIKE_COUNT + communityId);
            //再获取删除的评论的点赞数量
            Integer commentLikeCount = redisCache.getCacheObject(TWO_LIKE_COUNT + commentId);
            //所有子集的点赞数量
            int commentLikeChildrenCount = 0;
            if (commentIdList.size() > 0) {
                //说明删除了子集、获取所有子集的点赞数量
                for (Long commentIdChildren : commentIdList) {
                    String commentLikeChildrenCountString = redisCache.getCacheObject(TWO_LIKE_COUNT + commentIdChildren);
                    if (StringUtils.isNotBlank(commentLikeChildrenCountString)) {
                        commentLikeChildrenCount = commentLikeChildrenCount + Integer.parseInt(commentLikeChildrenCountString);
                    }
                }
            }
            if (commentLikeCount == null){
                commentLikeCount = 0;
            }
            if (likeCount == null){
                likeCount = 0;
            }
            //把删除后点赞数量写入到redis
            likeCount = likeCount - commentLikeCount - commentLikeChildrenCount;
            if (likeCount < 0){
                likeCount = 0;
            }
            redisCache.setCacheObject(ONE_LIKE_COUNT + communityId, likeCount);*/
            //删除评论需要根据这个评论是根评论还子评论，根评论删除对应资讯发布人的未读互动里面对应的值(如果有)根评论还会删除所有子评论，子评论删除评论对象的未读互动
            Integer isRoot = commentIndex.getIsRoot();
            if (1 == isRoot) {
                //如果是根评论先查询是否有子集评论
                List<CommentIndex> commentIndexList = baseMapper.selectCommentIdListByCommentId(commentId);
                if (commentIndexList != null && commentIndexList.size() > 0) {
                    for (CommentIndex index : commentIndexList) {
                        //删除未读互动中的子评论相关信息
                        deleteCommentChildren(index);
                    }
                }
                //删除根评论相关信息
                //根据资讯id查询资讯发布人的id
                CommunityNews communityNews = communityNewsMapper.selectById(communityId);
                Long toUserId = communityNews.getUserId();
                String commentInteractionUserKey = COMMENT_INTERACTION_USER + toUserId;
                //hKey={targetType:targetId}
                String hKey = ONE + ":" + commentId;
                if (RedisUtils.hasCacheMapKey(commentInteractionUserKey, hKey)) {
                    //说明有对应的未读互动删除对应的key
                    RedisUtils.delCacheMapValue(commentInteractionUserKey, hKey);
                    //目标人员的未读数量-1
                    String commentInteractionUserCountKey = COMMENT_INTERACTION_USER_COUNT + toUserId;
                    Object commentInteractionUserCount = RedisUtils.getCacheObject(commentInteractionUserCountKey);
                    if (ObjectUtils.isNotEmpty(commentInteractionUserCount)) {
                        RedisUtils.setCacheObject(commentInteractionUserCountKey, Math.max(Integer.parseInt(commentInteractionUserCount.toString()) - 1, 0));
                    }
                    //对应资讯下的未读数量-1
                    Object communityUserCount = RedisUtils.getCacheMapValue(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + toUserId, communityId.toString());
                    if (ObjectUtils.isNotEmpty(communityUserCount)) {
                        RedisUtils.setCacheMapValue(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + toUserId, communityId.toString(), Math.max(Integer.parseInt(communityUserCount.toString()) - 1, 0));
                    }
                }
            } else {
                //删除未读互动中的子评论相关信息
                deleteCommentChildren(commentIndex);
            }
        }
        return flag;
    }
    /**
     * 删除未读互动中的子评论相关信息
     *
     * @param commentIndex
     */
    public void deleteCommentChildren(CommentIndex commentIndex) {
        Long commentId = commentIndex.getCommentId();
        Long communityId = commentIndex.getCommunityId();
        //子评论
        //获取到回复的人的id
        Long toUserId = commentIndex.getToUserId();
        //判断该用户是否有未读的子评论互动
        String commentInteractionUserKey = COMMENT_INTERACTION_USER + toUserId;
        //hKey={targetType:targetId}
        String hKey = FOR + ":" + commentId;
        if (RedisUtils.hasCacheMapKey(commentInteractionUserKey, hKey)) {
            //说明有对应的未读互动删除对应的key
            RedisUtils.delCacheMapValue(commentInteractionUserKey, hKey);
            //目标人员的未读数量-1
            String commentInteractionUserCountKey = COMMENT_INTERACTION_USER_COUNT + toUserId;
            Object commentInteractionUserCount = RedisUtils.getCacheObject(commentInteractionUserCountKey);
            if (ObjectUtils.isNotEmpty(commentInteractionUserCount)) {
                RedisUtils.setCacheObject(commentInteractionUserCountKey, Math.max(Integer.parseInt(commentInteractionUserCount.toString()) - 1, 0));
            }
            //对应资讯下的未读数量-1
            Object communityUserCount = RedisUtils.getCacheMapValue(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + toUserId, communityId.toString());
            if (ObjectUtils.isNotEmpty(communityUserCount)) {
                RedisUtils.setCacheMapValue(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + toUserId, communityId.toString(), Math.max(Integer.parseInt(communityUserCount.toString()) - 1, 0));
            }
        }
    }
}
