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.ErrorMapping;
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 org.springframework.util.MultiValueMap;

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.goblinUrl}")
    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) {
        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") && storeOrderVo.getPayType().equals(param.getPayType()) && storeOrderVo.getDeviceFrom().equals(param.getDeviceFrom())) {
//            payInnerResultVo.setCode(checkVo.getData().getCode());
//            payInnerResultVo.setOrderCode(checkVo.getData().getOrderCode());
//            payInnerResultVo.setPayData(checkVo.getData().getPayData());
//            payInnerResultVo.setOrderId(param.getOrderId());
//            payInnerResultVo.setPayType(param.getPayType());
//            payInnerResultVo.setPrice(storeOrderVo.getPriceActual());
//            storeOrderVo.setPayCode(payInnerResultVo.getCode());
//            payInnerResultVo.setShowUrl(param.getShowUrl() + storeOrderVo.getOrderId());
//            payInnerResultVo.setReturnUrl(param.getReturnUrl() + storeOrderVo.getOrderId());
//            log.info(UserPathDto.setData("再次支付[原支付方式]", param, payInnerResultVo));
//        } else
        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("orderId", storeOrderVo.getOrderId());
            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());
            }
//            if (param.getPayType().equals("alipay") && param.getDeviceFrom().equals("wap")) {
//                httpData.add("showUrl", param.getShowUrl() + storeOrderVo.getMasterOrderCode());
//                httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
//            }
//            if (param.getPayType().equals("douyinpay")) {
//                httpData.add("showUrl", param.getShowUrl() + storeOrderVo.getMasterOrderCode());
//                httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
//            }
//            if (param.getPayType().equals("unionpay")) {
//                httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getMasterOrderCode());
//            }
            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();
        GoblinStoreOrderVo storeOrderVo = goblinRedisUtils.getGoblinOrder(orderId);
        if (storeOrderVo == null) {
            return ResponseDto.failure("订单不存在");
        } else {
            if (!storeOrderVo.getUserId().equals(uid)) {
                return null;
            }
            String returnCheckData = HttpUtil.get(checkUrl + "?code=" + storeOrderVo.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();
        String nowStr = DateUtil.getNowTime();
        log.info("refundCallback订单退款回调参数: [RefundCallbackParam={}]", refundCallbackParam);
        GoblinBackOrderVo backOrderVo = goblinMongoUtils.getGoblinBackOrderVoByBackCode(refundCallbackParam.getOrderRefundCode());
        if (backOrderVo == null) {
            log.info("refundCallback: 退款订单查询失败，编号{}", refundCallbackParam.getOrderRefundCode());
            return "fail";
        }
        if (backOrderVo.getStatus() == GoblinStatusConst.Status.ORDER_LOG_STATUS_20.getValue() || backOrderVo.getStatus() == GoblinStatusConst.Status.ORDER_LOG_STATUS_201.getValue()) {
            log.info("refundCallback: 退款订单已取消，编号{}", refundCallbackParam.getOrderRefundCode());
            return "fail";
        }
        if (backOrderVo.getStatus() == GoblinStatusConst.Status.ORDER_LOG_STATUS_22.getValue()) {
            log.info("refundCallback: 退款订单已完成，编号{}", refundCallbackParam.getOrderRefundCode());
            return "success";
        }
        Integer status = refundCallbackParam.getStatus();
        if (1 == status && (backOrderVo.getStatus() == 0 || backOrderVo.getStatus() == 10)) { // 退款成功
            LinkedList<String> sqls = CollectionUtil.linkedListString();
            LinkedList<Object[]> sqlsOrder = CollectionUtil.linkedListObjectArr();
            LinkedList<Object[]> sqlsOrderSku = CollectionUtil.linkedListObjectArr();
            LinkedList<Object[]> sqlsBackOrder = CollectionUtil.linkedListObjectArr();
            sqls.add(SqlMapping.get("goblin_order.store.refundPrice"));
            sqls.add(SqlMapping.get("goblin_order.store.refundSkuPrice"));
            sqls.add(SqlMapping.get("goblin_order.store.refundBackOrder"));
            String orderId = backOrderVo.getOrderId();
            List<GoblinBackOrderSkuVo> backOrderSkuVos = backOrderVo.getBackOrderSkuVos();
            GoblinStoreOrderVo orderVo = goblinRedisUtils.getGoblinOrder(orderId);
            orderVo.setPriceRefund(orderVo.getPriceRefund() == null ? BigDecimal.ZERO : orderVo.getPriceRefund().add(refundCallbackParam.getRefundPrice()));
            if (orderVo.getPriceRefund().compareTo(orderVo.getPriceActual()) >= 0) {
                //整单退款 退券
                orderVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_6.getValue());
                if (!(orderVo.getUcouponId() == null || orderVo.getUcouponId().equals(""))) {
                    goblinOrderUtils.backCoupon(orderVo.getUcouponId(), orderVo.getUserId());
                }

                if (!(orderVo.getStoreCouponId() == null || orderVo.getStoreCouponId().equals(""))) {
                    List<BackCouponParam> params = ObjectUtil.getBackCouponParam();
                    BackCouponParam backCouponParam = BackCouponParam.getNew();
                    backCouponParam.setuCouponIds(orderVo.getStoreCouponId());
                    backCouponParam.setUid(orderVo.getUserId());
                    params.add(backCouponParam);
                    goblinOrderUtils.backStoreCoupon(params);
                }
            }
            backOrderVo.setStatus(GoblinStatusConst.Status.ORDER_BACK_STATUS_2.getValue());
            backOrderVo.setRefundAt(nowStr);
            for (GoblinBackOrderSkuVo backOrderSkuVo : backOrderSkuVos) {
                GoblinOrderSkuVo orderSkuVo = goblinRedisUtils.getGoblinOrderSkuVo(backOrderSkuVo.getOrderSkuId());
                BigDecimal refundSkuPrice = backOrderSkuVo.getRefundPrice();
                orderSkuVo.setPriceRefund(orderSkuVo.getPriceRefund() == null ? refundSkuPrice : orderSkuVo.getPriceRefund().add(refundSkuPrice));
                if (orderSkuVo.getPriceRefund().compareTo(orderSkuVo.getSkuPriceActual()) >= 0) {
                    orderSkuVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_6.getValue());
                    String pre = GoblinStatusConst.MarketPreStatus.getPre(orderSkuVo.getSkuId());
                    String skuId = orderSkuVo.getSkuId();
                    goblinRedisUtils.incrSkuStock(pre, skuId, orderSkuVo.getNum());
                    goblinRedisUtils.decrSkuCountByUid(orderVo.getUserId(), skuId, orderSkuVo.getNum());
                }
                goblinRedisUtils.setGoblinOrderSku(backOrderSkuVo.getOrderSkuId(), orderSkuVo);
                goblinMongoUtils.updateGoblinOrderSkuVo(backOrderSkuVo.getOrderSkuId(), orderSkuVo);
                sqlsOrderSku.add(new Object[]{
                        orderSkuVo.getPriceRefund(), orderSkuVo.getStatus(), now,
                        backOrderSkuVo.getOrderSkuId(), now, now
                });
                GoblinOrderLogVo logVo = GoblinOrderLogVo.getNew();
                logVo.setOrderId(orderVo.getOrderId());
                logVo.setOrderCode(orderVo.getOrderCode());
                logVo.setPayCode(orderVo.getPayCode());
                if (orderSkuVo.getSkuId().indexOf(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue()) > 0) {
                    logVo.setOrderType("zhengzai");
                } else {
                    logVo.setOrderType("order");
                }
                logVo.setStoreId(orderVo.getStoreId());
                logVo.setSpuId(orderSkuVo.getSpuId());
                logVo.setSpuName(backOrderSkuVo.getSpuName());
                logVo.setSkuId(backOrderSkuVo.getSkuId());
//                if (orderVo.getStatus().equals(GoblinStatusConst.Status.ORDER_STATUS_6.getValue())) {
//                    refundSkuPrice = refundSkuPrice.add(orderVo.getPriceExpress());
//                }
                logVo.setSkuPriceActual(refundSkuPrice.multiply(BigDecimal.valueOf(100)).negate().longValue());
                logVo.setStatus(GoblinStatusConst.Status.ORDER_LOG_STATUS_22.getValue());
                logVo.setRemark("订单退款");
                logVo.setOperationId(backOrderVo.getUserId());
                logVo.setOperationType(GoblinStatusConst.Type.OPERATION_TYPE_2.getValue());
                logVo.setCreatedAt(now);
                goblinMongoUtils.insertGoblinOrderLogVo(logVo);
            }
            //redis
            goblinRedisUtils.setGoblinOrder(orderId, orderVo);
            goblinRedisUtils.setBackOrderVo(backOrderVo.getBackOrderId(), backOrderVo);
            //mongo
            goblinMongoUtils.updateGoblinStoreOrderVo(orderId, orderVo);
            goblinMongoUtils.updateGoblinBackOrderVo(backOrderVo.getBackOrderId(), backOrderVo);
            //mysql
            sqlsOrder.add(new Object[]{
                    orderVo.getPriceRefund(), orderVo.getStatus(), now,
                    orderId, now, now
            });
            sqlsBackOrder.add(new Object[]{
                    backOrderVo.getStatus(), now, now, backOrderVo.getBackOrderId(), now, now
            });
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_STORE_ORDER_OPERA.getKey(),
                    SqlMapping.gets(sqls, sqlsOrder, sqlsOrderSku, sqlsBackOrder));
            //减积分
            goblinOrderUtils.desTask(orderVo.getUserId(), backOrderVo.getRealBackPrice());
        } else if (0 == status) {
            return "fail";
        }
        return "success";
    }
}
