package com.sino.mci.mq.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

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

/**
 * 消息发送 RabbitMQ 配置。
 * <p>
 * 重试机制：主队列设置死信交换机（DLX）和死信路由键；发送失败需要延迟重试时，
 * 将消息发送到 DLX 并设置 per-message TTL，到期后由 DLX 重新路由回主队列消费。
 */
@Configuration
public class MqConfig {

    public static final String SEND_EXCHANGE = "mci.send.exchange";
    public static final String SEND_QUEUE = "mci.send.queue";
    public static final String SEND_ROUTING_KEY = "mci.send";

    public static final String SEND_DLX_EXCHANGE = "mci.send.dlx.exchange";
    public static final String SEND_DLX_ROUTING_KEY = "mci.send.retry";

    public static final String CALLBACK_EXCHANGE = "mci.callback.exchange";
    public static final String CALLBACK_QUEUE = "mci.callback.queue";
    public static final String CALLBACK_ROUTING_KEY = "mci.callback";

    public static final String INBOUND_EXCHANGE = "mci.inbound.exchange";
    public static final String INBOUND_QUEUE = "mci.inbound.queue";
    public static final String INBOUND_ROUTING_KEY = "mci.inbound";

    public static final String INBOUND_FLOW_EXCHANGE = "mci.inbound.flow.exchange";
    public static final String INBOUND_FLOW_QUEUE = "mci.inbound.flow.queue";
    public static final String INBOUND_FLOW_ROUTING_KEY = "mci.inbound.flow";

    @Bean
    public Queue sendQueue() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-dead-letter-exchange", SEND_DLX_EXCHANGE);
        args.put("x-dead-letter-routing-key", SEND_DLX_ROUTING_KEY);
        return new Queue(SEND_QUEUE, true, false, false, args);
    }

    @Bean
    public DirectExchange sendExchange() {
        return new DirectExchange(SEND_EXCHANGE, true, false);
    }

    @Bean
    public Binding sendBinding(Queue sendQueue, DirectExchange sendExchange) {
        return BindingBuilder.bind(sendQueue).to(sendExchange).with(SEND_ROUTING_KEY);
    }

    @Bean
    public DirectExchange sendDlxExchange() {
        return new DirectExchange(SEND_DLX_EXCHANGE, true, false);
    }

    @Bean
    public Binding sendDlxBinding(Queue sendQueue, DirectExchange sendDlxExchange) {
        return BindingBuilder.bind(sendQueue).to(sendDlxExchange).with(SEND_DLX_ROUTING_KEY);
    }

    @Bean
    public Queue callbackQueue() {
        return new Queue(CALLBACK_QUEUE, true);
    }

    @Bean
    public DirectExchange callbackExchange() {
        return new DirectExchange(CALLBACK_EXCHANGE, true, false);
    }

    @Bean
    public Binding callbackBinding(Queue callbackQueue, DirectExchange callbackExchange) {
        return BindingBuilder.bind(callbackQueue).to(callbackExchange).with(CALLBACK_ROUTING_KEY);
    }

    @Bean
    public Queue inboundQueue() {
        return new Queue(INBOUND_QUEUE, true);
    }

    @Bean
    public DirectExchange inboundExchange() {
        return new DirectExchange(INBOUND_EXCHANGE, true, false);
    }

    @Bean
    public Binding inboundBinding(Queue inboundQueue, DirectExchange inboundExchange) {
        return BindingBuilder.bind(inboundQueue).to(inboundExchange).with(INBOUND_ROUTING_KEY);
    }

    @Bean
    public Queue inboundFlowQueue() {
        return new Queue(INBOUND_FLOW_QUEUE, true);
    }

    @Bean
    public DirectExchange inboundFlowExchange() {
        return new DirectExchange(INBOUND_FLOW_EXCHANGE, true, false);
    }

    @Bean
    public Binding inboundFlowBinding(Queue inboundFlowQueue, DirectExchange inboundFlowExchange) {
        return BindingBuilder.bind(inboundFlowQueue).to(inboundFlowExchange).with(INBOUND_FLOW_ROUTING_KEY);
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
