package net.yyc.common.rabbitmq.core;

import net.yyc.common.rabbitmq.listenter.MqListener;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Slf4j
public class BaseRabbiMqHandler<T> {

	@Autowired
	private StringRedisTemplate redisTemplate;

	private static final long DEF_REPORT_TTL = 7L * 24 * 60 * 60 * 1000;

	public void onMessageAck(T t, Long deliveryTag, Channel channel, MqListener mqListener) {
		log.warn("==================== delivery-tag：[{}], ack 开始 ==========================", deliveryTag);
		Map<String, String> res = null;
		try {
			log.warn("开始执行操作");
			res = mqListener.handler(t, channel);
		} catch (Exception e) {
			log.info("接收消息失败,但不放回队列");
			e.printStackTrace();
		} finally {
			// 插入redis
			setIntoRedis(res.get("key"), res.get("res"));

			log.warn("开始ack操作");
			try {
				channel.basicAck(deliveryTag, false);
			} catch (IOException e) {
				e.printStackTrace();
			}

			log.warn("==================== delivery-tag：[{}], ack 结束 ==========================", deliveryTag);
		}

	}

    public void onMessage(T t, Long deliveryTag, Channel channel, MqListener mqListener) {
        try {
            mqListener.handler(t, channel);
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            log.info("接收消息失败,重新放回队列");
            try {
                /**
                 * deliveryTag:该消息的index
                 * multiple：是否批量.true:将一次性拒绝所有小于deliveryTag的消息。
                 * requeue：被拒绝的是否重新入队列
                 */
                channel.basicNack(deliveryTag, false, true);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

    }

	private void setIntoRedis(final String key, final String res) {

		log.warn("-----------------------------循环插入redis开始--------------------------------------");

		for (int i = 0; ; i++) {
			log.info("-----------redis写入中，第 [{}] 次-----------", i);
			redisTemplate.opsForValue().set(key, res, DEF_REPORT_TTL, TimeUnit.MILLISECONDS);
			try {
				Thread.sleep(50);
			} catch (Exception e) {
				continue;
			}

			String s = redisTemplate.opsForValue().get(key);

			if (res.equals(s)) {
				log.info("r-key：{}", key);
				log.info("r-res：{}", res);
				log.info("r-content ：{}", s);
				log.info("-----------redis成功-----------");
				break;
			}
		}

		log.warn("-----------------------------循环插入redis开始--------------------------------------");
	}
}
