package com.mortals.xhx.base.framework.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mortals.xhx.common.key.QueueKey;
import com.mortals.xhx.module.access.model.AccessLogEntity;
import com.mortals.xhx.module.biz.model.BizLogEntity;
import com.mortals.xhx.module.error.model.ErrorLogEntity;
import com.mortals.xhx.module.operate.model.OperateLogEntity;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.AsyncRabbitTemplate;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.*;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class RabbitConfig {
    public Integer messageTtl = 86400000;
    public Map<String, Object> args = new HashMap<>();

    // 创建 Queue
    @Bean
    public Queue accessLogQueue() {
        args.put("x-message-ttl", messageTtl);
        return new Queue(QueueKey.ACCESS_LOG_QUEUE, // Queue 名字
                true, // durable: 是否持久化
                false, // exclusive: 是否排它
                false,
                args); // autoDelete: 是否自动删除
    }

    @Bean
    public Queue bizLogQueue() {
        args.put("x-message-ttl", messageTtl);
        return new Queue(QueueKey.BIZ_LOG_QUEUE, // Queue 名字
                true, // durable: 是否持久化
                false, // exclusive: 是否排它
                false, args); // autoDelete: 是否自动删除
    }


    @Bean
    public Queue errorLogQueue() {
        return new Queue(QueueKey.ERROR_LOG_QUEUE, // Queue 名字
                true, // durable: 是否持久化
                false, // exclusive: 是否排它
                false, args); // autoDelete: 是否自动删除
    }

    @Bean
    public Queue operationLogQueue() {
        return new Queue(QueueKey.OPERATION_LOG_QUEUE, // Queue 名字
                true, // durable: 是否持久化
                false, // exclusive: 是否排它
                false, args); // autoDelete: 是否自动删除
    }


    // 创建 Direct Exchange
    @Bean
    public DirectExchange exchange() {
        return new DirectExchange(QueueKey.EXCHANGE,
                true,  // durable: 是否持久化
                false);  // exclusive: 是否排它
    }

    // 创建 Binding
    @Bean
    public Binding accessBinding() {
        return BindingBuilder.bind(accessLogQueue()).to(exchange()).with(QueueKey.ACCESS_LOG_QUEUE);
    }

    @Bean
    public Binding bizBinding() {
        return BindingBuilder.bind(bizLogQueue()).to(exchange()).with(QueueKey.BIZ_LOG_QUEUE);
    }

    @Bean
    public Binding errorBinding() {
        return BindingBuilder.bind(errorLogQueue()).to(exchange()).with(QueueKey.ERROR_LOG_QUEUE);
    }

    @Bean
    public Binding operBinding() {
        return BindingBuilder.bind(operationLogQueue()).to(exchange()).with(QueueKey.OPERATION_LOG_QUEUE);
    }

    @Bean(name = "consumerBatchContainerFactory")
    public SimpleRabbitListenerContainerFactory consumerBatchContainerFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
        // 创建 SimpleRabbitListenerContainerFactory 对象
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setAfterReceivePostProcessors(m -> {
                    m.getMessageProperties().setContentType("application/json");
                  //  m.getMessageProperties().setHeader("__TypeId__","java.lang.String");
                    return m;
                });
        configurer.configure(factory, connectionFactory);
        // 额外添加批量消费的属性
        factory.setBatchListener(true);
        factory.setBatchSize(10);
        factory.setReceiveTimeout(5 * 1000L);
        factory.setConsumerBatchEnabled(true);
        return factory;
    }

    @Bean(name = "consumerContainerFactory")
    public SimpleRabbitListenerContainerFactory consumerContainerFactory(
            SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
        // 创建 SimpleRabbitListenerContainerFactory 对象
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        configurer.configure(factory, connectionFactory);
        return factory;
    }

    //修改系列和与反序列化转换器
    @Bean
    public MessageConverter messageConverter() {
        //return null;
        ObjectMapper objectMapper = new ObjectMapper();
        //设置转换的实体类可见性[避免属性访问权问题所导致的缺少字段]
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        Jackson2JsonMessageConverter jackson2JsonMessageConverter = new Jackson2JsonMessageConverter();
        //因为实体类的包名不同的问题；重写 classMapper映射，不然接收消息异常报错
        jackson2JsonMessageConverter.setClassMapper(new ClassMapper() {
            @Override
            public void fromClass(Class<?> aClass, MessageProperties messageProperties) {
                //反序列化指定类路径
/*                if (messageProperties.getConsumerQueue().equalsIgnoreCase(QueueKey.ACCESS_LOG_QUEUE)) {
                    messageProperties.setHeader("__TypeId__", "java.lang.String");
                }
               else if(messageProperties.getConsumerQueue().equalsIgnoreCase(QueueKey.BIZ_LOG_QUEUE)){
                    messageProperties.setHeader("__TypeId__", "com.mortals.xhx.module.biz.model.BizLogEntity");
                }else if(messageProperties.getConsumerQueue().equalsIgnoreCase(QueueKey.ERROR_LOG_QUEUE)){
                    messageProperties.setHeader("__TypeId__", "com.mortals.xhx.module.error.model.ErrorLogEntity");
                }else if(messageProperties.getConsumerQueue().equalsIgnoreCase(QueueKey.OPERATION_LOG_QUEUE)){
                    messageProperties.setHeader("__TypeId__", "com.mortals.xhx.module.operate.model.OperateLogEntity");
                }*/
            }

            @Override
            public Class<?> toClass(MessageProperties properties) {
                if (properties.getConsumerQueue().equalsIgnoreCase(QueueKey.ACCESS_LOG_QUEUE)) {
                   // return String.class;
                    return AccessLogEntity.class;
                }else if (properties.getConsumerQueue().equalsIgnoreCase(QueueKey.BIZ_LOG_QUEUE)) {
                    return BizLogEntity.class;
                }else if (properties.getConsumerQueue().equalsIgnoreCase(QueueKey.ERROR_LOG_QUEUE)) {
                    return ErrorLogEntity.class;
                }else if (properties.getConsumerQueue().equalsIgnoreCase(QueueKey.OPERATION_LOG_QUEUE)) {
                    return OperateLogEntity.class;
                }
                return String.class;
            }
        });
        return jackson2JsonMessageConverter;
    }

}
