package com.kxs.common.mq.config;

import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import com.kxs.common.core.constant.CommonConstants;
import com.kxs.common.core.util.SpringContextHolder;
import com.kxs.common.mq.enums.MQSendTypeEnum;
import com.kxs.common.mq.model.AbstractMQ;
import jakarta.annotation.PostConstruct;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.Set;


/**
 * rabbitmq队列配置
 *
 * @author 没秃顶的码农
 * @date 2024-04-24
 */
@Component
public class RabbitConfiguration {

	@Autowired
	private RabbitMQBeanProcessor rabbitMqBeanProcessor;

	public static final String BIND_PREFIX = "BIND_";

	/**
	 * 普通交换机
	 */
	public static final String EXCHANGE_TOPIC_RANCH ="kxs_direct_ranch";

	/**
	 * 死信交换机
	 */
	public static final String EXCHANGE_DEAD_RANCH ="kxs_dead_ranch";

	/**
	 * 广播交换机
	 */
	public static final String EXCHANGE_FANOUT_RANCH ="kxs_fanout_ranch";

	/**
	 * 延时交换机
	 */
	public static final String EXCHANGE_DELAY_RANCH="kxs_delay_ranch";

	/** 注入延迟交换机Bean **/
	@Autowired
	@Qualifier(EXCHANGE_TOPIC_RANCH)
	private DirectExchange directExchange;

	/** 注入延迟交换机Bean **/
	@Autowired
	@Qualifier(EXCHANGE_FANOUT_RANCH)
	private FanoutExchange fanoutExchange;

	/** 注入延迟交换机Bean **/
	@Autowired
	@Qualifier(EXCHANGE_DELAY_RANCH)
	private CustomExchange delayedExchange;

	/** 死信交换机 **/
	@Autowired
	@Qualifier(EXCHANGE_DEAD_RANCH)
	private DirectExchange deadExchange;


	@PostConstruct
	public void init(){

		// 获取到所有的MQ定义
		Set<Class<?>> set = ClassUtil.scanPackageBySuper(CommonConstants.PACKAGE_NAME, AbstractMQ.class);

		for (Class<?> aClass : set) {
			// 实例化
			AbstractMQ amq = (AbstractMQ) ReflectUtil.newInstance(aClass);

			// 注册正常Queue 需判断是否有死信队列
			if(amq.getDeadQueueName() != null){
				rabbitMqBeanProcessor.beanDefinitionRegistry.registerBeanDefinition(amq.getQueueName(),
						BeanDefinitionBuilder.genericBeanDefinition(Queue.class, () ->
								QueueBuilder.durable(amq.getQueueName()).deadLetterExchange(EXCHANGE_DEAD_RANCH)
										.deadLetterRoutingKey(amq.getDeadQueueName()).build()
						).getBeanDefinition());
				//  注册死信队列
				rabbitMqBeanProcessor.beanDefinitionRegistry.registerBeanDefinition(amq.getDeadQueueName(),
						BeanDefinitionBuilder.rootBeanDefinition(Queue.class).addConstructorArgValue(amq.getDeadQueueName()).getBeanDefinition());

				//死信队列绑定死信交换机
				rabbitMqBeanProcessor.beanDefinitionRegistry.registerBeanDefinition(BIND_PREFIX + amq.getDeadQueueName(),
						BeanDefinitionBuilder.genericBeanDefinition(Binding.class, () ->
								BindingBuilder.bind(SpringContextHolder.getBean( amq.getDeadQueueName(), Queue.class))
										.to(deadExchange).with(amq.getDeadQueueName())
						).getBeanDefinition()
				);
			}else{
				rabbitMqBeanProcessor.beanDefinitionRegistry.registerBeanDefinition(amq.getQueueName(),
						BeanDefinitionBuilder.genericBeanDefinition(Queue.class, () ->
								QueueBuilder.durable(amq.getQueueName()).build()
						).getBeanDefinition());
			}

			//普通队列
			if(amq.getMqType() == MQSendTypeEnum.QUEUE){
				rabbitMqBeanProcessor.beanDefinitionRegistry.registerBeanDefinition(BIND_PREFIX + amq.getQueueName(),
						BeanDefinitionBuilder.genericBeanDefinition(Binding.class, () ->
								BindingBuilder.bind(SpringContextHolder.getBean(amq.getQueueName(), Queue.class))
										.to(directExchange).with(amq.getQueueName())
						).getBeanDefinition()
				);
			}
			// 广播模式
			if(amq.getMqType() == MQSendTypeEnum.FANOUT){
				rabbitMqBeanProcessor.beanDefinitionRegistry.registerBeanDefinition(BIND_PREFIX + amq.getQueueName(),
						BeanDefinitionBuilder.genericBeanDefinition(Binding.class, () ->
								BindingBuilder.bind(Objects.requireNonNull(SpringContextHolder.getBean(amq.getQueueName(), Queue.class)))
										.to(fanoutExchange)
						).getBeanDefinition()
				);
			}
			//延迟队列
			if(amq.getMqType()== MQSendTypeEnum.DELAY){
				// 延迟交换机与Queue进行绑定， 绑定Bean名称 = mqName_DelayedBind
				rabbitMqBeanProcessor.beanDefinitionRegistry.registerBeanDefinition(BIND_PREFIX + amq.getQueueName() + "_delayed",
						BeanDefinitionBuilder.genericBeanDefinition(Binding.class, () ->
								BindingBuilder.bind(Objects.requireNonNull(SpringContextHolder.getBean(amq.getQueueName(), Queue.class)))
										.to(delayedExchange).with(amq.getQueueName()).noargs()

						).getBeanDefinition()
				);
			}

		}
	}

}