package com.liquidnet.service.goblin.service.impl;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.type.TypeReference;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.adam.dto.vo.AdamAddressesVo;
import com.liquidnet.service.adam.dto.vo.AdamRscPolymer01Vo;
import com.liquidnet.service.base.*;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.goblin.constant.GoblinStatusConst;
import com.liquidnet.service.goblin.dto.manage.GoblinOrderParam;
import com.liquidnet.service.goblin.dto.manage.GoblinOrderSkuParam;
import com.liquidnet.service.goblin.dto.manage.GoblinOrderStoreParam;
import com.liquidnet.service.goblin.dto.vo.*;
import com.liquidnet.service.goblin.param.GoblinOrderPreParam;
import com.liquidnet.service.goblin.param.GoblinOrderSqlParam;
import com.liquidnet.service.goblin.param.PayAgainParam;
import com.liquidnet.service.goblin.param.SyncOrderParam;
import com.liquidnet.service.goblin.entity.GoblinOrderAttr;
import com.liquidnet.service.goblin.entity.GoblinOrderSku;
import com.liquidnet.service.goblin.entity.GoblinStoreOrder;
import com.liquidnet.service.goblin.service.IGoblinOrderService;
import com.liquidnet.service.goblin.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
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 GoblinOrderServiceImpl implements IGoblinOrderService {

    @Autowired
    GoblinRedisUtils redisUtils;
    @Autowired
    GoblinMongoUtils mongoUtils;
    @Autowired
    QueueUtils queueUtils;
    @Autowired
    GoblinOrderUtils orderUtils;

    @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<GoblinPayInnerResultVo> checkOrder(GoblinOrderParam param, String uid) {
        List<String> skuAndPreListAndNumber = CollectionUtil.arrayListString();

        List<GoblinOrderSqlParam> orderSqlParams = ObjectUtil.getGoblinOrderSqlParamArrayListList();

        String orderMasterCode = IDGenerator.storeMasterCode();//总订单id
        GoblinOrderPreParam preParam = GoblinOrderPreParam.getNew();
        preParam.setPayType(param.getPayType());
        preParam.setDeviceFrom(param.getDeviceFrom());
        preParam.setOpenId(param.getOpenId());
        preParam.setReturnUrl(param.getReturnUrl());
        preParam.setShowUrl(param.getShowUrl());
        preParam.setOrderMasterCode(orderMasterCode);
        preParam.setExpireTime(5);
        preParam.setPriceActual(BigDecimal.ZERO);
        preParam.setStoreName("");
        preParam.setSkuName("");
        preParam.setOrderIdList("");
        try {
            List<GoblinOrderStoreParam> goblinOrderStoreParamList = param.getGoblinOrderStoreParamList();//分订单
            //获取用户相关
            String addressId;
            if (param.getAddressIds() == null || param.getAddressIds().size() == 0) {
                addressId = "";
            } else {
                addressId = StringUtils.join(param.getAddressIds(), ",");
            }
            AdamRscPolymer01Vo userVo = null;
            if (noZhengzaiOrder(uid)) {
                userVo = orderUtils.adamAddressEnterMember(uid, null, addressId);
            }
            AdamAddressesVo addressesVo;
            boolean isMember;
            if (userVo == null) {
                isMember = false;
                addressesVo = null;
            } else {
                addressesVo = userVo.getAddressesVo();
                switch (userVo.getMembership()) {
                    case 10:
                    case 11:
                        isMember = true;
                        break;
                    default:
                        isMember = false;
                        break;
                }
            }
            for (GoblinOrderStoreParam storeParam : goblinOrderStoreParamList) {//商铺维度循环
                String orderId = IDGenerator.nextSnowId();
                String orderCode = IDGenerator.storeCode(orderId);
                for (GoblinOrderSkuParam skuParam : storeParam.getGoblinOrderSkuParamArrayList()) {//商品维度循环
                    String skuId = skuParam.getSkuId();
                    int number = skuParam.getNumber();
                    GoblinGoodsSkuInfoVo skuVo = redisUtils.getGoodsSkuInfoVo(skuId);
                    if (!(skuVo.getStatus().equals("3") && skuVo.getShelvesStatus().equals("3"))) {
                        throw new Exception("不可购买");
                    }
                    // 判断库存
                    String pre = GoblinStatusConst.MarketPreStatus.getPre(skuId);
                    int limitCount = skuVo.getBuyLimit() == 0 ? Integer.MAX_VALUE : skuVo.getBuyLimit();
                    int surplusGeneral = redisUtils.decrSkuStock(pre, skuId, number);
                    skuAndPreListAndNumber.add(skuId + "," + pre + "," + number);
                    //判断限购
                    if (noZhengzaiOrder(uid)) {
                        String res1 = orderUtils.judgeOrderLimit(uid, skuId, number, limitCount);
                        if (!res1.equals("")) {
                            throw new Exception("已超出限购数量");
                        }
                    }
                    //库存回滚
                    if (surplusGeneral < 0) {
                        throw new Exception("已售罄");
                    }
                }//GoblinOrderSkuParam
                //下单
                GoblinOrderPreParam pre = order(param, storeParam, uid, isMember, addressesVo, orderMasterCode, orderId, orderCode);
                preParam.setPriceActual(preParam.getPriceActual().add(pre.getPriceActual()));
                preParam.setStoreName(preParam.getStoreName() + "," + pre.getStoreName());
                preParam.setSkuName(preParam.getSkuName() + "," + pre.getSkuName());
                preParam.setOrderIdList(preParam.getOrderIdList() + "," + pre.getOrderIdList());

                GoblinOrderSqlParam sqlParam = GoblinOrderSqlParam.getNew();
                sqlParam.setStoreOrder(pre.getStoreOrder());
                sqlParam.setOrderAttr(pre.getOrderAttr());
                sqlParam.setOrderSkuList(pre.getOrderSkuList());
                orderSqlParams.add(sqlParam);
            }//GoblinOrderStoreParam
            if (preParam.getOrderIdList().equals("")) {
                throw new Exception("参数异常");
            }
            return payOrder(preParam, orderSqlParams, uid);
        } catch (Exception e) {
            log.error("Kylin Order Pay Error = {}", e);
            //回顾限购 回滚库存
            for (String item : skuAndPreListAndNumber) {
                String[] array = item.split(",");
                String skuId = array[0];
                String pre = array[1];
                int number = Integer.parseInt(array[2]);
                redisUtils.incrSkuStock(pre, skuId, number);
                if (noZhengzaiOrder(uid)) {
                    redisUtils.decrSkuCountByUid(uid, skuId, number);
                }
            }
            log.error("回滚库存");
            if (e.getMessage() == null) {
                return ResponseDto.failure(ErrorMapping.get("20018"));//乱七八糟异常
            } else if (e.getMessage().equals("券不可用")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("不可购买")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("参数异常")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("已售罄")) {
                return ResponseDto.failure(e.getMessage());
            } else if (e.getMessage().equals("已超出限购数量")) {
                return ResponseDto.failure(e.getMessage());
            } else {
                return ResponseDto.failure(ErrorMapping.get("20018"));//乱七八糟异常
            }
        }
    }

    private GoblinOrderPreParam order(GoblinOrderParam param, GoblinOrderStoreParam storeParam, String uid, boolean isMember, AdamAddressesVo addressesVo, String orderMasterCode, String orderId, String orderCode) throws Exception {
        String platVoucherCode = storeParam.getPlatVoucherCode();
        String storeId = storeParam.getStoreId();
        Map token = CurrentUtil.getTokenClaims();
        String headerCliSource = CurrentUtil.getHeaderCliSource(), headerCliVersion = CurrentUtil.getHeaderCliVersion();
        String source = headerCliSource == null ? "" : headerCliSource;
        String version = headerCliVersion == null ? "" : headerCliVersion;
        LocalDateTime now = LocalDateTime.now();
        String skuName = "";
        BigDecimal price;//sku应付价格
        BigDecimal priceBase;//sku原价
        BigDecimal storeTotalPrice = BigDecimal.ZERO;//订单总金额
        BigDecimal voucherMarket = BigDecimal.ZERO;//活动优惠金额
        String writeOffCode = ""; //取货码
        List<GoblinOrderSku> goblinOrderSkuList = ObjectUtil.getGoblinOrderSkuArrayList();
        String marketId = "";
        String marketType = "";
        for (GoblinOrderSkuParam skuParam : storeParam.getGoblinOrderSkuParamArrayList()) {
            String pre = GoblinStatusConst.MarketPreStatus.getPre(skuParam.getSkuId());
            GoblinGoodsSkuInfoVo skuVo = redisUtils.getGoodsSkuInfoVo(skuParam.getSkuId());
            GoblinGoodsInfoVo spuVo = redisUtils.getGoodsInfoVo(skuParam.getSpuId());
            marketId = spuVo.getMarketId();
            marketType = pre;
            skuName = skuName.concat(skuVo.getName()).concat(",");
            if (pre != null && pre.equals(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue())) {
                writeOffCode = "EMPTY";
            }
            //获得 商品原价和活动价格
            priceBase = skuVo.getPrice();
            if (isMember) {
                priceBase = skuVo.getPriceMember();
            }
            if (pre != null) {
                GoblinGoodsSkuInfoVo skuMarketVo = redisUtils.getGoodsSkuInfoVo(skuParam.getSkuId().split(pre)[0]);
                price = skuMarketVo.getPrice();
                if (isMember) {
                    price = skuMarketVo.getPriceMember();
                }
            } else {
                price = skuVo.getPrice();
                if (isMember) {
                    price = skuVo.getPriceMember();
                }
            }
            //获得活动优惠价格
            priceBase = priceBase.multiply(BigDecimal.valueOf(skuParam.getNumber()));
            price = price.subtract(BigDecimal.valueOf(skuParam.getNumber()));
            voucherMarket = voucherMarket.add(priceBase.subtract(price));
            storeTotalPrice = storeTotalPrice.add(price);
            //订单sku
            GoblinOrderSku orderSku = GoblinOrderSku.getNew();
            orderSku.setOrderSkuId(IDGenerator.nextTimeId2());
            orderSku.setOrderId(orderId);
            orderSku.setStatus(GoblinStatusConst.Status.ORDER_STATUS_0.getValue());
            orderSku.setSpuId(skuParam.getSpuId());
            orderSku.setSpuName(spuVo.getName());
            orderSku.setSkuId(skuParam.getSkuId());
            orderSku.setNum(skuParam.getNumber());
            orderSku.setSkuPrice(priceBase);
            orderSku.setSkuPriceActual(price);
            orderSku.setSkuName(skuVo.getName());
            orderSku.setSkuNo(skuVo.getSkuNo());
            orderSku.setSkuImage(skuVo.getSkuPic());
            orderSku.setSkuSpecs(JSON.toJSONString(skuVo.getSkuSpecList()));
            orderSku.setPriceVoucher(priceBase.subtract(price));
            orderSku.setCreatedAt(now);
            orderSku.setSpuName(spuVo.getName());
            orderSku.setSpuPic(spuVo.getCoverPic());
            goblinOrderSkuList.add(orderSku);
        }
        //优惠券
        BigDecimal voucherPrice = BigDecimal.ZERO;
        if (platVoucherCode != null && !platVoucherCode.equals("")) {
            HashMap<String, Object> hashMap = orderUtils.useCoupon(platVoucherCode, "购买商品[" + orderCode + "]", storeTotalPrice, "");//todo
            voucherPrice = (BigDecimal) hashMap.get("voucher");
            Integer typeVoucher = (Integer) hashMap.get("type");
            if (typeVoucher.equals(-1)) {
                throw new Exception("券不可用");
            }
        }
        GoblinStoreInfoVo storeInfoVo = redisUtils.getStoreInfoVo(storeId);
        //生成订单
        GoblinStoreOrder storeOrder = GoblinStoreOrder.getNew();
        storeOrder.setMasterOrderCode(orderMasterCode);
        storeOrder.setOrderId(orderId);
        storeOrder.setStoreId(storeId);
        storeOrder.setStoreName(storeInfoVo.getStoreName());
        storeOrder.setOrderCode(orderCode);
        storeOrder.setUserId(uid);
        storeOrder.setUserName(StringUtils.defaultString(((String) token.get("nickname")), ""));
        storeOrder.setUserMobile(StringUtils.defaultString(((String) token.get("mobile")), ""));
        storeOrder.setPriceTotal(storeTotalPrice);
        if (addressesVo == null) {
            storeOrder.setPriceExpress(BigDecimal.ZERO);
        } else {
            storeOrder.setPriceExpress(BigDecimal.ZERO);
        }
        storeOrder.setPriceActual(storeOrder.getPriceTotal().add(storeOrder.getPriceExpress()).add(voucherMarket).subtract(voucherPrice));
        storeOrder.setPriceRefund(BigDecimal.ZERO);
        storeOrder.setPriceCoupon(voucherPrice);
        storeOrder.setPriceVoucher(voucherMarket.add(voucherPrice));
        storeOrder.setStatus(0);
        storeOrder.setUcouponId(platVoucherCode);
        storeOrder.setPayType(param.getPayType());
        storeOrder.setDeviceFrom(param.getDeviceFrom());
        storeOrder.setSource(source);
        storeOrder.setVersion(version);
        storeOrder.setIsMember(isMember ? 1 : 0);
        storeOrder.setOrderType(0);
        storeOrder.setWriteOffCode(writeOffCode);
        storeOrder.setPayCountdownMinute(5);
        storeOrder.setIpAddress(CurrentUtil.getCliIpAddr());
        storeOrder.setCreatedAt(now);
        storeOrder.setMarketId(marketId);
        storeOrder.setMarketType(marketType);

        //订单attr
        GoblinOrderAttr orderAttr = GoblinOrderAttr.getNew();
        orderAttr.setOrderAttrId(IDGenerator.nextTimeId2());
        orderAttr.setOrderId(orderId);
        if (!writeOffCode.equals("EMPTY")) {
            orderAttr.setExpressContacts(addressesVo.getName());
            orderAttr.setExpressAddress(addressesVo.getProvince() + "," + addressesVo.getCounty() + "," + addressesVo.getCity());
            orderAttr.setExpressAddressDetail(addressesVo.getAddress());
            orderAttr.setExpressPhone(addressesVo.getPhone());
            orderAttr.setExpressType(1);
            orderAttr.setCreatedAt(now);
        }
        //返回值
        GoblinOrderPreParam preParam = GoblinOrderPreParam.getNew();
        preParam.setPriceActual(storeOrder.getPriceActual());
        preParam.setStoreName(storeInfoVo.getStoreName());
        preParam.setSkuName(skuName);
        preParam.setOrderIdList(storeOrder.getOrderId());
        preParam.setStoreOrder(storeOrder);
        preParam.setOrderAttr(orderAttr);
        preParam.setOrderSkuList(goblinOrderSkuList);
        return preParam;
    }

    private ResponseDto<GoblinPayInnerResultVo> payOrder(GoblinOrderPreParam preParam, List<GoblinOrderSqlParam> sqlParams, String uid) {
        //是否免费
        boolean isFree = false;
        GoblinPayInnerResultVo payInnerResultVo;
        String payCode;
        if (preParam.getPriceActual().compareTo(BigDecimal.valueOf(0)) > 0 && !preParam.getPayType().equals("huifu")) {
            // 调用支付
            LinkedMultiValueMap<String, String> httpData = CollectionUtil.linkedMultiValueMapStringString();
            httpData.add("type", "PRODUCT");
            httpData.add("price", preParam.getPriceActual().toString());
//            httpData.add("price","0.01");
            httpData.add("name", preParam.getStoreName());
            httpData.add("detail", preParam.getSkuName());
            httpData.add("orderCode", preParam.getOrderMasterCode());
            httpData.add("orderId", preParam.getOrderIdList().substring(1));
            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", preParam.getExpireTime() + "");
            httpData.add("payType", preParam.getPayType());
            httpData.add("deviceFrom", preParam.getDeviceFrom());
            if (preParam.getDeviceFrom().equals("js") || preParam.getDeviceFrom().equals("applet")) {
                httpData.add("openId", preParam.getOpenId());
            }
            if (preParam.getPayType().equals("alipay") && preParam.getDeviceFrom().equals("wap")) {
                httpData.add("showUrl", preParam.getShowUrl() + preParam.getOrderMasterCode());
                httpData.add("returnUrl", preParam.getReturnUrl());
            }
            if (preParam.getPayType().equals("douyinpay")) {
                httpData.add("showUrl", preParam.getShowUrl() + preParam.getOrderMasterCode());
                httpData.add("returnUrl", preParam.getReturnUrl());
            }
            if (preParam.getPayType().equals("unionpay")) {
                httpData.add("returnUrl", preParam.getReturnUrl());
            }
            String returnData = HttpUtil.post(payUrl, httpData);
            log.info("调用 DRAGON 结果 = " + returnData);
            ResponseDto<GoblinPayInnerResultVo> dto = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<GoblinPayInnerResultVo>>() {
            });
            payInnerResultVo = GoblinPayInnerResultVo.getNew();
            payInnerResultVo.setCode(dto.getData().getCode());
            payInnerResultVo.setOrderCode(dto.getData().getOrderCode());
            payInnerResultVo.setPayData(dto.getData().getPayData());
            payInnerResultVo.setPayType(preParam.getPayType());
            payInnerResultVo.setPrice(preParam.getPriceActual());
            payCode = payInnerResultVo.getCode();
            payInnerResultVo.setShowUrl(preParam.getShowUrl());
            payInnerResultVo.setReturnUrl(preParam.getReturnUrl());
        } else if (preParam.getPayType().equals("huifu")) {
            isFree = true;
            preParam.setPayType("huifu");
            payCode = "HUIFU_PAY_CODE";
            payInnerResultVo = GoblinPayInnerResultVo.getNew();
            payInnerResultVo.setPrice(preParam.getPriceActual());
            payInnerResultVo.setPayType(preParam.getPayType());
        } else {
            isFree = true;
            preParam.setPayType("FREE");
            payCode = "FREE_PAY_CODE";
            payInnerResultVo = GoblinPayInnerResultVo.getNew();
            payInnerResultVo.setPrice(BigDecimal.valueOf(0));
            payInnerResultVo.setPayType(preParam.getPayType());
        }
        payInnerResultVo.setOrderMasterCode(preParam.getOrderMasterCode());

        LinkedList<String> sqls = CollectionUtil.linkedListString();
        sqls.add(SqlMapping.get("goblin.order.create.sku_insert"));
        sqls.add(SqlMapping.get("goblin.order.create.order_insert"));
        sqls.add(SqlMapping.get("goblin.order.create.attr_insert"));
        for (GoblinOrderSqlParam item : sqlParams) {
            List<String> goblinOrderSkuIdList = CollectionUtil.linkedListString();
            LinkedList<Object[]> sqlDataSku = CollectionUtil.linkedListObjectArr();
            LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();
            LinkedList<Object[]> sqlDataAttr = CollectionUtil.linkedListObjectArr();
            for (GoblinOrderSku orderSku : item.getOrderSkuList()) {
                sqlDataSku.add(new Object[]{
                        orderSku.getOrderSkuId(), orderSku.getOrderId(), orderSku.getSpuId(), orderSku.getSpuName(), orderSku.getSpuPic(), orderSku.getSkuId(), orderSku.getNum(), orderSku.getSkuPrice(), orderSku.getSkuPriceActual(), orderSku.getSkuName(),
                        orderSku.getSkuNo(), orderSku.getSkuImage(), orderSku.getSkuSpecs(), orderSku.getPriceVoucher(), orderSku.getCreatedAt()
                });
                //订单 orderSku Vo
                GoblinOrderSkuVo orderSkuVo = GoblinOrderSkuVo.getNew();
                BeanUtils.copyProperties(orderSku, orderSkuVo);
                redisUtils.setGoblinOrderSku(orderSkuVo.getOrderSkuId(), orderSkuVo);
                mongoUtils.insertGoblinOrderSkuVo(orderSkuVo);
                goblinOrderSkuIdList.add(orderSkuVo.getOrderSkuId());
            }
            GoblinStoreOrder storeOrder = item.getStoreOrder();
            sqlDataOrder.add(new Object[]{
                    storeOrder.getMasterOrderCode(), storeOrder.getOrderId(), storeOrder.getStoreId(), storeOrder.getStoreName(), storeOrder.getOrderCode(), storeOrder.getUserId(), storeOrder.getUserName(), storeOrder.getUserMobile(), storeOrder.getPriceTotal(),
                    storeOrder.getPriceActual(), storeOrder.getPriceRefund(), storeOrder.getPriceExpress(), storeOrder.getPriceCoupon(), storeOrder.getPriceVoucher(), storeOrder.getStatus(), storeOrder.getUcouponId(), storeOrder.getPayType(), storeOrder.getDeviceFrom(),
                    storeOrder.getSource(), storeOrder.getVersion(), storeOrder.getIsMember(), storeOrder.getOrderType(), storeOrder.getWriteOffCode(), storeOrder.getPayCountdownMinute(), storeOrder.getIpAddress(), storeOrder.getPayCode(), storeOrder.getMarketId(), storeOrder.getMarketType(), storeOrder.getCreatedAt()
            });
            GoblinOrderAttr orderAttr = item.getOrderAttr();
            sqlDataAttr.add(new Object[]{
                    orderAttr.getOrderAttrId(), orderAttr.getOrderId(), orderAttr.getExpressContacts(), orderAttr.getExpressAddress(), orderAttr.getExpressAddressDetail(), orderAttr.getExpressPhone(), orderAttr.getExpressType(), orderAttr.getCreatedAt()
            });

            //订单vo
            GoblinStoreOrderVo orderVo = GoblinStoreOrderVo.getNew();
            BeanUtils.copyProperties(storeOrder, orderVo);
            //订单attr vo
            GoblinOrderAttrVo orderAttrVo = GoblinOrderAttrVo.getNew();
            BeanUtils.copyProperties(orderAttr, orderAttrVo);
            //redis 赋值
            orderVo.setOrderAttrVo(orderAttrVo);
            orderVo.setOrderSkuVoIds(goblinOrderSkuIdList);
            redisUtils.setGoblinOrder(orderVo.getOrderId(), orderVo);
            redisUtils.setMasterCode(preParam.getOrderMasterCode(), preParam.getOrderIdList().substring(1));
            mongoUtils.insertGoblinStoreOrderVo(orderVo);
            //redis 添加未支付列表
            redisUtils.addUnPayOrder(orderVo.getOrderId());
            //redis 订单列表
            if (noZhengzaiOrder(uid)) {
                if (orderVo.getMarketType()==null) {
                    redisUtils.addOrderList(uid, orderVo.getOrderId());
                } else if(orderVo.getMarketType().equals(GoblinStatusConst.MarketPreStatus.MARKET_PRE_ZHENGZAI.getValue())){
                    redisUtils.addZhengzaiOrderList(uid, orderVo.getOrderId());
                }
            }
            //mysql  执行sql
            String sqlData = SqlMapping.gets(sqls, sqlDataSku, sqlDataOrder, sqlDataAttr);
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_CREATE_PAY.getKey(), sqlData);
        }
        log.info(UserPathDto.setData("下单(唤起支付)", preParam, payInnerResultVo));
        if (isFree && preParam.getPayType().equals("huifu")) {
            return ResponseDto.success(payInnerResultVo);
        } else if (isFree) {
            SyncOrderParam syncOrderParam = SyncOrderParam.getNew();
            syncOrderParam.setOrderCode(preParam.getOrderMasterCode());
            syncOrderParam.setPaymentAt(DateUtil.format(LocalDateTime.now(), DateUtil.Formatter.yyyyMMddHHmmss));
            syncOrderParam.setCode(payCode);
            syncOrderParam.setPrice(preParam.getPriceActual());
            syncOrderParam.setPaymentId("FREE_PAYMENT_ID");
            syncOrderParam.setPaymentType(null);
            syncOrderParam.setStatus(1);
            syncOrder(syncOrderParam);
            return ResponseDto.success(payInnerResultVo);
        } else {
            return ResponseDto.success(payInnerResultVo);
        }
    }

    @Override
    public ResponseDto<GoblinPayInnerResultVo> payAgain(PayAgainParam param) {
        String uid = CurrentUtil.getCurrentUid();
        LocalDateTime now = LocalDateTime.now();
        //检查订单时间 是否关闭
        GoblinStoreOrderVo storeOrderVo = redisUtils.getGoblinOrder(param.getOrderId());
        if (!storeOrderVo.getUserId().equals(uid)) {
            return ResponseDto.failure("无权查看");
        }
        if (storeOrderVo == null) {
            return ResponseDto.failure("订单不存在");
        }

        if (storeOrderVo.getStatus() != GoblinStatusConst.Status.ORDER_STATUS_0.getValue()) {
            return ResponseDto.failure("订单无法支付");//订单
        }
        String returnCheckData = HttpUtil.get(checkUrl + "?code=" + storeOrderVo.getPayCode(), null);
        ResponseDto<GoblinPayInnerResultVo> checkVo = JsonUtils.fromJson(returnCheckData, new TypeReference<ResponseDto<GoblinPayInnerResultVo>>() {
        });
        if (checkVo.getData().getStatus() == 1) {
            return ResponseDto.failure("订单已支付");
        }
        GoblinPayInnerResultVo payInnerResultVo = GoblinPayInnerResultVo.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", storeOrderVo.getPriceActual().toString());
            httpData.add("name", redisUtils.getStoreInfoVo(storeOrderVo.getStoreId()).getStoreName());
            httpData.add("detail", "查找最初订单");
            httpData.add("orderCode", storeOrderVo.getOrderCode());
//            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", storeOrderVo.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.getOrderId());
                httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getOrderId());
            }
            if (param.getPayType().equals("douyinpay")) {
                httpData.add("showUrl", param.getShowUrl() + storeOrderVo.getOrderId());
                httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getOrderId());
            }
            if (param.getPayType().equals("unionpay")) {
                httpData.add("returnUrl", param.getReturnUrl() + storeOrderVo.getOrderId());
            }
            String returnData = HttpUtil.post(payUrl, httpData);
            log.info("调用 DRAGON 结果 = " + returnData);
            ResponseDto<GoblinPayInnerResultVo> dto = JsonUtils.fromJson(returnData, new TypeReference<ResponseDto<GoblinPayInnerResultVo>>() {
            });
            payInnerResultVo.setCode(dto.getData().getCode());
            payInnerResultVo.setOrderCode(dto.getData().getOrderCode());
            payInnerResultVo.setPayData(dto.getData().getPayData());
            payInnerResultVo.setOrderId(storeOrderVo.getOrderId());
            payInnerResultVo.setPayType(storeOrderVo.getPayType());
            payInnerResultVo.setPrice(storeOrderVo.getPriceActual());
            storeOrderVo.setPayCode(payInnerResultVo.getCode());
            payInnerResultVo.setShowUrl(param.getShowUrl() + storeOrderVo.getOrderId());
            payInnerResultVo.setReturnUrl(param.getReturnUrl() + storeOrderVo.getOrderId());
            //mysql
            queueUtils.sendMsgByRedis(MQConst.GoblinQueue.GOBLIN_ORDER_AGAIN.getKey(),
                    SqlMapping.get("goblin_order.pay.again", param.getPayType(), param.getDeviceFrom(), payInnerResultVo.getCode(), param.getOrderId(), now, now));
            log.info(UserPathDto.setData("再次支付[新支付方式]", param, payInnerResultVo));
        }
        return ResponseDto.success(payInnerResultVo);
    }

    @Override
    public String syncOrder(SyncOrderParam syncOrderParam) {
        log.debug("SYNC PARAM = " + syncOrderParam.toString());
        //支付时间
        LocalDateTime now = LocalDateTime.now();
        String[] array = redisUtils.getMasterCode(syncOrderParam.getOrderCode());
        String uid = "0";
        BigDecimal priceActual = BigDecimal.ZERO;
        for (String orderId : array) {
            GoblinStoreOrderVo orderVo = redisUtils.getGoblinOrder(orderId);
            priceActual = priceActual.add(orderVo.getPriceActual());
            uid = orderVo.getUserId();
            if (orderVo == null) {
                log.error("订单号：" + syncOrderParam.getOrderCode() + " 订单不存在");
                return "fail";//订单不存在
            }
            if (orderVo.getStatus() != GoblinStatusConst.Status.ORDER_STATUS_0.getValue()) {
                if (orderVo.getPayCode().equals(syncOrderParam.getCode())) {
                    log.error("订单号：" + syncOrderParam.getOrderCode() + " 重复支付");
                    return "fail";//重复支付
                }
            }
//            if (orderVo.getPriceActual().compareTo(syncOrderParam.getPrice()) != 0) {
//                log.error("订单号：" + syncOrderParam.getOrderCode() + " 价格不符");
//                return "fail";//价格不符
//            }
            LinkedList<String> sqls = CollectionUtil.linkedListString();
            LinkedList<Object[]> sqlDataOrder = CollectionUtil.linkedListObjectArr();
            LinkedList<Object[]> sqlDataSku = CollectionUtil.linkedListObjectArr();
            GoblinStoreOrder storeOrder = GoblinStoreOrder.getNew();
            if (orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_5.getValue() && syncOrderParam.getStatus().equals(1)) {
                log.error("订单号为 {} 的订单超时支付", syncOrderParam.getOrderCode());
                // todo hujiachen 操作超时支付
//                orderVo.setStatus(GoblinStatusConst.OrderStatus.ORDER_STATUS_61.getValue());
//                redisUtils.setGoblinOrder(orderVo.getOrderId(),orderVo);
            } else if ((orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_6.getValue() || orderVo.getStatus() == GoblinStatusConst.Status.ORDER_STATUS_7.getValue()) && syncOrderParam.getStatus().equals(1)) {
                log.error("订单号为 {} 的订单正在退款 或者已退款", syncOrderParam.getOrderCode());
            } else if (syncOrderParam.getStatus().equals(1)) {
                log.error("订单号为 {} 的订单正常流程", syncOrderParam.getOrderCode());
                storeOrder.setPaymentType(syncOrderParam.getPaymentType());
                storeOrder.setPaymentId(syncOrderParam.getPaymentId());
                storeOrder.setPayCode(syncOrderParam.getCode());
                LocalDateTime payTime = LocalDateTime.parse(syncOrderParam.getPaymentAt(), DTF_YMD_HMS);
                storeOrder.setPayTime(payTime);
                if (orderVo.getWriteOffCode().equals("EMPTY")) {
                    storeOrder.setWriteOffCode(IDGenerator.getWriteOffCode());
                } else {
                    storeOrder.setWriteOffCode("");
                }
                storeOrder.setStatus(GoblinStatusConst.Status.ORDER_STATUS_2.getValue());
                storeOrder.setUpdatedAt(now);
                sqls.add(SqlMapping.get("goblin_order.pay.order"));
                sqlDataOrder.add(new Object[]{
                        storeOrder.getPaymentType(), storeOrder.getPaymentId(), storeOrder.getPayCode(), storeOrder.getPayTime(), storeOrder.getWriteOffCode(), storeOrder.getStatus(), storeOrder.getUpdatedAt(),
                        orderId, now, now
                });
                sqls.add(SqlMapping.get("goblin_order.pay.sku"));
                List<String> skuList = orderVo.getOrderSkuVoIds();
                for (String orderSkuVoIds : skuList) {
                    GoblinOrderSkuVo orderSkuVo = redisUtils.getGoblinOrderSkuVo(orderSkuVoIds);
                    //增加销量
                    redisUtils.incrSkuSaleCount(orderSkuVo.getSpuId(), orderSkuVo.getSkuId(), orderSkuVo.getNum());
                    orderSkuVo.setStatus(GoblinStatusConst.Status.ORDER_STATUS_2.getValue());
                    //redis
                    redisUtils.setGoblinOrderSku(orderSkuVo.getOrderSkuId(), orderSkuVo);
                    //mongo
                    mongoUtils.updateGoblinOrderSkuVo(orderSkuVo.getOrderSkuId(), orderSkuVo);
                    //mongo 添加操作日志
                    GoblinOrderLogVo logVo = GoblinOrderLogVo.getNew();
                    logVo.setOrderId(orderVo.getOrderId());
                    logVo.setOrderCode(orderVo.getOrderCode());
                    logVo.setPayCode(orderVo.getPayCode());
                    logVo.setStoreId(orderVo.getStoreId());
                    if (orderSkuVo.getSkuId().indexOf(GoblinStatusConst.MarketPreStatus.MARKET_PRE_PURCHASE.getValue()) > 0) {
                        logVo.setOrderType("zhengzai");
                    } else {
                        logVo.setOrderType("order");
                    }
                    logVo.setSpuId(orderSkuVo.getSpuId());
                    logVo.setSkuId(orderSkuVo.getSkuId());
                    logVo.setSkuPriceActual(orderSkuVo.getSkuPriceActual().multiply(new BigDecimal(100)).longValue());
                    logVo.setStatus(GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getValue());
                    logVo.setRemark(GoblinStatusConst.Status.ORDER_LOG_STATUS_11.getDesc());
                    logVo.setOperationId(uid);
                    logVo.setOperationName(orderVo.getUserName());
                    logVo.setOperationType(GoblinStatusConst.Type.OPERATION_TYPE_1.getValue());
                    logVo.setCreatedAt(LocalDateTime.now());
                    mongoUtils.insertGoblinOrderLogVo(logVo);
                    //mysql
                    sqlDataSku.add(new Object[]{
                            GoblinStatusConst.Status.ORDER_STATUS_2.getValue(), now,
                            orderSkuVo.getOrderSkuId(), now, now
                    });
                }
                //redis
                orderVo.setPayCode(storeOrder.getPayCode());
                orderVo.setPayTime(syncOrderParam.getPaymentAt());
                orderVo.setWriteOffCode(storeOrder.getWriteOffCode());
                orderVo.setStatus(storeOrder.getStatus());
                orderVo.setPaymentId(syncOrderParam.getPaymentId());
                orderVo.setPaymentType(syncOrderParam.getPaymentType());
                orderVo.setOrderSkuVoIds(skuList);
                redisUtils.setGoblinOrder(orderId, orderVo);
                redisUtils.setOffCode(orderVo.getMasterOrderCode(), orderVo.getWriteOffCode());
                //删除未支付订单
                redisUtils.removeGoblinOrder(null, orderId);
                //mongo
                mongoUtils.updateGoblinStoreOrderVo(orderId, orderVo);
                //mysql
                queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_ORDER_CREATE.getKey(),
                        SqlMapping.gets(sqls, sqlDataOrder, sqlDataSku));
            }
            //发短信
//            SmsEnum.ADTemplate adTemplate = null;
//            if (orderTicketData.getGetTicketType().equals("express")) {
//                adTemplate = SmsEnum.ADTemplate.SMS_225995308;
//            } else if (orderTicketData.getGetTicketType().equals("electronic")) {
//                adTemplate = ticketData.getIsShowCode() == 1 ? SmsEnum.ADTemplate.SMS_225995308 : SmsEnum.ADTemplate.SMS_225995308;
//            }
//
//            if (null != adTemplate) {
//                queueUtils.sendMsgByRedis(MQConst.KylinQueue.SMS_NOTICE.getKey(),
//                        SmsMessage.builder().setPhone(orderTicketData.getUserMobile())
//                                .setSignName(SmsEnum.ADSignName.M02.getVal())
//                                .setTemplateCode(adTemplate.name())
//                                .setTemplateParam("name", orderTicketData.getPerformanceTitle())
//                                .setTemplateParam("time", time1 + " " + time2).toJson()
//                );
//            }
            //加分
            if (noZhengzaiOrder(uid)) {
                orderUtils.doTask(uid, priceActual);
            }
        }
        return "success";
    }

    @Override
    public ResponseDto<Integer> checkOrderResult(String orderId) {
        String uid = CurrentUtil.getCurrentUid();
        GoblinStoreOrderVo storeOrderVo = redisUtils.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<SyncOrderParam> syncOrderDtoParam = JsonUtils.fromJson(returnCheckData, new TypeReference<ResponseDto<SyncOrderParam>>() {
            });
            if (syncOrderDtoParam.getData().getStatus() == 1) {
                //处理订单
                syncOrder(syncOrderDtoParam.getData());
                return ResponseDto.success(1);
            } else {
                return ResponseDto.success(0);
            }
        }
    }

    @Override
    public ResponseDto<Integer> checkOrderResultMaterCode(String masterCode) {
        String[] orderIds = redisUtils.getMasterCode(masterCode);
        if (orderIds == null) {
            return ResponseDto.failure("订单不存在");
        } else {
            for (String orderId : orderIds) {
                GoblinStoreOrderVo storeOrderVo = redisUtils.getGoblinOrder(orderId);
                String returnCheckData = HttpUtil.get(checkUrl + "?code=" + storeOrderVo.getPayCode(), null);
                ResponseDto<SyncOrderParam> syncOrderDtoParam = JsonUtils.fromJson(returnCheckData, new TypeReference<ResponseDto<SyncOrderParam>>() {
                });
                if (syncOrderDtoParam.getData().getStatus() == 1) {
                    //处理订单
                    syncOrder(syncOrderDtoParam.getData());
                } else {
                    return ResponseDto.success(0);
                }
            }
            return ResponseDto.success(1);
        }
    }

    private boolean noZhengzaiOrder(String uid) {
        return !uid.equals("zhengzai");
    }
}
