package com.liquidnet.service.order.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.base.UserPathDto;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.entity.GoblinNftOrder;
import com.liquidnet.service.goblin.param.*;
import com.liquidnet.service.goblin.service.IGoblinNftOrderService;
import com.liquidnet.service.order.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.liquidnet.commons.lang.util.DateUtil.DTF_YMD_HMS;

@Service
@Slf4j
public class GoblinNftOrderServiceImpl implements IGoblinNftOrderService {

    @Autowired
    GoblinRedisUtils goblinRedisUtils;
    @Autowired
    GoblinMongoUtils goblinMongoUtils;
    @Autowired
    QueueUtils queueUtils;
    @Autowired
    GoblinOrderUtils goblinOrderUtils;
    @Autowired
    GoblinNftOrderUtils nftOrderUtils;

    @Value("${liquidnet.service.order.url-pay.pay}")
    private String payUrl;
    @Value("${liquidnet.service.order.url-pay.check}")
    private String checkUrl;
    @Value("${liquidnet.service.order.url-pay.nftPayNotify}")
    private String synUrl;

    @Override
    public ResponseDto<GoblinNftPayResultVo> checkOrder(GoblinNftOrderPayParam payParam) {
        // 基础参数
        String skuId = payParam.getSkuId();
        String uid = CurrentUtil.getCurrentUid();
        GoblinGoodsSkuInfoVo skuVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId);
        String spuId = skuVo.getSpuId();
        int number = 1;

        // 3审核通过 3已上架 0未删除 才可购买
        if (!skuVo.getStatus().equals("3") || !skuVo.getShelvesStatus().equals("3") || skuVo.getDelFlg().equals("1")) {
            return ResponseDto.failure("该商品当前不可购买～");
        }
        // 判断开售、停售时间
        LocalDateTime saleStartTime = skuVo.getSaleStartTime();
        LocalDateTime saleStopTime = skuVo.getSaleStopTime();
        LocalDateTime nowTime = LocalDateTime.now();
        if (nowTime.isBefore(saleStartTime)) {
            return ResponseDto.failure("该商品还未开始售卖～");
        } else if (null != saleStopTime && nowTime.isAfter(saleStopTime)) {
            return ResponseDto.failure("该商品已停售～");
        }
        // 权限限购
        String mobile = StringUtils.defaultString(((String) CurrentUtil.getTokenClaims().get(CurrentUtil.TOKEN_MOBILE)), "");
        boolean isVip = nftOrderUtils.isVipMember(uid);
        Boolean isAuthBuy = goblinOrderUtils.judgeOrderRose(isVip, skuId, mobile, Integer.parseInt(skuVo.getBuyFactor()));
        if (!isAuthBuy) {
            return ResponseDto.failure("该商品仅限特定用户购买～");
        }
        // 判断优惠券不能一起使用
        /*String platVoucherCode = payParam.getPlatVoucherCode();
        String storeVoucherCode = payParam.getStoreVoucherCode();
        if (!StringUtils.isEmpty(platVoucherCode) && !StringUtils.isEmpty(storeVoucherCode)) {
            return ResponseDto.failure("平台券与店铺券不可一起使用哦～");
        }*/

        // 判断数量限购
        int limitCount = skuVo.getBuyLimit();
        if (!Objects.equals(0, limitCount)) {
            String isOutLimit = goblinOrderUtils.judgeOrderLimit(uid, skuId, number, limitCount);
            if (!StringUtils.isEmpty(isOutLimit)) {
                goblinRedisUtils.decrSkuCountByUid(uid, skuId, number);
                return ResponseDto.failure("您已超出限购数量～");
            }
        }
        // 判断库存
        int surplusGeneral = nftOrderUtils.decrSkuStock(skuId, number);
        if (surplusGeneral < 0) {
            nftOrderUtils.backSkuCountAndStock(uid, skuId, number);
            return ResponseDto.failure("库存不足啦～");
        }

        /**
         * 判断优惠券
         * 因平台券和店铺券不能同时使用所以不需要相互考虑失败退另一种券的问题,各自处理就好
         * 回滚好库存和用户已购买数量
         * 无论平台券还是店铺券都只支持代金券1的类型
         */
        BigDecimal voucherPrice = BigDecimal.ZERO;
        BigDecimal storeVoucherPrice = BigDecimal.ZERO;
        String orderId = IDGenerator.nextSnowId();
        String orderCode = IDGenerator.storeCode(orderId);
        BigDecimal totalPrice = skuVo.getPrice();
        if (isVip) {// 会员价
            totalPrice = skuVo.getPriceMember();
        }
        /*if (!StringUtils.isEmpty(platVoucherCode)) {// 平台券
            GoblinUseResultVo useResultVo = nftOrderUtils.useCoupon(platVoucherCode, "购买NFT商品[" + orderCode + "]", totalPrice, spuId, uid);
            String typeVoucher = useResultVo.getCouType();
            if (typeVoucher.equals("-1")) {
                nftOrderUtils.backSkuCountAndStock(uid, skuId, number);
                return ResponseDto.failure("当前平台券不允许使用～");
            } else {
                voucherPrice = useResultVo.getValue();
            }
        }
        if (!StringUtils.isEmpty(storeVoucherCode)) {// 店铺券
            GoblinUseResultVo storeCouponVo = nftOrderUtils.useStoreCoupon(storeVoucherCode, "购买NFT商品[" + orderCode + "]", totalPrice, spuId, uid);
            String typeVoucher = storeCouponVo.getCouType();
            if (typeVoucher.equals("-1")) {
                nftOrderUtils.backSkuCountAndStock(uid, skuId, number);
                return ResponseDto.failure("当前店铺券不允许使用～");
            } else {
                storeVoucherPrice = storeCouponVo.getValue();
            }
        }*/

        // 下单数据
        GoblinNftOrder nftOrder = order(payParam, skuVo.getStoreId(), uid, spuId, number, orderId, orderCode, totalPrice, voucherPrice, storeVoucherPrice, isVip);

        // 下单唤起支付
        GoblinNftPayResultVo nftPayResultVo = payOrder(nftOrder, uid, payParam);
        return ResponseDto.success(nftPayResultVo);
    }

    private GoblinNftOrder order(
            GoblinNftOrderPayParam payParam, String storeId, String uid, String spuId, int number,
            String orderId, String orderCode,
            BigDecimal totalPrice, BigDecimal voucherPrice, BigDecimal storeVoucherPrice,
            boolean isVip
    ) {
        LocalDateTime now = LocalDateTime.now();

        Map token = CurrentUtil.getTokenClaims();
        String headerCliSource = CurrentUtil.getHeaderCliSource(), headerCliVersion = CurrentUtil.getHeaderCliVersion();
        String source = headerCliSource == null ? "" : headerCliSource;
        String version = headerCliVersion == null ? "" : headerCliVersion;

        GoblinStoreInfoVo storeInfoVo = goblinRedisUtils.getStoreInfoVo(storeId);
        String storeName = storeInfoVo.getStoreName();

        // 生成订单
        GoblinNftOrder nftOrder = GoblinNftOrder.getNew();
        nftOrder.setOrderId(orderId);
        nftOrder.setOrderCode(orderCode);
        nftOrder.setStoreId(storeId);
        nftOrder.setSkuId(payParam.getSkuId());
        nftOrder.setSpuId(spuId);
        nftOrder.setNum(number);
        nftOrder.setStoreName(storeName);
        nftOrder.setUserId(uid);
        nftOrder.setUserName(StringUtils.defaultString(((String) token.get(CurrentUtil.TOKEN_NICKNAME)), ""));
        nftOrder.setUserMobile(StringUtils.defaultString(((String) token.get(CurrentUtil.TOKEN_MOBILE)), ""));
        nftOrder.setPriceTotal(totalPrice);
        BigDecimal priceActual = totalPrice.subtract(voucherPrice).subtract(storeVoucherPrice);
        nftOrder.setPriceActual(priceActual.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : priceActual);
        nftOrder.setPriceCoupon(voucherPrice);
        nftOrder.setStorePriceCoupon(storeVoucherPrice);
        nftOrder.setPriceVoucher(voucherPrice.add(storeVoucherPrice));
        nftOrder.setStatus(GoblinStatusConst.NftStatus.ORDER_STATUS_1.getValue());
        /*nftOrder.setUcouponId(payParam.getPlatVoucherCode());
        nftOrder.setStoreCouponId(payParam.getStoreVoucherCode());*/
        nftOrder.setUcouponId("");
        nftOrder.setStoreCouponId("");
        nftOrder.setPayType(payParam.getPayType());
        nftOrder.setDeviceFrom(payParam.getDeviceFrom());
        nftOrder.setSource(source);
        nftOrder.setVersion(version);
        nftOrder.setIsMember(isVip ? 1 : 0);
        nftOrder.setOrderType(GoblinStatusConst.NftStatus.ORDER_TYPE_1.getValue());
        nftOrder.setPayCountdownMinute(5);
        nftOrder.setIpAddress(CurrentUtil.getCliIpAddr());
        nftOrder.setCreatedAt(now);

        return nftOrder;
    }

    private GoblinNftPayResultVo payOrder(GoblinNftOrder nftOrder, String uid, GoblinNftOrderPayParam payParam) {
        // 是否免费
        boolean isFree = false;
        GoblinNftPayResultVo NftPayResultVo = GoblinNftPayResultVo.getNew();
        NftPayResultVo.setOrderId(nftOrder.getOrderId());
        String payCode;
        if (nftOrder.getPriceActual().compareTo(BigDecimal.valueOf(0)) > 0) {// 调用支付
            LinkedMultiValueMap<String, String> httpData = CollectionUtil.linkedMultiValueMapStringString();
            httpData.add("type", "PRODUCT");
            httpData.add("price", nftOrder.getPriceActual().toString());
            // 测试0.01
//             httpData.add("price","0.01");
            httpData.add("name", nftOrder.getStoreName());
            GoblinGoodsSkuInfoVo skuVo = goblinRedisUtils.getGoodsSkuInfoVo(nftOrder.getSkuId());
            httpData.add("detail", skuVo.getName());
            httpData.add("orderCode", nftOrder.getOrderCode());
            httpData.add("orderId", nftOrder.getOrderId());
            httpData.add("clientIp", CurrentUtil.getCliIpAddr());
            httpData.add("notifyUrl", synUrl);
            httpData.add("createDate", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            httpData.add("expireTime", "5");
            httpData.add("payType", nftOrder.getPayType());
            httpData.add("deviceFrom", nftOrder.getDeviceFrom());
            if (nftOrder.getDeviceFrom().equals("js") || nftOrder.getDeviceFrom().equals("applet")) {
                httpData.add("openId", payParam.getOpenId());
            }
            String showUrl = payParam.getShowUrl().concat(nftOrder.getOrderCode());
            String returnUrl = payParam.getReturnUrl().concat(nftOrder.getOrderCode());
            httpData.add("showUrl", showUrl);
            httpData.add("returnUrl", returnUrl);

            LinkedMultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
            header.add("Accept", "application/json;charset=UTF-8");
            String returnData = HttpUtil.post(payUrl, httpData, header);
            log.info("调用 DRAGON 结果 = " + returnData);
            ResponseDto<GoblinPayInnerResultVo> dto = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<GoblinPayInnerResultVo>>() {
            });
            GoblinPayInnerResultVo dtoData = dto.getData();

            payCode = dtoData.getCode();
            NftPayResultVo.setCode(payCode);
            NftPayResultVo.setOrderCode(dtoData.getOrderCode());
            NftPayResultVo.setPayData(dtoData.getPayData());
            NftPayResultVo.setPayType(nftOrder.getPayType());
            NftPayResultVo.setPrice(nftOrder.getPriceActual());
            NftPayResultVo.setShowUrl(showUrl);
            NftPayResultVo.setReturnUrl(returnUrl);
        } else {
            isFree = true;
            nftOrder.setPayType("FREE");
            payCode = "FREE_PAY_CODE";
            NftPayResultVo.setPrice(BigDecimal.valueOf(0));
            NftPayResultVo.setPayType(nftOrder.getPayType());
        }

        LinkedList<String> sqls = CollectionUtil.linkedListString();
        sqls.add(SqlMapping.get("goblin_nft_order.insert"));
        LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();

        nftOrder.setPayCode(payCode);
        sqlDataOrder.add(new Object[]{
                nftOrder.getSpuId(), nftOrder.getSkuId(), nftOrder.getNum(),
                nftOrder.getOrderId(), nftOrder.getStoreId(), nftOrder.getStoreName(), nftOrder.getOrderCode(), nftOrder.getUserId(), nftOrder.getUserName(), nftOrder.getUserMobile(), nftOrder.getPriceTotal(), nftOrder.getPayCode(),
                nftOrder.getPriceActual(), nftOrder.getPriceCoupon(), nftOrder.getStorePriceCoupon(), nftOrder.getPriceVoucher(), nftOrder.getStatus(), nftOrder.getUcouponId(), nftOrder.getStoreCouponId(), nftOrder.getPayType(), nftOrder.getDeviceFrom(),
                nftOrder.getSource(), nftOrder.getVersion(), nftOrder.getIsMember(), nftOrder.getOrderType(), nftOrder.getPayCountdownMinute(), nftOrder.getIpAddress(), nftOrder.getCreatedAt()
        });

        // 订单vo
        GoblinNftOrderVo orderVo = GoblinNftOrderVo.getNew().copy(nftOrder);
        orderVo.setCreatedAt(nftOrder.getCreatedAt());

        // 待支付发送队列
        queueUtils.sendMsgByRedisGoblinStock(orderVo.getOrderCode(), nftOrder.getCreatedAt(), "NFT");

        // redis 订单详情
        nftOrderUtils.setNftOrder(orderVo);
        // redis 订单列表
        nftOrderUtils.addNftOrderList(uid, orderVo.getOrderId());

        // mongo
        goblinMongoUtils.setGoblinNftOrderVo(orderVo);

        // 执行sql
        String sqlData = SqlMapping.gets(sqls, sqlDataOrder);
        queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(), sqlData);

        log.info(UserPathDto.setData("NFT下单(唤起支付)", nftOrder, NftPayResultVo));
        if (isFree) {// 免费直接回调
            GoblinNftOrderPayCallbackParam NftOrderPayCallbackParam = GoblinNftOrderPayCallbackParam.getNew();
            NftOrderPayCallbackParam.setCode(payCode);
            NftOrderPayCallbackParam.setOrderCode(nftOrder.getOrderCode());
            NftOrderPayCallbackParam.setPaymentAt(DateUtil.format(LocalDateTime.now(), DateUtil.Formatter.yyyyMMddHHmmss));
            NftOrderPayCallbackParam.setPrice(nftOrder.getPriceActual());
            NftOrderPayCallbackParam.setPaymentId("FREE_PAYMENT_ID");
            NftOrderPayCallbackParam.setPaymentType(null);
            NftOrderPayCallbackParam.setStatus(1);
            syncOrder(NftOrderPayCallbackParam);
        }

        return NftPayResultVo;
    }

    @Override
    public ResponseDto<GoblinNftPayResultVo> payAgain(GoblinNftOrderPayAgainParam param) {
        return ResponseDto.failure("暂不支持此接口");
        /*String uid = CurrentUtil.getCurrentUid();
        LocalDateTime now = LocalDateTime.now();
        //检查订单时间 是否关闭
        GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(param.getOrderId());

        if (storeOrderVo == null) {
            return ResponseDto.failure("订单不存在");
        }

        if (!storeOrderVo.getUserId().equals(uid)) {
            return ResponseDto.failure(ErrorMapping.get("20003"));
        }

        if (storeOrderVo.getStatus() != GoblinStatusConst.Status.ORDER_STATUS_0.getValue()) {
            return ResponseDto.failure("订单无法支付");//订单
        }
        MultiValueMap<String, String> header = CollectionUtil.linkedMultiValueMapStringString();
        header.add("Accept", "application/json;charset=UTF-8");
        String returnCheckData = HttpUtil.get(checkUrl + "?code=" + storeOrderVo.getPayCode(), null, header);
        ResponseDto<GoblinPayInnerResultVo> checkVo = JsonUtils.fromJson(returnCheckData, new TypeReference<ResponseDto<GoblinPayInnerResultVo>>() {
        });
        if (checkVo.getData().getStatus() == 1) {
            return ResponseDto.failure("订单已支付");
        }
        BigDecimal price = BigDecimal.ZERO;
        String[] orderIds = goblinRedisUtils.getMasterCode(storeOrderVo.getMasterOrderCode());
        for (String orderId : orderIds) {
            GoblinStoreOrderVo orderVo = goblinRedisUtils.getGoblinOrder(orderId);
            price = price.add(orderVo.getPriceActual());
        }
        GoblinNftPayResultVo NftPayResultVo = GoblinNftPayResultVo.getNew();
        if (!storeOrderVo.getPayType().equals("FREE")) {
            // 调用支付
            LinkedMultiValueMap<String, String> httpData = CollectionUtil.linkedMultiValueMapStringString();
            httpData.add("type", "PRODUCT");
            httpData.add("price", price.toString());
            httpData.add("name", goblinRedisUtils.getStoreInfoVo(storeOrderVo.getStoreId()).getStoreName());
            httpData.add("detail", "查找最初订单");
            httpData.add("orderCode", storeOrderVo.getMasterOrderCode());
            httpData.add("clientIp", storeOrderVo.getIpAddress());
            httpData.add("notifyUrl", synUrl);
            httpData.add("createDate", storeOrderVo.getCreatedAt());
            httpData.add("expireTime", storeOrderVo.getPayCountdownMinute().toString());
            httpData.add("payType", param.getPayType());
            httpData.add("deviceFrom", param.getDeviceFrom());

            if (param.getDeviceFrom().equals("js") || param.getDeviceFrom().equals("applet")) {
                httpData.add("openId", param.getOpenId());
            }
            httpData.add("showUrl", param.getShowUrl() + storeOrderVo.getMasterOrderCode());
            httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
            String returnData = HttpUtil.post(payUrl, httpData);
            log.debug("调用 DRAGON 结果 = " + returnData);
            ResponseDto<GoblinPayInnerResultVo> dto = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<GoblinPayInnerResultVo>>() {
            });
            NftPayResultVo.setCode(dto.getData().getCode());
            NftPayResultVo.setOrderCode(storeOrderVo.getMasterOrderCode());
            NftPayResultVo.setPayData(dto.getData().getPayData());
            NftPayResultVo.setOrderId(storeOrderVo.getMasterOrderCode());
            NftPayResultVo.setPayType(param.getPayType());
            NftPayResultVo.setPrice(price);
            NftPayResultVo.setShowUrl(param.getShowUrl() + storeOrderVo.getMasterOrderCode());
            NftPayResultVo.setReturnUrl(param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
            //redis
            storeOrderVo.setPayType(param.getPayType());
            storeOrderVo.setDeviceFrom(param.getDeviceFrom());
            storeOrderVo.setPayCode(NftPayResultVo.getCode());
            goblinRedisUtils.setGoblinOrder(storeOrderVo.getOrderId(), storeOrderVo);
            //mongo
            goblinMongoUtils.updateGoblinStoreOrderVo(storeOrderVo.getOrderId(), storeOrderVo);
            //mysql
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_AGAIN.getKey(),
                    SqlMapping.get("goblin_order.pay.again", param.getPayType(), param.getDeviceFrom(), NftPayResultVo.getCode(), param.getOrderId(), now, now));
            log.info(UserPathDto.setData("再次支付[新支付方式]", param, NftPayResultVo));
        }
        return ResponseDto.success(NftPayResultVo);*/
    }

    @Override
    public ResponseDto<Integer> checkOrderResult(String orderId) {
        String uid = CurrentUtil.getCurrentUid();
        GoblinNftOrderVo nftOrder = nftOrderUtils.getNftOrder(orderId);
        if (null == nftOrder || !nftOrder.getUserId().equals(uid)) {
            return ResponseDto.failure("订单不存在");
        } else {
            String returnCheckData = HttpUtil.get(checkUrl + "?code=" + nftOrder.getPayCode(), null);
            ResponseDto<GoblinNftOrderPayCallbackParam> syncOrderDtoParam = JsonUtils.fromJson(returnCheckData, new TypeReference<ResponseDto<GoblinNftOrderPayCallbackParam>>() {
            });
            if (syncOrderDtoParam.getData().getStatus() == 1) {
                //处理订单
                syncOrder(syncOrderDtoParam.getData());
                return ResponseDto.success(1);
            } else {
                return ResponseDto.success(0);
            }
        }
    }

    @Override
    public String syncOrder(GoblinNftOrderPayCallbackParam syncOrderParam) {
        log.info("SYNC PARAM = " + syncOrderParam.toString());

        String orderCode = syncOrderParam.getOrderCode();
        String orderId = syncOrderParam.getOrderId();

        GoblinNftOrderVo orderVo = nftOrderUtils.getNftOrder(orderId);
        if (null == orderVo) {
            log.error("Nft订单不存在 param:[orderCode:{}]", orderCode);
            return "fail";
        }
        if (orderVo.getPayCode().equals(syncOrderParam.getCode())) {
            log.error("Nft订单payCode不匹配 param:[orderCode:{}, payCode:{}]", orderCode, syncOrderParam.getCode());
            return "fail";
        }
        if (!Objects.equals(orderVo.getStatus(), GoblinStatusConst.NftStatus.ORDER_STATUS_2.getValue())) {
            log.error("Nft订单当前状态不能支付回调 param:[orderCode:{}, status:{}]", orderCode, orderVo.getStatus());
            return "fail";
        }

        if (Objects.equals(1, syncOrderParam.getStatus())) {// 超时支付
            if (Objects.equals(orderVo.getStatus(), GoblinStatusConst.NftStatus.ORDER_STATUS_3.getValue())) {
                log.error("Nft订单超时支付 param:[orderCode:{}]", orderCode);
                // 退款
                nftOrderUtils.refundOrderSku(orderId, syncOrderParam.getPaymentId(), syncOrderParam.getPaymentType());
            } else if (syncOrderParam.getStatus().equals(1)) {// 正常流程
                LocalDateTime now = LocalDateTime.now();
                String uid = orderVo.getUserId();

                GoblinNftOrder nftOrder = GoblinNftOrder.getNew();
                nftOrder.setPaymentType(syncOrderParam.getPaymentType());
                nftOrder.setPaymentId(syncOrderParam.getPaymentId());
                nftOrder.setPayCode(syncOrderParam.getCode());
                LocalDateTime payTime = LocalDateTime.parse(syncOrderParam.getPaymentAt(), DTF_YMD_HMS);
                nftOrder.setPayTime(payTime);
                nftOrder.setStatus(GoblinStatusConst.NftStatus.ORDER_STATUS_2.getValue());
                nftOrder.setUpdatedAt(now);

                LinkedList<String> sqls = CollectionUtil.linkedListString();
                LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();
                sqls.add(SqlMapping.get("goblin_nft_order.update.pay"));
                sqlDataOrder.add(new Object[]{
                        nftOrder.getPaymentType(), nftOrder.getPaymentId(), nftOrder.getPayCode(),
                        nftOrder.getPayTime(), nftOrder.getStatus(), nftOrder.getUpdatedAt(),
                        orderId, now, now
                });

                // redis
                orderVo.setStatus(GoblinStatusConst.NftStatus.ORDER_STATUS_2.getValue());
                orderVo.setPayCode(syncOrderParam.getCode());
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                LocalDateTime parsedDate = LocalDateTime.parse(syncOrderParam.getPaymentAt(), formatter);
                orderVo.setPayTime(parsedDate);
                orderVo.setPaymentId(syncOrderParam.getPaymentId());
                orderVo.setPaymentType(syncOrderParam.getPaymentType());
                nftOrderUtils.setNftOrder(orderVo);
                // mongo
                goblinMongoUtils.updateGoblinNftOrderVo(orderVo);
                // mysql
                queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(),
                        SqlMapping.gets(sqls, sqlDataOrder));

                // 加积分
                goblinOrderUtils.doTask(uid, orderVo.getPriceActual());
            }
        }

        return "success";
    }

    @Override
    public String refundSyncOrder(GoblinNftOrderRefundCallbackParam refundCallbackParam) {
        LocalDateTime now = LocalDateTime.now();
        log.info("NftRefundCallback订单退款回调参数: [RefundCallbackParam={}]", refundCallbackParam);
        GoblinNftOrderCallBackVo nftOrderRefundVo = goblinMongoUtils.getGoblinNftOrderRefundVo(refundCallbackParam.getOrderRefundCode());
        if (nftOrderRefundVo == null) {
            log.info("NftRefundCallback: 退款订单查询失败，编号{}", refundCallbackParam.getOrderRefundCode());
            return "fail";
        }
        if (nftOrderRefundVo.getStatus() == GoblinStatusConst.NftStatus.ORDER_REFUND_STATUS_2.getValue()) {
            log.info("NftRefundCallback: 退款订单已完成，编号{}", refundCallbackParam.getOrderRefundCode());
            return "success";
        }
        Integer status = refundCallbackParam.getStatus();
        if (1 == status) { // 退款成功
            LinkedList<String> sqls = CollectionUtil.linkedListString();
            LinkedList<Object[]> sqlsOrder = CollectionUtil.linkedListObjectArr();
            LinkedList<Object[]> sqlsBackOrder = CollectionUtil.linkedListObjectArr();
            sqls.add(SqlMapping.get("goblin_nft_order.update.refund"));
            sqls.add(SqlMapping.get("goblin_nft_order_refund.refund"));
            String orderId = nftOrderRefundVo.getOrderId();
            GoblinNftOrderVo nftOrder = nftOrderUtils.getNftOrder(orderId);
            //整单退款 退券
            nftOrder.setStatus(GoblinStatusConst.NftStatus.ORDER_STATUS_5.getValue());
            if (StringUtil.isNotEmpty(nftOrder.getUcouponId())) {
                goblinOrderUtils.backCoupon(nftOrder.getUcouponId(), nftOrder.getUserId());
            }

            if (StringUtil.isNotEmpty(nftOrder.getStoreCouponId())) {
                List<BackCouponParam> params = ObjectUtil.getBackCouponParam();
                BackCouponParam backCouponParam = BackCouponParam.getNew();
                backCouponParam.setuCouponIds(nftOrder.getStoreCouponId());
                backCouponParam.setUid(nftOrder.getUserId());
                params.add(backCouponParam);
                goblinOrderUtils.backStoreCoupon(params);
            }
            nftOrderRefundVo.setStatus(GoblinStatusConst.NftStatus.ORDER_REFUND_STATUS_2.getValue());
            nftOrderRefundVo.setRefundAt(now);
            //redis
            nftOrderUtils.setNftOrder(nftOrder);
            nftOrderUtils.setBackOrderVo(nftOrderRefundVo);
            //mongo
            goblinMongoUtils.updateGoblinNftOrderVo(nftOrder);
            goblinMongoUtils.updateGoblinNftOrderRefundVo(nftOrderRefundVo);
            //mysql
            sqlsOrder.add(new Object[]{
                    nftOrder.getStatus(), now,
                    orderId, now, now
            });
            sqlsBackOrder.add(new Object[]{
                    nftOrderRefundVo.getStatus(), now, now, nftOrderRefundVo.getOrderRefundId(), now, now
            });
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_ORDER_OPERA.getKey(),
                    SqlMapping.gets(sqls, sqlsOrder, sqlsBackOrder));
            //减积分
            goblinOrderUtils.desTask(nftOrder.getUserId(), nftOrderRefundVo.getRealBackPrice());
        } else if (0 == status) {
            return "fail";
        }
        return "success";
    }
}
