package org.dromara.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.domain.R;
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.CommunityNews;
import org.dromara.domain.communityNews.bo.CommunityNewsBo;
import org.dromara.domain.communityNews.vo.CommentInteractionVo;
import org.dromara.domain.communityNews.vo.CommunityNewsVo;
import org.dromara.mapper.CommunityNewsMapper;
import org.dromara.service.ICommunityNewsService;
import org.springframework.stereotype.Service;

import java.util.*;

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

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

    private final CommunityNewsMapper baseMapper;

    /**
     * 查询社区资讯
     *
     * @param communityId 主键
     * @return 社区资讯
     */
    @Override
    public CommunityNewsVo queryById(Long communityId){
        CommunityNewsVo communityNews = baseMapper.selectVoById(communityId);
        communityNews.setIsStar("N");
        communityNews.setIsLike("N");
        communityNews.setUserShare(0L);
        String key = SHARE_COMMUNITY + communityId;
        if (RedisUtils.hasKey(key)) {
            long atomicValue = RedisUtils.getAtomicValue(key);
            communityNews.setUserShare(atomicValue);
        }
        Long userId = LoginHelper.getUserId();
        String likeOneKey = ONE_LIKE + communityId;
        List<Long> userIdList = RedisUtils.getCacheList(likeOneKey);
        if (userIdList != null && userIdList.size() > 0) {
            if (userIdList.contains(userId)) {
                communityNews.setIsLike("Y");
            }
        }
        //该资讯收藏人员的key
        String starsCommunityKey = STARS_COMMUNITY + communityId;
        List<Long> userIdListStars = RedisUtils.getCacheList(starsCommunityKey);
        if (userIdListStars != null && userIdListStars.size() > 0) {
            //判断该用户是否收藏过
            if (userIdListStars.contains(userId)) {
                communityNews.setIsStar("Y");
            }
        }
        //查询redis中的点赞数量，收藏数量，评论数量
        Object likeCount = RedisUtils.getCacheObject(ONE_LIKE_COUNT + communityId);
        if (ObjectUtils.isNotEmpty(likeCount)) {
            communityNews.setUserLikes(likeCount.toString());
        }
        //收藏
        Object startCount = RedisUtils.getCacheObject(STARS_USER_COUNT + communityId);
        if (ObjectUtils.isNotEmpty(startCount)) {
            communityNews.setUserStars(startCount.toString());
        }
        //评论
        Object communityCommentCount = RedisUtils.getCacheObject(COMMUNITY_COMMENT_COUNT + communityId);
        if (ObjectUtils.isNotEmpty(communityCommentCount)) {
            communityNews.setUserComment(communityCommentCount.toString());
        }
        return communityNews;
    }

    /**
     * 分页查询社区资讯列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 社区资讯分页列表
     */
    @Override
    public TableDataInfo<CommunityNewsVo> queryPageList(CommunityNewsBo bo, PageQuery pageQuery) {
        Long userId = LoginHelper.getUserId();
        LambdaQueryWrapper<CommunityNews> lqw = buildQueryWrapper(bo);
        Page<CommunityNewsVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<CommunityNewsVo> communityNewsList = result.getRecords();
        //设置是否有未读互动
        if (communityNewsList != null && communityNewsList.size() > 0) {
            for (CommunityNewsVo news : communityNewsList) {
                news.setIsInteraction("N");
                //key=comment_interaction_community_user_count:{userId} hkey = {community_id} value = 资讯下有多少个未读的互动(点赞，收藏，回复)
                if (RedisUtils.hasCacheMapKey(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + userId, news.getCommunityId().toString())) {
                    news.setIsInteraction("Y");
                }
            }
        }
        return TableDataInfo.build(result);
    }

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

    private LambdaQueryWrapper<CommunityNews> buildQueryWrapper(CommunityNewsBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<CommunityNews> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(CommunityNews::getCommunityId);
        lqw.eq(StringUtils.isNotBlank(bo.getCommunityTitle()), CommunityNews::getCommunityTitle, bo.getCommunityTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getCommunityType()), CommunityNews::getCommunityType, bo.getCommunityType());
        lqw.eq(StringUtils.isNotBlank(bo.getCommunityContent()), CommunityNews::getCommunityContent, bo.getCommunityContent());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), CommunityNews::getStatus, bo.getStatus());
        lqw.eq(bo.getPublishTime() != null, CommunityNews::getPublishTime, bo.getPublishTime());
        lqw.eq(bo.getUserId() != null, CommunityNews::getUserId, bo.getUserId());
        lqw.eq(bo.getStaffId() != null, CommunityNews::getStaffId, bo.getStaffId());
        lqw.like(StringUtils.isNotBlank(bo.getStaffName()), CommunityNews::getStaffName, bo.getStaffName());
        lqw.eq(StringUtils.isNotBlank(bo.getAuthor()), CommunityNews::getAuthor, bo.getAuthor());
        lqw.eq(StringUtils.isNotBlank(bo.getSource()), CommunityNews::getSource, bo.getSource());
        lqw.eq(StringUtils.isNotBlank(bo.getCoverImage()), CommunityNews::getCoverImage, bo.getCoverImage());
        lqw.eq(bo.getViewCount() != null, CommunityNews::getViewCount, bo.getViewCount());
        lqw.eq(StringUtils.isNotBlank(bo.getIsTop()), CommunityNews::getIsTop, bo.getIsTop());
        lqw.eq(StringUtils.isNotBlank(bo.getUserComment()), CommunityNews::getUserComment, bo.getUserComment());
        lqw.eq(StringUtils.isNotBlank(bo.getUserLikes()), CommunityNews::getUserLikes, bo.getUserLikes());
        lqw.eq(StringUtils.isNotBlank(bo.getUserStars()), CommunityNews::getUserStars, bo.getUserStars());
        return lqw;
    }

    /**
     * 新增社区资讯
     *
     * @param bo 社区资讯
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(CommunityNewsBo bo) {
        CommunityNews add = MapstructUtils.convert(bo, CommunityNews.class);
        validEntityBeforeSave(add);
        add.setUserId(LoginHelper.getUserId());
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setCommunityId(add.getCommunityId());
        }
        return flag;
    }

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

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

    /**
     * 校验并批量删除社区资讯信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }
    /**
     * 设置未读互动
     *
     * @return
     */
    @Override
    public void setCommentInteraction(CommentInteractionVo commentInteractionVo) {
        //把对应用户的未读互动存储到redis 还需要记录数量
        //目标用户id
        Long targetUserId = commentInteractionVo.getTargetUserId();
        String targetType = commentInteractionVo.getTargetType();
        String type = commentInteractionVo.getType();
        Long targetId = commentInteractionVo.getTargetId();
        /* 社区资讯ID 当是点赞回复的时候有值 */
        Long communityId = commentInteractionVo.getTargetId();
        //判断是否是点赞回复
        if (targetType.equals(FIV)) {
            communityId = commentInteractionVo.getCommunityId();
        }
        //-------------------获取设置用户的未读互动数量----------------
        String commentInteractionUserCountKey = COMMENT_INTERACTION_USER_COUNT + targetUserId;
        Object commentInteractionUserCount = RedisUtils.getCacheObject(commentInteractionUserCountKey);
        if (commentInteractionUserCount != null) {
            //判断是删除还是新增
            if (ONE.equals(type)) {
                RedisUtils.setCacheObject(commentInteractionUserCountKey, Integer.parseInt(commentInteractionUserCount.toString()) + 1);
            } else {
                RedisUtils.setCacheObject(commentInteractionUserCountKey, Math.max(Integer.parseInt(commentInteractionUserCount.toString()) - 1, 0));
            }
        } else {
            if (ONE.equals(type)) {
                RedisUtils.setCacheObject(commentInteractionUserCountKey, 1);
            }
        }
        //-------------------设置用户的未读互动数量结束----------------
        //-------------------设置用户的未读资讯的id和该资讯下一共有多少未读互动数量----------------
        //key=comment_interaction_community_user_count:{userId} hkey = {community_id} value = 资讯下有多少个未读的互动(点赞，收藏，回复)
        String commentInteractionCommunityUserCount = RedisUtils.getCacheMapValue(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + targetUserId, communityId.toString());
        //判断是删除还是新增
        if (ONE.equals(type)) {
            //新增
            if (StringUtils.isNotBlank(commentInteractionCommunityUserCount)) {
                RedisUtils.setCacheMapValue(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + targetUserId, communityId.toString(), String.valueOf(Integer.parseInt(commentInteractionCommunityUserCount) + 1));
            } else {
                RedisUtils.setCacheMapValue(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + targetUserId, communityId.toString(), ONE);
            }
        } else {
            //删除
            if (StringUtils.isNotBlank(commentInteractionCommunityUserCount)) {
                int commentInteractionCommunityUserCountResult = Integer.parseInt(commentInteractionCommunityUserCount) - 1;
                if (commentInteractionCommunityUserCountResult <= 0) {
                    RedisUtils.delCacheMapValue(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + targetUserId, communityId.toString());
                } else {
                    RedisUtils.setCacheMapValue(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + targetUserId, communityId.toString(), commentInteractionCommunityUserCountResult);
                }
            }
        }
        //-------------------设置用户的未读资讯的id和该资讯下一共有多少未读互动数量结束----------------
        //-------------------存储用户的未读资讯数据----------------
        String commentInteractionUserKey = COMMENT_INTERACTION_USER + targetUserId;
        Map<String, Object> commentInteractionUserMap = RedisUtils.getCacheMap(commentInteractionUserKey);
        //hKey={targetType:targetId}
        String hKey = targetType + ":" + targetId;
        if (ONE.equals(type)) {
            //新增/追加一条数据
            RedisUtils.setCacheMapValue(commentInteractionUserKey, hKey, commentInteractionVo);
        } else {
            //删除
            if (commentInteractionUserMap != null && commentInteractionUserMap.size() > 0) {
                //删除一条数据
                RedisUtils.delCacheMapValue(commentInteractionUserKey, hKey);
            }
        }
        //-------------------存储用户的未读资讯数据结束----------------
    }

    /**
     * 获取未读互动列表
     */
    @Override
    public R<Map<String, Object>> getCommentInteraction(CommentInteractionVo commentInteractionVo) {
        Long userId = LoginHelper.getUserId();
        Map<String, Object> resultMap = new HashMap<>();
        String commentInteractionUserCountKey = COMMENT_INTERACTION_USER_COUNT + userId;
        Object commentInteractionUserCount = RedisUtils.getCacheObject(commentInteractionUserCountKey);
        int commentInteractionUserCountInt = 0;
        if (ObjectUtils.isNotEmpty(commentInteractionUserCount)) {
            commentInteractionUserCountInt = Integer.parseInt(commentInteractionUserCount.toString());
        }
        resultMap.put("total", commentInteractionUserCountInt);
        //-------------------存储用户的未读资讯数据----------------
        String commentInteractionUserKey = COMMENT_INTERACTION_USER + userId;
        Map<String, Object> commentInteractionUserMap = RedisUtils.getCacheMap(commentInteractionUserKey);
        List<Object> resultList = new ArrayList<>();
        if (commentInteractionUserMap != null && commentInteractionUserMap.size() > 0) {
            resultList.addAll(commentInteractionUserMap.values());
        }
        resultMap.put("list", resultList);
        //清空未读key
        RedisUtils.deleteObject(commentInteractionUserCountKey);
        RedisUtils.deleteObject(commentInteractionUserKey);
        RedisUtils.deleteObject(COMMENT_INTERACTION_COMMUNITY_USER_COUNT + userId);
        return R.ok(resultMap);
    }

    /**
     * 获取未读互动数量
     */
    @Override
    public R<Integer> getCommentInteractionCount(CommentInteractionVo commentInteractionVo) {
        Long userId = LoginHelper.getUserId();
        String commentInteractionUserCountKey = COMMENT_INTERACTION_USER_COUNT + userId;
        Object commentInteractionUserCount = RedisUtils.getCacheObject(commentInteractionUserCountKey);
        int commentInteractionUserCountInt = 0;
        if (ObjectUtils.isNotEmpty(commentInteractionUserCount)) {
            commentInteractionUserCountInt = Integer.parseInt(commentInteractionUserCount.toString());
        }
        return R.ok(commentInteractionUserCountInt);
    }
}
