package com.m2pool.lease.config;


import org.springframework.amqp.core.*;
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.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

import static com.m2pool.lease.constant.RabbitmqConstant.*;

@Configuration
public class RabbitMQConfig {

    @Bean
    public MessageConverter jackson2JsonMessageConverter() {
        //自动生成消息唯一id
        //jackson2JsonMessageConverter.setCreateMessageIds(true);
        return new JacksonMessageConverter();
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        rabbitTemplate.setMessageConverter(jackson2JsonMessageConverter());

        //// 自定义 MessagePostProcessor 来设置 content-type
        //rabbitTemplate.setBeforePublishPostProcessors(new MessagePostProcessor() {
        //    @Override
        //    public Message postProcessMessage(Message message) {
        //        // 设置 content-type 为 application/json
        //        message.getMessageProperties().setContentType("application/json");
        //        return message;
        //    }
        //});
        // 开启发布确认模式
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                System.out.println("消息发送成功，correlationData: " + correlationData);
            } else {
                System.out.println("消息发送失败，原因: " + cause);
                // 这里可以添加将失败消息存储到数据库的逻辑
            }
        });
        rabbitTemplate.setMandatory(true);
        return rabbitTemplate;
    }


    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        //消费者序列化
        factory.setMessageConverter(jackson2JsonMessageConverter());
        factory.setConcurrentConsumers(3); // 设置初始消费者数量
        factory.setMaxConcurrentConsumers(5); // 设置最大消费者数量
        return factory;
    }


    /**
     * 矿池代理队列
     * @return
     */
    @Bean
    public Queue poolProxyQueue() {
        // durable 设置为 true 表示队列持久化
        return new Queue(POOL_PROXY_QUEUE_NAME, true);
    }

   //----------------定义订单延迟队列------------------------

    /**
     * 死信 交换机
     * @return
     */
   @Bean
   public DirectExchange deadLetterExchange() {
       return new DirectExchange(DEAD_LETTER_EXCHANGE_NAME);
   }

   /**
     * 死信 队列
     * @return
     */
    @Bean
    public Queue deadLetterQueue() {
        return new Queue(DEAD_LETTER_QUEUE_NAME, true);
    }

    /**
     * 死信 队列绑定死信交换机
     * @return
     */
    @Bean
    public Binding deadLetterBinding() {
        return BindingBuilder.bind(deadLetterQueue()).to(deadLetterExchange()).with(DEAD_LETTER_ROUTING_KEY);
    }

    /**
     * 订单超时消息 交换机
     * @return
     */
    @Bean
    public DirectExchange orderOvertimeExchange() {
        return new DirectExchange(ORDER_OVERTIME_EXCHANGE_NAME);
    }

    /**
     * 订单超时消息 队列 （死信交换机达成延迟队列功能）
     * @return
     */
    @Bean
    public Queue orderOvertimeQueue() {
        Map<String, Object> args = new HashMap<>();
        // 设置死信交换机
        args.put("x-dead-letter-exchange", DEAD_LETTER_EXCHANGE_NAME);
        // 设置死信路由键
        args.put("x-dead-letter-routing-key", DEAD_LETTER_ROUTING_KEY);
        // 设置队列中消息的 TTL（单位：毫秒）
        args.put("x-message-ttl", 900000);
        return new Queue(ORDER_OVERTIME_QUEUE_NAME, true, false, false, args);
    }

    /**
     * 订单超时消息 队列绑定普通交换机
     * @return
     */
    @Bean
    public Binding orderOvertimeBinding() {
        return BindingBuilder.bind(orderOvertimeQueue()).to(orderOvertimeExchange()).with(ORDER_OVERTIME_ROUTING_KEY);
    }

    //----------------定义订单延迟队列------------------------

    //----------------定义支付相关队列------------------------
    /**
     * 声明 Topic 类型的交换机
     */
    @Bean
    public DirectExchange payExchange() {
        return new DirectExchange(PAY_EXCHANGE);
    }

    // 支付相关队列声明
    /**
     * 声明支付消息队列
     */
    @Bean
    public Queue payAutoQueue() {
        return new Queue(PAY_AUTO_QUEUE, true);
    }

    /**
     * 声明支付返回消息队列
     */
    @Bean
    public Queue payAutoReturnQueue() {
        return new Queue(PAY_AUTO_RETURN_QUEUE, true);
    }

    // 余额充值相关队列声明
    /**
     * 声明余额充值消息队列
     */
    @Bean
    public Queue payRechargeQueue() {
        return new Queue(PAY_RECHARGE_QUEUE, true);
    }

    /**
     * 声明余额充值返回信息队列
     */
    @Bean
    public Queue payRechargeReturnQueue() {
        return new Queue(PAY_RECHARGE_RETURN_QUEUE, true);
    }

    // 余额提现相关队列声明
    /**
     * 声明余额提现消息队列
     */
    @Bean
    public Queue payWithdrawQueue() {
        return new Queue(PAY_WITHDRAW_QUEUE, true);
    }

    /**
     * 声明余额提现返回信息队列
     */
    @Bean
    public Queue payWithdrawReturnQueue() {
        return new Queue(PAY_WITHDRAW_RETURN_QUEUE, true);
    }

    // 支付相关绑定
    /**
     * 将支付消息队列绑定到交换机
     */
    @Bean
    public Binding payAutoBinding() {
        return BindingBuilder.bind(payAutoQueue()).to(payExchange()).with(PAY_AUTO_ROUTING_KEY);
    }

    /**
     * 将支付返回消息队列绑定到交换机
     */
    @Bean
    public Binding payAutoReturnBinding() {
        return BindingBuilder.bind(payAutoReturnQueue()).to(payExchange()).with(PAY_AUTO_RETURN_ROUTING_KEY);
    }


    // 余额充值相关绑定
    /**
     * 将余额充值消息队列绑定到交换机
     */
    @Bean
    public Binding payRechargeBinding() {
        return BindingBuilder.bind(payRechargeQueue()).to(payExchange()).with(PAY_RECHARGE_ROUTING_KEY);
    }

    /**
     * 将余额充值返回信息队列绑定到交换机
     */
    @Bean
    public Binding payRechargeReturnBinding() {
        return BindingBuilder.bind(payRechargeReturnQueue()).to(payExchange()).with(PAY_RECHARGE_RETURN_ROUTING_KEY);
    }

    // 余额提现相关绑定
    /**
     * 将余额提现消息队列绑定到交换机
     */
    @Bean
    public Binding payWithdrawBinding() {
        return BindingBuilder.bind(payWithdrawQueue()).to(payExchange()).with(PAY_WITHDRAW_ROUTING_KEY);
    }

    /**
     * 将余额提现返回信息队列绑定到交换机
     */
    @Bean
    public Binding payWithdrawReturnBinding() {
        return BindingBuilder.bind(payWithdrawReturnQueue()).to(payExchange()).with(PAY_WITHDRAW_RETURN_ROUTING_KEY);
    }




    //钱包删除 提现相关绑定


    @Bean
    public Queue deleteWalletReturnQueue() {
        return new Queue(DELETE_WALLET_RETURN_QUEUE, true);
    }

    @Bean
    public Queue deleteWalletQueue() {
        return new Queue(DELETE_WALLET_QUEUE, true);
    }

    /**
     * 将钱包删除消息队列绑定到交换机
     */
    @Bean
    public Binding deleteWalletBinding() {
        return BindingBuilder.bind(deleteWalletQueue()).to(payExchange()).with(DELETE_WALLET_ROUTING_KEY);
    }

    /**
     * 将钱包删除返回信息队列绑定到交换机
     */
    @Bean
    public Binding deleteWalletReturnBinding() {
        return BindingBuilder.bind(deleteWalletReturnQueue()).to(payExchange()).with(DELETE_WALLET_RETURN_ROUTING_KEY);
    }


    //----------------定义支付相关队列------------------------
}
