package com.dhcc.finance.rabbitmq;

import com.dhcc.common.constant.FinanceStatusCode;
import com.dhcc.common.constant.SysConstants;
import com.dhcc.common.exception.RestStatusException;
import com.dhcc.common.model.CurrencyMeta;
import com.dhcc.common.model.response.RestfulResponse;
import com.dhcc.finance.constant.FinanceDictConsts;
import com.dhcc.finance.main.dao.CwBdRecordBatchMapper;
import com.dhcc.finance.main.dao.CwBdRecordSerialMapper;
import com.dhcc.finance.main.domain.CwBdRecordBatch;
import com.dhcc.finance.main.domain.CwBdRecordSerial;
import com.dhcc.finance.main.model.VoucherRequestInfo;
import com.dhcc.finance.main.service.FinanceForThirdService;
import com.dhcc.finance.main.service.FinanceForThirdSupplyService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;

/**
 * @author liuxianjv
 * @description: 监听处理MQ里面系列项目的记账信息
 * @date 2020-06-04 14:00
 */
@Slf4j
@Component
@RabbitListener(bindings = @QueueBinding(
        exchange = @Exchange(value = SysConstants.MqConstans.EXCHANGE_BUSLOG_TOPIC, type = ExchangeTypes.TOPIC),
        value = @Queue(value = SysConstants.MqConstans.ROUTE_KEY_SEQ_SERIES_PROJECT_ACCOUNT_LOG, durable = "true"),
        key = SysConstants.MqConstans.ROUTE_KEY_SEQ_SERIES_PROJECT_ACCOUNT_LOG),
        concurrency = "6")
public class SeqSeriesProjectAccountLogServiceImpl {

    @Autowired
    FinanceForThirdService financeForThirdService;// 财务对外提供的服务

    @Autowired
    CwBdRecordBatchMapper cwBdRecordBatchMapper;// 自动记录批次信息表
    @Autowired
    CwBdRecordSerialMapper cwBdRecordSerialMapper;

    @Autowired
    FinanceForThirdSupplyService financeForThirdSupplyService;


    /**
     * @param [voucherRequestInfo, channel, message]
     * @return void
     * @description: 消费消息获取记账信息并处理
     * @author liuxianjv
     * @date 2020-06-04 14:00
     */
    @RabbitHandler
    public void recieved(VoucherRequestInfo voucherRequestInfo, Channel channel, Message message) throws IOException {
        RestfulResponse<Object, CurrencyMeta> createVoucherInfo = new RestfulResponse<Object, CurrencyMeta>(SysConstants.CODE.FAIL,
                FinanceStatusCode.CREATE_VOUCHER_INFO_ERROR.message());
        try {
            log.info("进入监听>>>>>>>>>>>>" + voucherRequestInfo.toString());
            log.info("当前线程号>>>>>>>>>>>>" + Thread.currentThread().getName());
            //记录批次号
            RestfulResponse<Object, CurrencyMeta> res = financeForThirdSupplyService.insertRecordForBatch(voucherRequestInfo);
            if (SysConstants.CODE.SUCCESS != res.getCode()) {//若重复批次号记账成功,则不记账
                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
                return;
            }

            try {
                createVoucherInfo = financeForThirdService.createVoucherInfo(voucherRequestInfo);
            } catch (Exception e) {
                log.error("记账异常>>>>>>>>>", e);
                throw e;// 如果发生异常将异常抛出
            }
            log.info("消费返回结果>>>>>>>>>" + createVoucherInfo.getMsg());
        } catch (Exception e) {
            if (e instanceof RestStatusException) {
                // 如果是自己抛出的异常,根据返回的异常编号,从财务状态枚举中获取提示信息
                FinanceStatusCode enumByKey = FinanceStatusCode.getEnumByKey(e.getMessage());
                if (enumByKey != null) {
                    createVoucherInfo.setMsg(enumByKey.message());
                }
            }
            log.error("消息消费异常>>>>>>>>>", e);
        } finally {
            //最终进行消息确认处理的确认,将消息从队列中进行移除,完成消费
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            CwBdRecordBatch cwBdRecordBatch1 = new CwBdRecordBatch();//批次号记录实体
            cwBdRecordBatch1.setBatchNo(voucherRequestInfo.getBatchNo());
            cwBdRecordBatch1.setTradecode(voucherRequestInfo.getTradeCode());
            cwBdRecordBatch1.setUpdateTime(new Date());
            if (SysConstants.CODE.SUCCESS != createVoucherInfo.getCode()) {
                cwBdRecordBatch1.setFailReason(createVoucherInfo.getMsg());
                cwBdRecordBatch1.setSignType(FinanceDictConsts.SF.no);
                if (FinanceStatusCode.CREATE_VOUCHER_INFO_ERROR.message().equals(createVoucherInfo.getMsg())) {
                    CwBdRecordSerial cwBdRecordSerial = new CwBdRecordSerial();//流水记录实体
                    cwBdRecordSerial.setBatchNo(voucherRequestInfo.getBatchNo());
                    cwBdRecordSerial.setTradecode(voucherRequestInfo.getTradeCode());
                    cwBdRecordSerial.setSignType(FinanceDictConsts.STATE.fail);
                    cwBdRecordSerialMapper.updateRecordForSerialNo(cwBdRecordSerial);
                }
            } else {
                cwBdRecordBatch1.setSignType(FinanceDictConsts.SF.yes);
                if (StringUtils.isNotBlank((String) createVoucherInfo.getData())
                        && FinanceStatusCode.SCENARIO_NOT_CREATE_VOUCHER.message().equals(createVoucherInfo.getData())) {
                    cwBdRecordBatch1.setFailReason((String) createVoucherInfo.getData());
                } else {
                    cwBdRecordBatch1.setFailReason("");
                }
            }
            cwBdRecordBatchMapper.updateRecordBybatchNo(cwBdRecordBatch1);//更新批次号记录表
        }
    }

}