package com.prolog.upcloud.base.wh.operate.service.impl.mq;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.prolog.upcloud.base.wh.operate.dao.EisLogMapper;
import com.prolog.upcloud.base.wh.operate.model.EisLog;
import com.prolog.upcloud.base.wh.operate.mq.MqConsumer;
import com.prolog.upcloud.base.wh.operate.service.InterfacePlatform;
import com.prolog.upcloud.base.wh.operate.utils.TransactionHelper;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;

import static com.prolog.constant.EisInterfaceConstant.*;
import static com.prolog.constant.RabbitMqConstant.*;
import static com.prolog.cs.biz.outbound.model.tms.TmsConstant.*;

@Component
@Slf4j
public class MqConsumerImpl implements MqConsumer {

    @Resource
    private EisLogMapper eisLogMapper;
    @Resource
    private InterfacePlatform ip;

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2EIS_INBOUND_REQUEST_EXCHANGE), key = WMS2EIS_INBOUND_REQUEST_ROUTING_KEY, value = @Queue(WMS2EIS_INBOUND_REQUEST_QUEUE)))
    public void inBoundRequest(Message message, Channel channel) {
        requestEis(message, channel, IN_BOUND_REQUEST);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2EIS_CONTAINER_TAILGATING_REQUEST_EXCHANGE), key = WMS2EIS_CONTAINER_TAILGATING_REQUEST_ROUTING_KEY, value = @Queue(WMS2EIS_CONTAINER_TAILGATING_REQUEST_QUEUE)))
    public void containerTailgatingRequest(Message message, Channel channel) {
        requestEis(message, channel, CONTAINER_TAILGATING_REQUEST);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2EIS_OUTBOUND_REQUEST_EXCHANGE), key = WMS2EIS_OUTBOUND_REQUEST_ROUTING_KEY, value = @Queue(WMS2EIS_OUTBOUND_REQUEST_QUEUE)))
    public void outBoundRequest(Message message, Channel channel) {
        requestEis(message, channel, OUT_BOUND_REQUEST);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2EIS_UPGRADE_PRIORITY_EXCHANGE), key = WMS2EIS_UPGRADE_PRIORITY_ROUTING_KEY, value = @Queue(WMS2EIS_UPGRADE_PRIORITY_QUEUE)))
    public void upgradePriority(Message message, Channel channel) {
        requestEis(message, channel, UPGRADE_PRIORITY);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2EIS_CANCEL_TASKS_EXCHANGE), key = WMS2EIS_CANCEL_TASKS_ROUTING_KEY, value = @Queue(WMS2EIS_CANCEL_TASKS_QUEUE)))
    public void cancelTasks(Message message, Channel channel) {
        requestEis(message, channel, CANCEL_TASKS);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2EIS_OPERATION_COMPLETE_EXCHANGE), key = WMS2EIS_OPERATION_COMPLETE_ROUTING_KEY, value = @Queue(WMS2EIS_OPERATION_COMPLETE_QUEUE)))
    public void operationComplete(Message message, Channel channel) {
        requestEis(message, channel, OPERATION_COMPLETE);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2EIS_SAVE_LOG_EXCHANGE), key = WMS2EIS_SAVE_LOG_ROUTING_KEY, value = @Queue(WMS2EIS_SAVE_LOG_QUEUE)))
    public void saveLog(Message message, Channel channel) {
        final String params = getParams(message);
        EisLog eisLog = JSONObject.parseObject(params, EisLog.class);
        TransactionHelper.persistence(() -> eisLogMapper.save(eisLog));
        basicAck(message, channel);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2EIS_INVENTORY_LOCK_EXCHANGE), key = WMS2EIS_INVENTORY_LOCK_ROUTING_KEY, value = @Queue(WMS2EIS_INVENTORY_LOCK_QUEUE)))
    public void inventoryLock(Message message, Channel channel) {
        requestEis(message, channel, INVENTORY_LOCK);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2EIS_INVENTORY_AUDIT_EXCHANGE), key = WMS2EIS_INVENTORY_AUDIT_ROUTING_KEY, value = @Queue(WMS2EIS_INVENTORY_AUDIT_QUEUE)))
    public void inventoryAudit(Message message, Channel channel) {
        requestEis(message, channel, INVENTORY_AUDIT);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2TMS_SAVE_SHIP_BILL_EXCHANGE), key = WMS2TMS_SAVE_SHIP_BILL_ROUTING_KEY, value = @Queue(WMS2TMS_SAVE_SHIP_BILL_QUEUE)))
    public void tmsShipBill(Message message, Channel channel) {
        requestEis(message, channel, SHIP_BILL);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(WMS2TMS_SAVE_SHIP_BILL_PACKAGE_EXCHANGE), key = WMS2TMS_SAVE_SHIP_BILL_PACKAGE_ROUTING_KEY, value = @Queue(WMS2TMS_SAVE_SHIP_BILL_PACKAGE_QUEUE)))
    public void tmsShipBillPackage(Message message, Channel channel) {
        requestEis(message, channel, SHIP_BILL_PACKAGE);
    }

    private void requestEis(Message message, Channel channel, String url) {
        final String params = getParams(message);
        log.info("{}.request:{}", url, params);
        if (StrUtil.isBlank(params)) {
            return;
        }

        invoke(message, channel, params, url);
    }

    /**
     * 调用接口平台并记录日志
     */
    private void invoke(Message message, Channel channel, String params, String url) {

        ip.call4Eis(url, params);

        basicAck(message, channel);
    }


    /**
     * 得到参数
     */
    private String getParams(Message message) {
        String params = new String(message.getBody());
        Assert.notEmpty(params, "参数不能为空");
        return params;
    }


    /**
     * 手动消费MESSAGE
     *
     * @param message 消息
     * @param channel 通道
     */
    private void basicAck(Message message, Channel channel) {
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
