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) {
        // 基础参数
        GoblinNftOrderPayGoodsParam payGoodsParam = payParam.getGoblinNtfOrderPayGoodsParam();

        // 判断库存
        String skuId = payGoodsParam.getSkuId();
        int number = 1;
        int surplusGeneral = nftOrderUtils.decrSkuStock(skuId, number);
        if (surplusGeneral < 0) {
            nftOrderUtils.incrSkuStock(skuId, number);
            return ResponseDto.failure("库存不足啦～");
        }

        // 是店铺商品可购买
        String storeId = payGoodsParam.getStoreId();
        String spuId = payGoodsParam.getSpuId();
        GoblinGoodsInfoVo spuVo = goblinRedisUtils.getGoodsInfoVo(spuId);
        GoblinGoodsSkuInfoVo skuVo = goblinRedisUtils.getGoodsSkuInfoVo(skuId);
        if (!storeId.equals(spuVo.getStoreId()) || !storeId.equals(skuVo.getStoreId())) {
            log.info("NFT-storeId错误 相关参数:[storeId:{}, spuId:{}, skuId:{}]", storeId, spuId, skuId);
            return ResponseDto.failure("非法参数～");
        }
        // 3审核通过 3已上架 0未删除 才可购买
        if (!skuVo.getStatus().equals("3") || !skuVo.getShelvesStatus().equals("3") || skuVo.getDelFlg().equals("1")) {
            return ResponseDto.failure("该商品当前不可购买～");
        }

        // TODO: jxl 2022/3/23 是否开售

        // 数量限购
        String uid = CurrentUtil.getCurrentUid();
        int limitCount = skuVo.getBuyLimit() == 0 ? Integer.MAX_VALUE : skuVo.getBuyLimit();
        String isOutLimt = goblinOrderUtils.judgeOrderLimit(uid, skuId, 1, limitCount);
        if (!StringUtils.isEmpty(isOutLimt)) {
            goblinRedisUtils.decrSkuCountByUid(uid, skuId, number);
            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 = payGoodsParam.getPlatVoucherCode();
        String storeVoucherCode = payGoodsParam.getStoreVoucherCode();
        if (!StringUtils.isEmpty(platVoucherCode) && !StringUtils.isEmpty(storeVoucherCode)) {
            return ResponseDto.failure("平台券与店铺券不可一起使用哦～");
        }
        BigDecimal voucherPrice = BigDecimal.ZERO;
        String orderId = IDGenerator.nextSnowId();
        String orderCode = IDGenerator.storeCode(orderId);
        BigDecimal totalPrice = skuVo.getPrice();
        if (isVip) {
            totalPrice = skuVo.getPriceMember();
        }
        if (!StringUtils.isEmpty(platVoucherCode)) {// 平台券
            HashMap<String, Object> hashMap = nftOrderUtils.useCoupon(platVoucherCode, "购买NFT商品[" + orderCode + "]", totalPrice, spuId, uid);
            if (hashMap != null) {
                voucherPrice = (BigDecimal) hashMap.get("voucher");
                Integer typeVoucher = (Integer) hashMap.get("type");
                if (typeVoucher.equals(-1)) {
                    return ResponseDto.failure("当前平台券不允许使用～");
                } else {
                    // TODO: jxl 2022/3/24 错误回退
                }
            }
        }
        BigDecimal storeVoucherPrice = BigDecimal.ZERO;
        if (!StringUtils.isEmpty(storeVoucherCode)) {// 店铺券
            GoblinUseResultVo storeCouponVo = nftOrderUtils.useStoreCoupon(storeVoucherCode, "购买NFT商品[" + orderCode + "]", totalPrice, spuId, uid);
            String typeVoucher;
            if (storeCouponVo != null) {
                storeVoucherPrice = storeCouponVo.getValue();
                typeVoucher = storeCouponVo.getCouType();
                if (typeVoucher.equals("-1")) {
                    return ResponseDto.failure("当前店铺券不允许使用～");
                } else {
                    // TODO: jxl 2022/3/24 错误回退
                }
            }
        }

        // 下单数据
        GoblinNftOrder nftOrder = order(payParam, payGoodsParam, uid, orderId, orderCode, totalPrice, voucherPrice, storeVoucherPrice, isVip);

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

    private GoblinNftOrder order(
            GoblinNftOrderPayParam payParam, GoblinNftOrderPayGoodsParam payGoodsParam, String uid,
            String orderId, String orderCode,
            BigDecimal totalPrice, BigDecimal voucherPrice, BigDecimal storeVoucherPrice,
            boolean isVip
    ) {
        String storeId = payGoodsParam.getStoreId();
        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.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(payGoodsParam.getPlatVoucherCode());
        nftOrder.setStoreCouponId(payGoodsParam.getStoreVoucherCode());
        nftOrder.setPayType(payParam.getPayType());
        nftOrder.setDeviceFrom(payParam.getDeviceFrom());
        nftOrder.setSource(source);
        nftOrder.setVersion(version);
        nftOrder.setIsMember(isVip ? 1 : 0);
        nftOrder.setOrderType(0);
        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();
        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.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("下单(唤起支付)", 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";
    }
}
