package com.prolog.cs.biz.outbound.service.impl.mq;

import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.prolog.cs.biz.outbound.service.MqOutBoundConsumer;
import com.prolog.cs.biz.outbound.service.MqOutBoundProducer;
import com.prolog.cs.biz.outbound.service.PickTaskService;
import com.prolog.entity.vo.ApplyForDocumentPrintingVO;
import com.prolog.entity.vo.OrderBindingGridFeedbackVO;
import com.prolog.entity.vo.OutboundCheckResultCallbackVO;
import com.prolog.entity.vo.OutboundTaskCallbackVO;
import com.prolog.framework.core.exception.BizException;
import com.prolog.upcloud.base.wh.operate.model.EisLog;
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 java.util.Date;

import static com.prolog.constant.EisBusinessConstant.EIS;
import static com.prolog.constant.EisInterfaceConstant.*;
import static com.prolog.constant.RabbitMqConstant.*;

@Slf4j
@Component
public class RabbitMqOutBoundConsumerImpl implements MqOutBoundConsumer {

    @Resource
    private MqOutBoundProducer producer;

    @Resource
    private PickTaskService pickTaskService;

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(EIS2WMS_OUTBOUND_TASK_CALLBACK_EXCHANGE), key = EIS2WMS_OUTBOUND_TASK_CALLBACK_ROUTING_KEY, value = @Queue(EIS2WMS_OUTBOUND_TASK_CALLBACK_QUEUE)))
    public void outboundTaskCallback(Message message, Channel channel) {
        final String params = new String(message.getBody());

        handleAndSaveLog(() -> {
            pickTaskService.outboundTaskCallback(JSONObject.parseObject(params, OutboundTaskCallbackVO.class));
        }, params, OUTBOUND_TASK_CALLBACK);
        basicAck(message, channel);
    }

    @Override
//    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(EIS2WMS_COMPLETE_TASK_EXCHANGE), key = EIS2WMS_COMPLETE_TASK_ROUTING_KEY, value = @Queue(EIS2WMS_COMPLETE_TASK_QUEUE)))
    public void completeTask(Message message, Channel channel) {
//        final String params = new String(message.getBody());
//        List<CompleteTaskVO> list = JSONObject.parseArray(params, CompleteTaskVO.class);
//        EisLog eisLog = new EisLog();
//        eisLog.setId(IdUtil.fastSimpleUUID());
//        eisLog.setInitiator(EIS);
//        eisLog.setStatus(1);
//        eisLog.setUrl(COMPLETE_TASK);
//        eisLog.setRequest(params);
//        eisLog.setGmtCreate(new Date());
//        try {
//            pickTaskService.completeTask(list);
//        } catch (Exception e) {
//            eisLog.setGmtModified(new Date());
//            eisLog.setResponse(e.getMessage());
//            producer.saveEisLog(eisLog);
//            log.error("", e);
//        }
//        eisLog.setResponse("EIS出库回传WMS成功");
//        eisLog.setGmtModified(new Date());
//        producer.saveEisLog(eisLog);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(EIS2WMS_OUTBOUND_CHECK_RESULT_CALLBACK_EXCHANGE), key = EIS2WMS_OUTBOUND_CHECK_RESULT_CALLBACK_ROUTING_KEY, value = @Queue(EIS2WMS_OUTBOUND_CHECK_RESULT_CALLBACK_QUEUE)))
    public void outboundCheckResultCallback(Message message, Channel channel) {
        final String params = new String(message.getBody());

        handleAndSaveLog(() -> {
            pickTaskService.outboundCheckResultCallback(JSONObject.parseObject(params, OutboundCheckResultCallbackVO.class));
        }, params, OUTBOUND_CHECK_RESULT_CALLBACK);
        basicAck(message, channel);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(EIS2WMS_ORDER_BINDING_GRID_FEEDBACK_EXCHANGE), key = EIS2WMS_ORDER_BINDING_GRID_FEEDBACK_ROUTING_KEY, value = @Queue(EIS2WMS_ORDER_BINDING_GRID_FEEDBACK_QUEUE)))
    public void orderBindingGridFeedback(Message message, Channel channel) {
        final String params = new String(message.getBody());

        handleAndSaveLog(() -> {
            pickTaskService.orderBindingGridFeedback(JSONObject.parseObject(params, OrderBindingGridFeedbackVO.class));
        }, params, ORDER_BINDING_GRID_FEEDBACK);
        basicAck(message, channel);
    }

    @Override
    @RabbitListener(bindings = @QueueBinding(exchange = @Exchange(EIS2WMS_APPLY_FOR_DOCUMENT_PRINTING_EXCHANGE), key = EIS2WMS_APPLY_FOR_DOCUMENT_PRINTING_ROUTING_KEY, value = @Queue(EIS2WMS_APPLY_FOR_DOCUMENT_PRINTING_QUEUE)))
    public void applyForDocumentPrinting(Message message, Channel channel) {
        final String params = new String(message.getBody());

        handleAndSaveLog(() -> {
            pickTaskService.applyForDocumentPrinting(JSONObject.parseObject(params, ApplyForDocumentPrintingVO.class));
        }, params, APPLY_FOR_DOCUMENT_PRINTING);
        basicAck(message, channel);
    }


    public void handleAndSaveLog(WmsHandleFunctional func, String params, String url) {
        EisLog eisLog = new EisLog();
        eisLog.setId(IdUtil.fastSimpleUUID());
        eisLog.setInitiator(EIS);
        eisLog.setStatus(1);
        eisLog.setUrl(url);
        eisLog.setRequest(params);
        eisLog.setGmtCreate(new Date());
        try {
            func.accept();
        } catch (Exception e) {
            eisLog.setStatus(2);
            eisLog.setGmtModified(new Date());
            eisLog.setResponse(e.getMessage());
            producer.saveEisLog(eisLog);
            log.error("", e);
            return;
        }
        eisLog.setResponse("接收请求成功");
        eisLog.setGmtModified(new Date());
        producer.saveEisLog(eisLog);
    }

    @FunctionalInterface
    public interface WmsHandleFunctional {
        void accept() throws BizException;
    }

    private void basicAck(Message message, Channel channel) {
        try {
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
