package com.yida.data.school.atlas.mq;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import com.yida.data.common.core.entity.apply.enums.DelFlagType;
import com.yida.data.common.core.entity.atlas.CoreAtlasManagement;
import com.yida.data.common.core.entity.atlas.CoreAtlasManagementDetails;
import com.yida.data.common.core.entity.atlas.CoreAtlasManagementDetailsLike;
import com.yida.data.common.core.enums.AtlasManagementRedisEnum;
import com.yida.data.rabbit.constant.RabbitConstant;
import com.yida.data.school.atlas.mapper.CoreAtlasManagementDetailsLikeMapper;
import com.yida.data.school.atlas.service.CoreAtlasManagementDetailsService;
import com.yida.data.school.atlas.service.CoreAtlasManagementService;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.Objects;

import cc.mrbird.febs.common.redis.service.RedisService;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 图集mq接收类
 *
 * @author ZYJ
 * @date 2021/9/7
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class AtlasLikeRabbitReceiver {

    private final RedisService redisService;

    private final CoreAtlasManagementService coreAtlasManagementService;

    private final CoreAtlasManagementDetailsService coreAtlasManagementDetailsService;

    private final CoreAtlasManagementDetailsLikeMapper coreAtlasManagementDetailsLikeMapper;

    /**
     * 图集mq点赞和取消赞接收处理方法
     *
     * @param coreAtlasManagementDetailsLike 接收的消息
     * @param channel                        channel频道
     * @param message                        mq的Message对象
     * @author ZYJ
     * @date 2021/9/7 13:47
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(RabbitConstant.ATLAS_LIKE_QUEUE),
            exchange = @Exchange(RabbitConstant.ATLAS_LIKE_EXCHANGE)
    ))
    @Transactional(rollbackFor = Exception.class)
    public void atlasLikeReceiveMessage(CoreAtlasManagementDetailsLike coreAtlasManagementDetailsLike,
                                        Channel channel, Message message)
            throws IOException {
        log.info("接受到图集点赞相关消息: {}", JSONUtil.toJsonStr(coreAtlasManagementDetailsLike));
        log.info("开始处理消息: {}", coreAtlasManagementDetailsLike.getMark());
        CoreAtlasManagementDetailsLike byMark =
                this.coreAtlasManagementDetailsLikeMapper.selectOne(
                        new LambdaQueryWrapper<>(new CoreAtlasManagementDetailsLike())
                                .eq(CoreAtlasManagementDetailsLike::getCoreAtlasManagementDetailsId, coreAtlasManagementDetailsLike.getCoreAtlasManagementDetailsId())
                                .eq(CoreAtlasManagementDetailsLike::getUserId, coreAtlasManagementDetailsLike.getUserId()));
        // 数据库没有点赞记录，并传过来的对象delFlag参数为0，才表示是新增操作
        if (Objects.isNull(byMark) && DelFlagType.NORMAL_TYPE.getValue().equals(coreAtlasManagementDetailsLike.getDelFlag())) {
            // 新增点赞记录
            coreAtlasManagementDetailsLikeMapper.insert(coreAtlasManagementDetailsLike);

            // 修改图集照片或视频的点赞数+1
            CoreAtlasManagementDetails coreAtlasManagementDetails =
                    this.coreAtlasManagementDetailsService.getById(coreAtlasManagementDetailsLike.getCoreAtlasManagementDetailsId());
            if (Objects.isNull(coreAtlasManagementDetails)) {
                log.error("点赞图集作品信息为空, 不做任何操作");
                // 确认收到消息，只确认当前消费者的一个消息收到
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }
            coreAtlasManagementDetails.setLikeNum(coreAtlasManagementDetails.getLikeNum() + 1);
            this.coreAtlasManagementDetailsService.updateById(coreAtlasManagementDetails);
            // 修改图集的点赞数+1
            CoreAtlasManagement coreAtlasManagement = this.coreAtlasManagementService.
                    getById(coreAtlasManagementDetails.getCoreAtlasManagementId());
            if (Objects.isNull(coreAtlasManagement)) {
                log.error("点赞图集信息为空, 不做任何操作");
                // 确认收到消息，只确认当前消费者的一个消息收到
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }
            coreAtlasManagement.setLikeNum(coreAtlasManagement.getLikeNum() + 1);
            this.coreAtlasManagementService.updateById(coreAtlasManagement);
            // 更新redis中的数据
            redisService.hset(AtlasManagementRedisEnum.ATLAS_MANAGEMENT_DETAILS_LIKE_DETAILS.
                            getValue() + ":" + coreAtlasManagementDetailsLike.getCoreAtlasManagementDetailsId(),
                    String.valueOf(coreAtlasManagementDetailsLike.getUserId()), coreAtlasManagementDetailsLike);
            // 确认收到消息，只确认当前消费者的一个消息收到
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            log.info("点赞消息处理完成: {}", coreAtlasManagementDetailsLike.getMark());
        } else {
            // 取消点赞记录
            // 需要防止点赞记录还未保存，取消点赞已经先处理，需要重新放入队列
            int i = this.coreAtlasManagementDetailsLikeMapper.deleteById(coreAtlasManagementDetailsLike.getId());
            if (i == 0) {
                if (Boolean.TRUE.equals(message.getMessageProperties().getRedelivered())) {
                    log.info("当前数据: {}已重新放入队列过，不再重新放入队列！", coreAtlasManagementDetailsLike.getMark());
                    // 拒绝消息，并且不再重新进入队列
                    //public void basicReject(long deliveryTag, boolean requeue)
                    channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
                } else {
                    log.info("重新放入队列的数据: {}", coreAtlasManagementDetailsLike.getMark());
                    //设置消息重新回到队列处理
                    // requeue表示是否重新回到队列，true重新入队
                    channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
                }
            } else {
                // 修改图集照片或视频的点赞数-1
                CoreAtlasManagementDetails coreAtlasManagementDetails =
                        this.coreAtlasManagementDetailsService.getById(coreAtlasManagementDetailsLike.getCoreAtlasManagementDetailsId());
                if (Objects.isNull(coreAtlasManagementDetails)) {
                    log.error("取消赞图集作品信息为空, 不做任何操作");
                    // 确认收到消息，只确认当前消费者的一个消息收到
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                    return;
                }
                coreAtlasManagementDetails.setLikeNum(coreAtlasManagementDetails.getLikeNum() - 1);
                this.coreAtlasManagementDetailsService.updateById(coreAtlasManagementDetails);
                // 修改图集的点赞数-1
                CoreAtlasManagement coreAtlasManagement = this.coreAtlasManagementService.
                        getById(coreAtlasManagementDetails.getCoreAtlasManagementId());
                if (Objects.isNull(coreAtlasManagement)) {
                    log.error("取消赞图集信息为空, 不做任何操作");
                    // 确认收到消息，只确认当前消费者的一个消息收到
                    channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                    return;
                }
                coreAtlasManagement.setLikeNum(coreAtlasManagement.getLikeNum() - 1);
                this.coreAtlasManagementService.updateById(coreAtlasManagement);
                redisService.hdel(AtlasManagementRedisEnum.ATLAS_MANAGEMENT_DETAILS_LIKE_DETAILS.
                                getValue() + ":" + coreAtlasManagementDetailsLike.getCoreAtlasManagementDetailsId(),
                        String.valueOf(coreAtlasManagementDetailsLike.getUserId()));
                // 确认收到消息，只确认当前消费者的一个消息收到
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                log.info("取消赞消息处理完成: {}" + coreAtlasManagementDetailsLike.getMark());
            }
        }
    }
}
