package com.liquidnet.service.kylin.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.common.cache.redisson.util.RedisLockUtil;
import com.liquidnet.common.mq.constant.MQConst;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.adam.dto.vo.AdamAddressesVo;
import com.liquidnet.service.adam.dto.vo.AdamEntersVo;
import com.liquidnet.service.base.ErrorMapping;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.base.SqlMapping;
import com.liquidnet.service.feign.adam.api.FeignAdamBaseClient;
import com.liquidnet.service.kylin.constant.KylinRedisConst;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dao.OrderScriptDto;
import com.liquidnet.service.kylin.dto.dao.UserPathDao;
import com.liquidnet.service.kylin.dto.param.PayAgainParam;
import com.liquidnet.service.kylin.dto.param.PayOrderParam;
import com.liquidnet.service.kylin.dto.param.SyncOrderParam;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketTimesVo;
import com.liquidnet.service.kylin.dto.vo.middle.KylinTicketVo;
import com.liquidnet.service.kylin.dto.vo.middle.message.MessageConfigVo;
import com.liquidnet.service.kylin.dto.vo.middle.message.MessageDataVo;
import com.liquidnet.service.kylin.dto.vo.mongo.*;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderListVo;
import com.liquidnet.service.kylin.dto.vo.returns.OrderDetailsVo;
import com.liquidnet.service.kylin.dto.vo.returns.PayResultVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketEntitiesMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketsMapper;
import com.liquidnet.service.kylin.service.IKylinOrderRefundsService;
import com.liquidnet.service.kylin.service.IKylinOrderTicketsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liquidnet.service.kylin.utils.*;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import com.taobao.api.TaobaoClient;
import com.taobao.api.request.AlibabaDamaiMevOpenBatchpushticketRequest;
import com.taobao.api.response.AlibabaDamaiMevOpenBatchpushticketResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.bson.Document;
import org.redisson.api.RLock;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
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.*;


/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author liquidnet
 * @since 2021-05-20
 */
@Service
@Slf4j
public class KylinOrderTicketsServiceImpl extends ServiceImpl<KylinOrderTicketsMapper, KylinOrderTickets> implements IKylinOrderTicketsService {

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

    @Autowired
    private Environment environment;
    @Autowired
    private DataUtils dataUtils;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private OrderUtils orderUtils;
    @Autowired
    private OtherUtils otherUtils;
    @Autowired
    private RedisLockUtil redisLockUtil;
    @Autowired
    private MongoVoUtils mongoVoUtils;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private MongoConverter mongoConverter;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private TaobaoTicketUtils taobaoTicketUtils;
    @Autowired
    private KylinOrderTicketsMapper orderTicketsMapper;
    @Autowired
    private OrderRefundsCallbackServiceImpl orderRefundsCallbackService;

    ArrayList<Integer> canBuyStatus = new ArrayList() {{
        add(6);
        add(8);
        add(9);
        add(10);
    }};


    @Override
    public ResponseDto<PayResultVo> checkCanOrder(PayOrderParam payOrderParam) {
        Long currentTime;
        boolean isDownGeneral = false;
        String uid = CurrentUtil.getCurrentUid();
        String lock = "userId:" + uid;
        if (!redisLockUtil.tryLock(lock, 1, 5)) {
            return ResponseDto.failure("请求频繁");//参数错误
        }
        try {
            currentTime = System.currentTimeMillis();
            KylinPerformanceVo performanceData = dataUtils.getPerformanceVo(payOrderParam.getPerformanceId());
            currentTime = System.currentTimeMillis() - currentTime;
            log.debug("redis 获取演出详情 -> time:" + currentTime + "毫秒");
            KylinTicketTimesVo ticketTimesData = null;
            KylinTicketVo ticketData = null;
            for (int x = 0; x < performanceData.getTicketTimeList().size(); x++) {
                KylinTicketTimesVo timeItem = performanceData.getTicketTimeList().get(x);
                if (timeItem.getTimeId().equals(payOrderParam.getTimeId())) {
                    ticketTimesData = timeItem;
                    for (int y = 0; y < ticketTimesData.getTicketList().size(); y++) {
                        KylinTicketVo ticketItem = ticketTimesData.getTicketList().get(y);
                        if (ticketItem.getTicketsId().equals(payOrderParam.getTicketId())) {
                            ticketData = ticketItem;
                            break;
                        }
                    }
                    break;
                }
            }

            if (performanceData == null || ticketTimesData == null || ticketData == null) {
                redisLockUtil.unlock(lock);
                return ResponseDto.failure(ErrorMapping.get("20004"));//参数错误
            }
            if (!ticketData.getTimeId().equals(payOrderParam.getTimeId()) || !ticketTimesData.getPerformanceId().equals(payOrderParam.getPerformanceId())) {
                redisLockUtil.unlock(lock);
                return ResponseDto.failure(ErrorMapping.get("20004"));//参数错误
            }
            if (payOrderParam.getNumber() % ticketData.getCounts() != 0) {
                redisLockUtil.unlock(lock);
                return ResponseDto.failure(ErrorMapping.get("20007"));//数量错误
            }
            //判断代理
            if (!checkAgent(payOrderParam.getAgentId(), ticketData)) {
                redisLockUtil.unlock(lock);
                return ResponseDto.failure(ErrorMapping.get("20008"));//无权购买
            }

            Integer isStudent = ticketData.getIsStudent();
            //会员时间获取
            String memberTimeStart = ticketData.getMemberTimeStart(); // 会员开售时间
            String timeStart = ticketData.getTimeStart(); // 普通开售时间
            String timeEnd = ticketData.getTimeEnd(); // 购票停售时间
            String timeExpressEnd = ticketData.getTimeEndExpress(); // 快递停售时间
            currentTime = System.currentTimeMillis();
            boolean isMember = orderUtils.isMember(uid);//feignAdamBaseClient.isMember(uid).getData();//获取是否是会员
            currentTime = System.currentTimeMillis() - currentTime;
            log.debug("fegin 会员 -> time:" + (currentTime) + "毫秒");
            int memberType; //会员状态 不需要判断会员 1判断会员逻辑 2会员专属
            if (ticketData.getIsExclusive() == 1) {
                memberType = 2;
                if (!isMember) {
                    redisLockUtil.unlock(lock);
                    return ResponseDto.failure(ErrorMapping.get("20009"));//没有会员权限
                }
            } else {
                if (DateUtil.compareStrDay(DateUtil.getNowTime(), memberTimeStart) == 1 && DateUtil.compareStrDay(DateUtil.getNowTime(), timeStart) == -1 && ticketData.getIsMember() == 1) {
                    // 会员购买逻辑
                    memberType = 1;
                    if (!isMember) {
                        redisLockUtil.unlock(lock);
                        return ResponseDto.failure(ErrorMapping.get("20009"));//没有会员权限
                    }
                } else {
                    // 普通用户购买逻辑
                    memberType = 0;
                }
            }

            // 获取限购 实名
            int ticketLimit = ticketData.getLimitCount();//普通票种限购
            int ticketMemberLimit = ticketData.getLimitCountMember();//会员票种限购
            int performanceLimit = performanceData.getLimitCount();//普通演出限购
            int performanceMemberLimit = performanceData.getLimitCountMember();//会员演出限购
            int isTrueName = ticketData.getIsTrueName();//是否演出实名

            if (!canBuyStatus.contains(performanceData.getAppStatus())) {
                return ResponseDto.failure(ErrorMapping.get("20010"));//当前不可购买
            }

            if (!canBuyStatus.contains(performanceData.getAppStatus())) {
                return ResponseDto.failure(ErrorMapping.get("20010"));//当前不可购买
            }

            //通用判断时间
            if (isMember) {
                if (DateUtil.compareStrDay(DateUtil.getNowTime(), memberTimeStart) == -1) {
                    redisLockUtil.unlock(lock);
                    return ResponseDto.failure(ErrorMapping.get("20011"));//未开始
                }
            } else {
                if (DateUtil.compareStrDay(DateUtil.getNowTime(), timeStart) == -1) {
                    redisLockUtil.unlock(lock);
                    return ResponseDto.failure(ErrorMapping.get("20011"));//未开始
                }
            }
            if (DateUtil.compareStrDay(DateUtil.getNowTime(), timeEnd) == 1) {
                redisLockUtil.unlock(lock);
                return ResponseDto.failure(ErrorMapping.get("20012"));//已结束
            }

            //快递票判断
            if (payOrderParam.getIsExpress() != null) {
                if (payOrderParam.getIsExpress() == 1 && DateUtil.compareStrDay(DateUtil.getNowTime(), timeExpressEnd) == 1) {
                    redisLockUtil.unlock(lock);
                    return ResponseDto.failure(ErrorMapping.get("20013"));//快递票不卖
                }
                if (payOrderParam.getIsExpress() == 1 && payOrderParam.getAddressId().isEmpty()) {
                    redisLockUtil.unlock(lock);
                    return ResponseDto.failure(ErrorMapping.get("20014"));//快递票未填写收货地址
                }
            }
            //实名判断
            if (isTrueName == 1 && payOrderParam.getEnterIdList().size() <= 0) {
                redisLockUtil.unlock(lock);
                return ResponseDto.failure(ErrorMapping.get("20015"));//需要实名 未实名
            }
            if (isTrueName == 1 && payOrderParam.getEnterIdList().size() != payOrderParam.getNumber()) {
                redisLockUtil.unlock(lock);
                return ResponseDto.failure(ErrorMapping.get("20015"));//入场人数量错误
            }

            // 判断库存

            currentTime = System.currentTimeMillis();
            int surplusGeneral = dataUtils.changeSurplusGeneral(payOrderParam.getTicketId(), -payOrderParam.getNumber());
            currentTime = System.currentTimeMillis() - currentTime;
            log.debug("redis 获取库存 -> time:" + (currentTime) + "毫秒");

            if (surplusGeneral < 0) {//库存回滚
                currentTime = System.currentTimeMillis();
                dataUtils.changeSurplusGeneral(payOrderParam.getTicketId(), payOrderParam.getNumber());
                currentTime = System.currentTimeMillis() - currentTime;
                log.debug("redis 修改库存 售罄 -> time:" + (currentTime) + "毫秒");
                redisLockUtil.unlock(lock);
                return ResponseDto.failure(ErrorMapping.get("20016"));//没抢到
            } else {
                isDownGeneral = true;

                //学生票 判断
                List<AdamEntersVo> entersVoList = new ArrayList<>();
                if (isTrueName == 1) {
                    currentTime = System.currentTimeMillis();
                    for (String enterId : payOrderParam.getEnterIdList()) {
                        AdamEntersVo adamEnters = orderUtils.getEnters(uid, enterId);//feignAdamBaseClient.queryEnters(enterId, uid).getData();
                        entersVoList.add(adamEnters);
                        if (isStudent == 1) {
                            int age = IDCard.getAgeByIdCard(adamEnters.getIdCard());
                            if (age > 25) {
                                redisLockUtil.unlock(lock);
                                return ResponseDto.failure(ErrorMapping.get("20017"));//年龄超了
                            }
                        }
                    }
                    currentTime = System.currentTimeMillis() - currentTime;
                    log.debug("获取 feign 入场人 -> time:" + (currentTime) + "毫秒");
                }

                //限购判断 如果实名 则身份证维度限购 如果不实名则数量限购
                if (entersVoList.size() > 0) {
                    currentTime = System.currentTimeMillis();
                    for (int i = 0; i < entersVoList.size(); i++) {
                        String res1 = orderUtils.judgeOrderLimit(performanceData.getType(), uid, entersVoList.get(i).getIdCard(), payOrderParam.getPerformanceId(), payOrderParam.getTicketId(), performanceLimit, performanceMemberLimit, ticketLimit, ticketMemberLimit, 1, 1, memberType, isTrueName);
                        log.debug("redis 判断库存 -> time:" + (currentTime) + "毫秒");
                        if (!res1.equals("")) {
                            redisLockUtil.unlock(lock);
                            return ResponseDto.failure(res1);//乱七八糟异常
                        }
                    }
                    currentTime = System.currentTimeMillis() - currentTime;

                } else {
                    log.debug("redis 判断库存 -> time:" + (currentTime) + "毫秒");
                    currentTime = System.currentTimeMillis();
                    String res1 = orderUtils.judgeOrderLimit(performanceData.getType(), uid, "", payOrderParam.getPerformanceId(), payOrderParam.getTicketId(), performanceLimit, performanceMemberLimit, ticketLimit, ticketMemberLimit, payOrderParam.getNumber(), payOrderParam.getNumber(), memberType, isTrueName);
                    currentTime = System.currentTimeMillis() - currentTime;
                    if (!res1.equals("")) {
                        redisLockUtil.unlock(lock);
                        return ResponseDto.failure(res1);//乱七八糟异常
                    }
                    currentTime = System.currentTimeMillis() - currentTime;

                }

                ResponseDto<PayResultVo> resultData = order(payOrderParam, uid, isMember, isTrueName, performanceData, ticketData, entersVoList, isStudent, ticketTimesData, currentTime);
                redisLockUtil.unlock(lock);
                return resultData;
            }
        } catch (Exception e) {
            if (isDownGeneral) {
                currentTime = System.currentTimeMillis();
                dataUtils.changeSurplusGeneral(payOrderParam.getTicketId(), payOrderParam.getNumber());
                currentTime = System.currentTimeMillis() - currentTime;
                log.debug("redis 修改库存 异常 -> time:" + (currentTime) + "毫秒");
            }
            e.printStackTrace();
            log.error("Kylin Order Pay Error = " + e.getMessage());
            redisLockUtil.unlock(lock);
            return ResponseDto.failure(ErrorMapping.get("20018"));//乱七八糟异常
        }
    }

    private ResponseDto<PayResultVo> order(PayOrderParam payOrderParam, String uid, boolean isMember, int isTrueName, KylinPerformanceVo performanceData, KylinTicketVo ticketData, List<AdamEntersVo> entersVoList, Integer isStudent, KylinTicketTimesVo ticketTimesData, Long currentTime) {
        LinkedList<String> sqls = new LinkedList<>();
        String source = CurrentUtil.getCliSource() == null ? "" : CurrentUtil.getCliSource();
        String version = CurrentUtil.getCliVersion() == null ? "" : CurrentUtil.getCliVersion();
        LocalDateTime now = LocalDateTime.now();
        //生成订单 order_ticket
        KylinOrderTickets orderTickets = new KylinOrderTickets();
        String orderTicketId = IDGenerator.nextSnowId().toString();
        log.debug("\n ORDER_TICKET_ID = " + orderTicketId + " \n TIME = " + System.currentTimeMillis());
        orderTickets.setOrderTicketsId(orderTicketId);
        orderTickets.setUserId(uid);
        Map token = CurrentUtil.getTokenClaims();
        orderTickets.setUserName(StringUtils.defaultString(((String) token.get("nickname")), ""));
        orderTickets.setUserMobile(StringUtils.defaultString(((String) token.get("mobile")), ""));
        orderTickets.setPerformanceTitle(performanceData.getTitle());
        orderTickets.setOrderCode(IDGenerator.ticketOrderCode(orderTicketId));
        orderTickets.setPayCode("");
        orderTickets.setQrCode("");
        orderTickets.setOrderType(source);
        orderTickets.setOrderVersion(version);
        orderTickets.setNumber(payOrderParam.getNumber());
        orderTickets.setPrice(ticketData.getPrice());
        orderTickets.setPriceMember(ticketData.getMemberPrice());
        if (isMember) {
            orderTickets.setPriceTotal(ticketData.getMemberPrice().multiply(new BigDecimal(payOrderParam.getNumber())).add(payOrderParam.getIsExpress() == 1 ? ticketData.getPriceExpress() : new BigDecimal("0")));
        } else {
            orderTickets.setPriceTotal(ticketData.getPrice().multiply(new BigDecimal(payOrderParam.getNumber())).add(payOrderParam.getIsExpress() == 1 ? ticketData.getPriceExpress() : new BigDecimal("0")));
        }

        if (Arrays.asList("dev", "test").contains(environment.getProperty("spring.profiles.active"))) {
            orderTickets.setPriceActual(new BigDecimal("0.01"));
        } else {
            orderTickets.setPriceActual(orderTickets.getPriceTotal());
        }

        orderTickets.setPriceVoucher(new BigDecimal("0.0"));
        orderTickets.setPriceExpress(ticketData.getPriceExpress());
        orderTickets.setPriceRefund(new BigDecimal(0.0));
        orderTickets.setRefundNumber(0);
        orderTickets.setPayType(payOrderParam.getPayType());
        orderTickets.setPaymentType(null);
        orderTickets.setTimePay(null);
        if (payOrderParam.getIsExpress() == 1) {
            currentTime = System.currentTimeMillis();
            AdamAddressesVo addressesVo = orderUtils.getAddress(uid, payOrderParam.getAddressId());//feignAdamBaseClient.queryAddresses(payOrderParam.getAddressId(), uid).getData();
            orderTickets.setExpressContacts(addressesVo.getName());
            orderTickets.setExpressAddress(addressesVo.getAddress());
            orderTickets.setExpressPhone(addressesVo.getPhone());
            orderTickets.setGetTicketType("express");
            currentTime = System.currentTimeMillis() - currentTime;
            log.debug("feign 获取入场人 -> time:" + (currentTime) + "毫秒");
        } else {
            orderTickets.setExpressContacts("");
            orderTickets.setExpressAddress("");
            orderTickets.setExpressPhone("");
            orderTickets.setGetTicketType("electronic");
        }
        orderTickets.setCouponType("no");
        orderTickets.setGetTicketDescribe("");
        orderTickets.setPayCountdownMinute(performanceData.getPayCountdownMinute());
        orderTickets.setCreatedAt(now);
        orderTickets.setUpdatedAt(null);


        //生成订单 order_ticket_status
        KylinOrderTicketStatus orderTicketStatus = new KylinOrderTicketStatus();
        String orderTicketStatusId = IDGenerator.nextSnowId().toString();
        orderTicketStatus.setOrderTicketStatusId(orderTicketStatusId);
        orderTicketStatus.setOrderId(orderTicketId);
        orderTicketStatus.setExpressType(payOrderParam.getExpressType());
        orderTicketStatus.setTransferStatus(KylinTableStatusConst.ORDER_TRANSFER_STATUS0);
        orderTicketStatus.setStatus(KylinTableStatusConst.ORDER_STATUS0);
        orderTicketStatus.setIsStudent(isStudent);
        orderTicketStatus.setPayStatus(KylinTableStatusConst.ORDER_PAY_STATUS0);
        orderTicketStatus.setCreatedAt(now);
        orderTicketStatus.setUpdatedAt(null);
        sqls.add(SqlMapping.get("kylin_order_ticket_status.add"));
        LinkedList<Object[]> sqlsDataB = new LinkedList<Object[]>();
        sqlsDataB.add(orderTicketStatus.getAddObject());

        //生成订单 order_ticket_relation
        KylinOrderTicketRelations orderTicketRelations = new KylinOrderTicketRelations();
        String orderTicketRelationId = IDGenerator.nextSnowId().toString();
        orderTicketRelations.setOrderTicketRelationsId(orderTicketRelationId);
        orderTicketRelations.setOrderId(orderTicketId);
        orderTicketRelations.setTransferId("");
        orderTicketRelations.setLiveId("");
        orderTicketRelations.setAgentId(payOrderParam.getAgentId());
        orderTicketRelations.setIsMember(isMember ? 1 : 0);
        orderTicketRelations.setPerformanceId(payOrderParam.getPerformanceId());
        orderTicketRelations.setTimeId(payOrderParam.getTimeId());
        orderTicketRelations.setTicketId(payOrderParam.getTicketId());
        orderTicketRelations.setCreatedAt(now);
        orderTicketRelations.setUpdatedAt(null);
        sqls.add(SqlMapping.get("kylin_order_ticket_relation.add"));
        LinkedList<Object[]> sqlsDataC = new LinkedList<Object[]>();
        sqlsDataC.add(orderTicketRelations.getAddObject());


        //生成票
        KylinOrderTicketEntities orderTicketEntities = new KylinOrderTicketEntities();
        LinkedList<Object[]> sqlsDataD = null;
        sqlsDataD = new LinkedList<Object[]>();
        sqls.add(SqlMapping.get("kylin_order_ticket_entities.add"));
        if (isTrueName == 1) {
            for (AdamEntersVo enters : entersVoList) {
                String orderTicketEntitiesId = IDGenerator.nextSnowId().toString();
                orderTicketEntities.setOrderTicketEntitiesId(orderTicketEntitiesId);
                orderTicketEntities.setOrderId(orderTicketId);
                orderTicketEntities.setTicketId(payOrderParam.getTicketId());
                orderTicketEntities.setUserId(uid);
                orderTicketEntities.setPerformanceId(payOrderParam.getPerformanceId());
                orderTicketEntities.setTimeId(payOrderParam.getTimeId());
                orderTicketEntities.setEnterType(enters.getType());
                orderTicketEntities.setEnterName(enters.getName());
                orderTicketEntities.setEnterMobile(enters.getMobile());
                orderTicketEntities.setEnterIdCode(enters.getIdCard());
                orderTicketEntities.setStatus(KylinTableStatusConst.ENTITIES_STATUS0);
                orderTicketEntities.setSysDamai(ticketData.getSysDamai());
                orderTicketEntities.setCheckClient("");
                orderTicketEntities.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT0);
                orderTicketEntities.setRefundPrice(BigDecimal.valueOf(0.0));
                orderTicketEntities.setComment("");
                orderTicketEntities.setCreatedAt(now);
                orderTicketEntities.setUpdatedAt(null);
                sqlsDataD.add(orderTicketEntities.getAddObject());
                // 生成vo
                KylinOrderTicketEntitiesVo orderTicketEntitiesVo = new KylinOrderTicketEntitiesVo();
                BeanUtils.copyProperties(orderTicketEntities, orderTicketEntitiesVo);
                orderTicketEntitiesVo.setPerformanceTitle(performanceData.getTitle());
                orderTicketEntitiesVo.setTicketTitle(ticketData.getTitle());
                orderTicketEntitiesVo.setUseStart(ticketData.getUseStart());
                orderTicketEntitiesVo.setUseEnd(ticketData.getUseEnd());
                orderTicketEntitiesVo.setTicketsmId(ticketData.getMid());
                orderTicketEntitiesVo.setTimemId(ticketTimesData.getMid());
                orderTicketEntitiesVo.setCreatedAt(orderTicketEntities.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                orderTicketEntitiesVo.setUpdatedAt(null);
                orderTicketEntitiesVo.setChangeDate(orderTicketEntities.getCreatedAt());
                currentTime = System.currentTimeMillis();
                mongoTemplate.insert(orderTicketEntitiesVo, KylinOrderTicketEntitiesVo.class.getSimpleName());
                currentTime = System.currentTimeMillis() - currentTime;
                log.debug("mongo 添加入场人 -> time:" + (currentTime) + "毫秒");
                currentTime = System.currentTimeMillis();
                dataUtils.changeBuyInfo(orderTicketEntitiesVo.getUserId(), orderTicketEntitiesVo.getEnterIdCode(), orderTicketEntitiesVo.getPerformanceId(), orderTicketEntitiesVo.getTicketId(), 1);
                currentTime = System.currentTimeMillis() - currentTime;
                log.debug("redis 修改 限购 -> time:" + (currentTime) + "毫秒");
            }
        } else {
            for (int i = 0; i < payOrderParam.getNumber(); i++) {
                String orderTicketEntitiesId = IDGenerator.nextSnowId().toString();
                orderTicketEntities.setOrderTicketEntitiesId(orderTicketEntitiesId);
                orderTicketEntities.setOrderId(orderTicketId);
                orderTicketEntities.setTicketId(payOrderParam.getTicketId());
                orderTicketEntities.setUserId(uid);
                orderTicketEntities.setPerformanceId(payOrderParam.getPerformanceId());
                orderTicketEntities.setTimeId(payOrderParam.getTimeId());
                orderTicketEntities.setEnterType(0);
                orderTicketEntities.setEnterName("");
                orderTicketEntities.setEnterMobile("");
                orderTicketEntities.setEnterIdCode("");
                orderTicketEntities.setStatus(KylinTableStatusConst.ENTITIES_STATUS0);
                orderTicketEntities.setSysDamai(ticketData.getSysDamai());
                orderTicketEntities.setCheckClient("");
                orderTicketEntities.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT0);
                orderTicketEntities.setComment("");
                orderTicketEntities.setCreatedAt(now);
                orderTicketEntities.setUpdatedAt(null);
                sqlsDataD.add(orderTicketEntities.getAddObject());
                // 生成vo
                KylinOrderTicketEntitiesVo orderTicketEntitiesVo = new KylinOrderTicketEntitiesVo();
                BeanUtils.copyProperties(orderTicketEntities, orderTicketEntitiesVo);
                orderTicketEntitiesVo.setPerformanceTitle(performanceData.getTitle());
                orderTicketEntitiesVo.setTicketTitle(ticketData.getTitle());
                orderTicketEntitiesVo.setUseStart(ticketData.getUseStart());
                orderTicketEntitiesVo.setUseEnd(ticketData.getUseEnd());
                orderTicketEntitiesVo.setTicketsmId(ticketData.getMid());
                orderTicketEntitiesVo.setTimemId(ticketTimesData.getMid());
                orderTicketEntitiesVo.setCreatedAt(orderTicketEntities.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                orderTicketEntitiesVo.setUpdatedAt(null);
                orderTicketEntitiesVo.setChangeDate(orderTicketEntities.getCreatedAt());
                currentTime = System.currentTimeMillis();
                mongoTemplate.insert(orderTicketEntitiesVo, KylinOrderTicketEntitiesVo.class.getSimpleName());
                currentTime = System.currentTimeMillis() - currentTime;
                log.debug("mongo 添加入场人 -> time:" + (currentTime) + "毫秒");
                currentTime = System.currentTimeMillis();
                dataUtils.changeBuyInfo(orderTicketEntitiesVo.getUserId(), orderTicketEntitiesVo.getEnterIdCode(), orderTicketEntitiesVo.getPerformanceId(), orderTicketEntitiesVo.getTicketId(), 1);
                currentTime = System.currentTimeMillis() - currentTime;
                log.debug("redis 修改限购 -> time:" + (currentTime) + "毫秒");
            }
        }
        // 调用支付
        String time1 = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(ticketData.getUseStart()), DateUtil.Formatter.MM_dd_zh);
        String time2 = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(ticketData.getUseEnd()), DateUtil.Formatter.MM_dd_zh);
        String useTime = ticketData.getType() == 2 ? time1 + "~" + time2 : time2;


        LinkedMultiValueMap<String, String> httpData = new LinkedMultiValueMap<String, String>();
        httpData.add("type", "TICKET");
        if (Arrays.asList("dev", "test").contains(environment.getProperty("spring.profiles.active"))) {
            httpData.add("price", "0.01");
        } else {
            httpData.add("price", orderTickets.getPriceActual().toString());
        }
        httpData.add("name", useTime + ticketData.getTitle() + "-" + performanceData.getTitle());
        httpData.add("detail", performanceData.getTitle() + "-" + ticketData.getTitle() + "-" + useTime);
        httpData.add("order_code", orderTickets.getOrderCode());
        httpData.add("client_ip", CurrentUtil.getCliIpAddr());
        httpData.add("notify_url", synUrl);
        httpData.add("create_date", orderTickets.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        httpData.add("expire_time", (orderTickets.getPayCountdownMinute()) + "");

        if (payOrderParam.getDeviceFrom().equals("js") || payOrderParam.getDeviceFrom().equals("applet")) {
            httpData.add("open_id", payOrderParam.getOpenId());
        }
        if (payOrderParam.getPayType().equals("alipay") && payOrderParam.getDeviceFrom().equals("wap")) {
            httpData.add("show_url", payOrderParam.getShowUrl() + orderTicketId);
            httpData.add("return_url", payOrderParam.getReturnUrl() + orderTicketId);
        }

        currentTime = System.currentTimeMillis();
        String returnData = HttpUtil.post(payUrl + payOrderParam.getDeviceFrom() + "/" + payOrderParam.getPayType(), httpData);
        currentTime = System.currentTimeMillis() - currentTime;
        log.debug("调用 PHP 支付 -> time:" + (currentTime) + "毫秒");
        PayResultVo payResultVo = JsonUtils.fromJson(returnData, PayResultVo.class);
//        PayResultVo payResultVo = null;
//        try {
//            payResultVo = JsonUtils.fromJson("{\n" +
//                    "    \"code\": \"20210618130049218267704668657P\",\n" +
//                    "    \"order_code\": \"T7774750254320448484\",\n" +
//                    "    \"status\": null,\n" +
//                    "    \"order_id\": \"77747502543208448\",\n" +
//                    "    \"showUrl\": \"http://devm.zhengzai.tv/#/ticket/purchase/detail?id=5936241&amp;type=purchase&amp;performance_id=5936241&amp;ticket_id=10981&amp;amount=1&amp;products_array=&amp;amount_array=&amp;express=077747502543208448\",\n" +
//                    "    \"returnUrl\": \"http://devm.zhengzai.tv/#/order/status?order_type=ticket&amp;order_id=77747502543208448\",\n" +
//                    "    \"price\": 0.01,\n" +
//                    "    \"pay_data\": {\n" +
//                    "      \"packages\": null,\n" +
//                    "      \"partnerid\": null,\n" +
//                    "      \"prepayid\": null,\n" +
//                    "      \"sign\": null,\n" +
//                    "      \"mweb_url\": null,\n" +
//                    "      \"paySign\": null,\n" +
//                    "      \"signType\": null,\n" +
//                    "      \"redirect_url\": \"https://openapi.alipay.com/gateway.do?alipay_sdk=lokielse%2Fomnipay-alipay&app_id=2019082866535131&biz_content=%7B%22product_code%22%3A%22QUICK_WAP_PAY%22%2C%22total_amount%22%3A%220.01%22%2C%22subject%22%3A%2206%5Cu670830%5Cu65e5%5Cu5355%5Cu65e5%5Cu7968%5Cu80e1%5Cu5927%5Cu7f8e%5Cu5e76%5Cu53d1%5Cu4e0b%5Cu5355%22%2C%22body%22%3A%22%5Cu80e1%5Cu5927%5Cu7f8e%5Cu5e76%5Cu53d1%5Cu4e0b%5Cu5355%5Cu5355%5Cu65e5%5Cu796806%5Cu670830%5Cu65e5%22%2C%22out_trade_no%22%3A%2220210618130049218267704668657P%22%2C%22time_expire%22%3A%222021-06-18+13%3A06%22%2C%22quit_url%22%3A%22http%3A%5C%2F%5C%2Fdevm.zhengzai.tv%5C%2F%23%5C%2Fticket%5C%2Fpurchase%5C%2Fdetail%3Fid%3D5936241%26amp%3Btype%3Dpurchase%26amp%3Bperformance_id%3D5936241%26amp%3Bticket_id%3D10981%26amp%3Bamount%3D1%26amp%3Bproducts_array%3D%26amp%3Bamount_array%3D%26amp%3Bexpress%3D077747502543208448%22%7D&charset=utf-8&format=JSON&method=alipay.trade.wap.pay&notify_url=http%3A%2F%2Ftestpay.zhengzai.tv%2Fnotify%2Fwap%2Falipay%2F1&return_url=http%3A%2F%2Fdevm.zhengzai.tv%2F%23%2Forder%2Fstatus%3Forder_type%3Dticket%26amp%3Border_id%3D77747502543208448&sign_type=RSA2&timestamp=2021-06-18+13%3A00%3A49&version=1.0&sign=UaHmNdI1cXjjSkR4gwrnELSWXqb1Icg1uCOe0vEo5yHCqWOy4JZCZbjCR1xOHQKowSMBAr6U2XLtMAaNXr6mX%2B%2F5IiaChsD4IPoODNT7F4GckVcqP3GkdLZTro%2FGmBau6VoYw1uVpyutQTJsjEU1fQ%2F5KDAKLvg0XG%2F1D%2BXb%2Bv6LdLDvehCEPzy4W%2BCT0qPANU4ysgZkt9hP1ljH61%2FBWiDnfz%2BOdust4KBoJYQzNWO3XSwvc17OxdGHn8EBmYRJz6sr1nt0i2h4BGQtjrOHRB3dToVkxrlsHtbrOmiCdRFH6utSVA8UjeKtlEB%2FH%2BkQfVxPkpOicTjkokhDNK6svg%3D%3D\",\n" +
//                    "      \"order_str\": null,\n" +
//                    "      \"appId\": null,\n" +
//                    "      \"appid\": null,\n" +
//                    "      \"nonceStr\": null,\n" +
//                    "      \"noncestr\": null,\n" +
//                    "      \"timeStamp\": null,\n" +
//                    "      \"timestamp\": null,\n" +
//                    "      \"package\": null\n" +
//                    "    }\n" +
//                    "  }", PayResultVo.class);
//        } catch (Exception e) {
//            payResultVo = new PayResultVo();
//        }
        payResultVo.setOrder_id(orderTicketId);
        payResultVo.setPrice(orderTickets.getPriceActual());
        orderTickets.setPayCode(payResultVo.getCode());
        sqls.add(SqlMapping.get("kylin_order_ticket.add"));
        LinkedList<Object[]> sqlsDataA = new LinkedList<>();
        sqlsDataA.add(orderTickets.getAddObject());

        if (payOrderParam.getPayType().equals("alipay") && payOrderParam.getDeviceFrom().equals("wap")) {
            payResultVo.setShowUrl(payOrderParam.getShowUrl() + orderTicketId);
            payResultVo.setReturnUrl(payOrderParam.getReturnUrl() + orderTicketId);
        }
        // 生成vo
        KylinOrderTicketVo orderTicketVo = new KylinOrderTicketVo();
        orderTicketVo.setOrderTicket(orderTickets);
        orderTicketVo.setOrderTicketStatus(orderTicketStatus);
        orderTicketVo.setOrderTicketRelation(orderTicketRelations);
        orderTicketVo.setPerformanceImg(performanceData.getImgPoster());
        orderTicketVo.setTicketTitle(ticketData.getTitle());
        orderTicketVo.setUseStart(ticketData.getUseStart());
        orderTicketVo.setTimeStart(performanceData.getTimeStart());
        orderTicketVo.setOverdueAt(orderTickets.getCreatedAt().plusMinutes(performanceData.getPayCountdownMinute()).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        orderTicketVo.setCreatedAt(orderTickets.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        orderTicketVo.setChangeDate(orderTickets.getCreatedAt());
        currentTime = System.currentTimeMillis();
        mongoTemplate.insert(orderTicketVo, KylinOrderTicketVo.class.getSimpleName());
        currentTime = System.currentTimeMillis() - currentTime;
        log.debug("mongo  添加 订单 -> time:" + (currentTime) + "毫秒");

        currentTime = System.currentTimeMillis();
        mongoVoUtils.resetOrderListVo(uid, 1, orderTicketVo.getOrderTicketsId(), orderTicketVo);
        currentTime = System.currentTimeMillis() - currentTime;
        log.debug("redis 修改订单列表 -> time:" + (currentTime) + "毫秒");

        // 执行sql
        String sqlData = SqlMapping.gets(sqls, sqlsDataB, sqlsDataC, sqlsDataD, sqlsDataA);
        currentTime = System.currentTimeMillis();
        rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_CREADE, MQConst.ROUTING_KEY_SQL_ORDER_CREATE,
                sqlData);
        currentTime = System.currentTimeMillis() - currentTime;
        log.debug("MQ 发送 -> time:" + (currentTime) + "毫秒");
        return ResponseDto.success(payResultVo);
    }

    @Override
    public ResponseDto<PayResultVo> payAgain(PayAgainParam payAgainParam) {
        try {
            String uid = CurrentUtil.getCurrentUid();
            checkOrderTime(uid);
            //检查订单时间 是否关闭
            KylinOrderTicketVo orderTicketData = dataUtils.getOrderTicketVo(payAgainParam.getOrderId());
            if (!orderTicketData.getUserId().equals(uid)) {
                return null;
            }
            if (orderTicketData == null) {
                return ResponseDto.failure("订单不存在");
            }

            if (orderTicketData.getStatus() == KylinTableStatusConst.ORDER_STATUS1) {
                return ResponseDto.failure("订单已支付");
            } else {
                if (orderTicketData.getStatus() != KylinTableStatusConst.ORDER_STATUS0) {
                    return ResponseDto.failure("订单已关闭");
                }
            }
            String returnCheckData = HttpUtil.get(checkUrl + "?code=" + orderTicketData.getPayCode(), null);
            PayResultVo checkVo = JsonUtils.fromJson(returnCheckData, PayResultVo.class);
            if (checkVo.getStatus() == 1) {
                return ResponseDto.failure("'您已支付请刷新再试'");
            }
            if (!orderTicketData.getPayType().equals("no")) {

                if (orderTicketData.getEntitiesVoList().size() == 0) {
                    return ResponseDto.failure("参数错误");
                }
                KylinOrderTicketEntitiesVo entitiesData = orderTicketData.getEntitiesVoList().get(0);

                LinkedMultiValueMap<String, String> httpData = new LinkedMultiValueMap<String, String>();
                httpData.add("type", "TICKET");
                if (Arrays.asList("dev", "test").contains(environment.getProperty("spring.profiles.active"))) {
                    httpData.add("price", orderTicketData.getPriceActual().toString());
                } else {
                    httpData.add("price", "0.01");
                }
                httpData.add("name", entitiesData.getUseStart() + "" + entitiesData.getPerformanceTitle());
                httpData.add("detail", entitiesData.getPerformanceTitle() + "-" + entitiesData.getTicketTitle() + "-" + entitiesData.getUseStart());
                httpData.add("order_code", orderTicketData.getOrderCode());
                httpData.add("client_ip", CurrentUtil.getCliIpAddr());
                httpData.add("notify_url", synUrl);
                httpData.add("create_date", orderTicketData.getCreatedAt());
                httpData.add("expire_time", orderTicketData.getPayCountdownMinute().toString());

                httpData.add("open_id", payAgainParam.getOpenId());

                if (payAgainParam.getPayType().equals("alipay") && payAgainParam.getDeviceFrom().equals("wap")) {
                    httpData.add("show_url", payAgainParam.getShowUrl() + payAgainParam.getOrderId());
                    httpData.add("return_url", payAgainParam.getReturnUrl() + payAgainParam.getOrderId());
                }

                String returnData = HttpUtil.post(payUrl + payAgainParam.getDeviceFrom() + "/" + payAgainParam.getPayType(), httpData);
                PayResultVo payResultVo = JsonUtils.fromJson(returnData, PayResultVo.class);
                payResultVo.setOrder_id(orderTicketData.getOrderTicketsId());
                payResultVo.setPrice(orderTicketData.getPriceActual());
                if (payAgainParam.getPayType().equals("alipay") && payAgainParam.getDeviceFrom().equals("wap")) {
                    payResultVo.setShowUrl(payAgainParam.getShowUrl());
                    payResultVo.setReturnUrl(payAgainParam.getReturnUrl());
                }

                KylinOrderTickets orderTickets = new KylinOrderTickets();
                orderTickets.setOrderTicketsId(payAgainParam.getOrderId());
                orderTickets.setUpdatedAt(LocalDateTime.now());
                orderTickets.setPayCode(payResultVo.getCode());
                orderTickets.setPayType(payAgainParam.getPayType());

                //改vo
                HashMap<String, Object> map = new HashMap<>();
                map.put("payType", payAgainParam.getPayType());
                map.put("payCode", payResultVo.getCode());
                map.put("updatedAt", DateUtil.Formatter.yyyyMMddHHmmss.format(orderTickets.getUpdatedAt()));
                map.put("changeDate", orderTickets.getUpdatedAt());
                Document doc = mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).findOneAndUpdate(
                        Query.query(Criteria.where("orderTicketsId").is(payAgainParam.getOrderId())).getQueryObject(),
                        new BasicDBObject("$set", mongoConverter.convertToMongoType(map)),
                        new FindOneAndUpdateOptions().returnDocument(ReturnDocument.BEFORE)
                );

                LocalDateTime strTime = orderTicketData.getChangeDate();
                dataUtils.delOrderTicketRedis(orderTickets.getOrderTicketsId());

                LinkedList<String> sqls = new LinkedList<>();
                sqls.add(SqlMapping.get("kylin_order_ticket.payAgain"));
                LinkedList<Object[]> sqlsDataA = new LinkedList<>();
                sqlsDataA.add(orderTickets.getPayAgainObject(strTime, strTime));
                sqls.add(SqlMapping.get("kylin_order_ticket_status.payAgain"));
                LinkedList<Object[]> sqlsDataB = new LinkedList<>();
                sqlsDataB.add(new Object[]{orderTickets.getUpdatedAt(), orderTickets.getOrderTicketsId(), strTime, strTime});
                sqls.add(SqlMapping.get("kylin_order_ticket_relation.payAgain"));
                LinkedList<Object[]> sqlsDataC = new LinkedList<>();
                sqlsDataC.add(new Object[]{orderTickets.getUpdatedAt(), orderTickets.getOrderTicketsId(), strTime, strTime});

                String sqlData = SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataC);
                rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_AGAIN, MQConst.ROUTING_KEY_SQL_ORDER_AGAIN, sqlData);
                return ResponseDto.success(payResultVo);
            }
            return ResponseDto.failure("未选择支付方式");
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseDto.failure("订单已失效");
        }

    }

    @Override
    public String syncOrder(SyncOrderParam syncOrderParam) {
        //支付时间
        LocalDateTime now = LocalDateTime.now();
        String lock = "order_lock:" + syncOrderParam.getOrder_code();
        if (!redisLockUtil.tryLock(lock, 1, 5)) {
            return "fail";//参数错误
        }

        String timePay = DateUtil.Formatter.yyyyMMddHHmmss.format(now);
        KylinOrderTicketVo orderTicketData = mongoTemplate.findOne(Query.query(Criteria.where("orderCode").is(syncOrderParam.getOrder_code())), KylinOrderTicketVo.class, KylinOrderTicketVo.class.getSimpleName());
        if (orderTicketData == null) {
            redisLockUtil.unlock(lock);
            return "fail";//订单不存在
        }

        if (orderTicketData.getStatus() != KylinTableStatusConst.ORDER_STATUS0) {
            if (orderTicketData.getPayCode().equals(syncOrderParam.getCode()) && orderTicketData.getStatus() == KylinTableStatusConst.ORDER_STATUS1) {
                redisLockUtil.unlock(lock);
                return "success";//已经支付
            }

            if (!orderTicketData.getPayCode().equals(syncOrderParam.getCode())) {
                redisLockUtil.unlock(lock);
                return "fail";//重复支付
            }
        }

        if (orderTicketData.getPriceActual().compareTo(syncOrderParam.getPrice()) != 0) {
            redisLockUtil.unlock(lock);
            return "fail";//价格不符
        }

        LinkedList<String> sqls = new LinkedList<>();
        LinkedList<Object[]> sqlsDataA = new LinkedList<>();
        LinkedList<Object[]> sqlsDataB = new LinkedList<>();
        LinkedList<Object[]> sqlsDataC = new LinkedList<>();
        LinkedList<Object[]> sqlsDataD = new LinkedList<>();

        LocalDateTime strTime = orderTicketData.getChangeDate();

        KylinOrderTickets orderTickets = new KylinOrderTickets();
        KylinOrderTicketStatus orderTicketStatus = new KylinOrderTicketStatus();
        KylinOrderTicketEntities orderTicketEntities = new KylinOrderTicketEntities();

        if (orderTicketData.getStatus() == 2) {
            orderRefundsCallbackService.refundApply(orderTicketData.getOrderTicketsId());
        } else if (orderTicketData.getStatus() == 3 || orderTicketData.getStatus() == 4) {
            log.error("订单号位 {} 的订单正在退款 或者已退款", syncOrderParam.getOrder_code());
        } else {
            orderTickets.setOrderTicketsId(orderTicketData.getOrderTicketsId());
            orderTickets.setPaymentType(syncOrderParam.getPayment_type());
            orderTickets.setPayCode(syncOrderParam.getCode());
            orderTickets.setTimePay(timePay);
            orderTickets.setQrCode(IDGenerator.ticketQrCode(orderTicketData.getOrderTicketsId()));
            orderTickets.setUpdatedAt(now);
            sqls.add(SqlMapping.get("kylin_order_ticket.synPay"));
            sqlsDataA.add(orderTickets.getSynOrderObject(strTime, strTime));

            orderTicketStatus.setOrderId(orderTicketData.getOrderTicketsId());
            orderTicketStatus.setStatus(KylinTableStatusConst.ORDER_STATUS1);
            orderTicketStatus.setPayStatus(syncOrderParam.getStatus());
            orderTicketStatus.setUpdatedAt(orderTickets.getUpdatedAt());
            sqls.add(SqlMapping.get("kylin_order_ticket_status.synPay"));
            sqlsDataB.add(orderTicketStatus.getSynOrderObject(strTime, strTime));

            sqls.add(SqlMapping.get("kylin_order_ticket_relation.synPay"));
            sqlsDataC.add(new Object[]{orderTickets.getUpdatedAt(), orderTickets.getOrderTicketsId(), strTime, strTime});

            orderTicketEntities.setOrderId(orderTicketData.getOrderTicketsId());
            orderTicketEntities.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT1);
            orderTicketEntities.setUpdatedAt(orderTickets.getUpdatedAt());
            sqls.add(SqlMapping.get("kylin_order_ticket_entities.synPay"));
            sqlsDataD.add(orderTicketEntities.getSynOrderObject(strTime, strTime));

            //vo
            HashMap<String, Object> orderTicketVo = new HashMap<>();
            orderTicketVo.put("paymentType", orderTickets.getPaymentType());
            orderTicketVo.put("payCode", orderTickets.getPayCode());
            orderTicketVo.put("timePay", orderTickets.getTimePay());
            orderTicketVo.put("qrCode", orderTickets.getQrCode());
            orderTicketVo.put("status", KylinTableStatusConst.ORDER_STATUS1);
            orderTicketVo.put("payStatus", orderTicketStatus.getStatus());
            orderTicketVo.put("updatedAt", timePay);
            orderTicketVo.put("changeDate", now);
            mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderTicketsId").is(orderTickets.getOrderTicketsId())).getQueryObject(),
                    new BasicDBObject("$set", mongoConverter.convertToMongoType(orderTicketVo))
            );


            HashMap<String, Object> orderTicketEntitiesVo = new HashMap<>();
            orderTicketEntitiesVo.put("isPayment", KylinTableStatusConst.ENTITIES_IS_PAYMENT1);
            orderTicketEntitiesVo.put("updatedAt", timePay);
            orderTicketEntitiesVo.put("changeDate", now);
            mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).updateMany(
                    Query.query(Criteria.where("orderId").is(orderTickets.getOrderTicketsId())).getQueryObject(),
                    new BasicDBObject("$set", mongoConverter.convertToMongoType(orderTicketEntitiesVo))
            );

            rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_PAY, MQConst.ROUTING_KEY_SQL_ORDER_PAY,
                    SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataC, sqlsDataD));

            //生成vo redis
            dataUtils.delOrderTicketRedis(orderTickets.getOrderTicketsId());
            mongoVoUtils.resetOrderListVo(orderTicketData.getUserId(), 2, orderTicketData.getOrderTicketsId(), null);

            // 发短信
            KylinPerformanceVo performanceData = dataUtils.getPerformanceVo(orderTicketData.getPerformanceId());
            KylinTicketTimesVo ticketTimesData = null;
            KylinTicketVo ticketData = null;
            for (int x = 0; x < performanceData.getTicketTimeList().size(); x++) {
                KylinTicketTimesVo timeItem = performanceData.getTicketTimeList().get(x);
                if (timeItem.getTimeId().equals(orderTicketData.getTimeId())) {
                    ticketTimesData = timeItem;
                    for (int y = 0; y < ticketTimesData.getTicketList().size(); y++) {
                        KylinTicketVo ticketItem = ticketTimesData.getTicketList().get(y);
                        if (ticketItem.getTicketsId().equals(orderTicketData.getTicketId())) {
                            ticketData = ticketItem;
                            break;
                        }
                    }
                    break;
                }
            }

            MessageDataVo dataVo = new MessageDataVo();
            dataVo.setName(orderTicketData.getPerformanceTitle());
            String time1 = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(ticketData.getUseStart()), DateUtil.Formatter.yyyy_MM_dd);
            String time2 = DateUtil.format(DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceData.getTimeStart()), DateUtil.Formatter.HHmm);
            dataVo.setTime(time1 + " " + time2);

            MessageConfigVo configVo = new MessageConfigVo();
            configVo.setStatus(true);
            if (orderTicketData.getGetTicketType().equals("express")) {
                configVo.setId("SMS_181490473");
            } else if (orderTicketData.getGetTicketType().equals("electronic")) {
                configVo.setId(ticketData.getIsShowCode() == 1 ? "SMS_171358560" : "SMS_181500419");
            }
//            otherUtils.sendMessage(orderTicketData.getUserMobile(), dataVo, configVo, 1);

            // 大麦回调
            sycDamaiOrder(orderTickets.getOrderTicketsId());
        }
        redisLockUtil.unlock(lock);
        return "success";
    }

    @Override
    public PageInfo<List<KylinOrderListVo>> orderList() {
        //TODO 缺快递
        PageInfo<List<KylinOrderListVo>> mPageInfo = null;
        String uid = CurrentUtil.getCurrentUid();
        checkOrderTime(uid);
        try {
            List<KylinOrderListVo> voList = dataUtils.getOrderList(uid);
            for (int i = 0; i < voList.size(); i++) {
                KylinOrderListVo item = voList.get(i);
                //TODO 顺丰快递
                Object expresses = null;
                if (null != expresses) {
                    item.setExpress_number("");//expresses.getNumber()
                    item.setExpress_company("");//expresses.getName()
                    item.setKuaidi_status(-2);//expresses.getStatus()
                } else {
                    item.setExpress_number("");
                    item.setExpress_company("");
                    item.setKuaidi_status(-2);
                }

                if (item.getStatus().equals(KylinTableStatusConst.ORDER_STATUS0)) {
                    item.setRestTime(DateUtil.intervalSeconds(
                            DateUtil.parse(item.getOverdueAt(), "yyyy-MM-dd HH:mm:ss"),
                            DateUtil.parse(DateUtil.getNowTime(), "yyyy-MM-dd HH:mm:ss")
                    ));
                } else {
                    item.setRestTime(0L);
                }
                if (voList.size() >= 40) {
                    break;
                }
            }

            mPageInfo = new PageInfo(voList);
            mPageInfo.setTotal(voList.size());

            log.info(new UserPathDao(LocalDateTime.now(),"订单列表","NanParams",voList).toString());
            return mPageInfo;
        } catch (Exception e) {
            e.printStackTrace();
            return mPageInfo;
        }
    }

    @Override
    public OrderDetailsVo orderDetails(String orderId) {
        OrderDetailsVo vo = new OrderDetailsVo();
        try {
            String uid = CurrentUtil.getCurrentUid();
            checkOrderTime(uid);
            KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(orderId);
            if (!orderTicketVo.getUserId().equals(uid)) {
                log.error("ORDER_TICKET_USER_ID : {}",orderTicketVo.getUserId());
                log.error("TOKEN UID : {}",uid);
                return null;
            }
            if (null != orderTicketVo) {
                //TODO 顺丰快递
                Object expresses = null;
//                Expresses expresses = expressesMapper.selectOne(new UpdateWrapper<Expresses>().eq("order_id", orderId).eq("order_type", "order_ticket"));
                KylinPerformanceVo performanceVo = dataUtils.getPerformanceVo(orderTicketVo.getPerformanceId());
                List<KylinOrderTicketEntitiesVo> kylinOrderTicketEntitiesVoList = orderTicketVo.getEntitiesVoList();
                KylinTicketVo ticketVo = null;

                //获取购票数据
                for (int x = 0; x < performanceVo.getTicketTimeList().size(); x++) {
                    KylinTicketTimesVo timeItem = performanceVo.getTicketTimeList().get(x);
                    for (int y = 0; y < timeItem.getTicketList().size(); y++) {
                        KylinTicketVo ticketItem = timeItem.getTicketList().get(y);
                        if (ticketItem.getTicketsId().equals(orderTicketVo.getTicketId())) {
                            ticketVo = ticketItem;
                            break;
                        }
                    }
                }

                orderTicketVo.setIsTrueName(ticketVo.getIsTrueName());
                orderTicketVo.setNoticeImage(performanceVo.getNoticeImage());
                orderTicketVo.setNotice(performanceVo.getNotice());
                orderTicketVo.setTicketType(ticketVo.getType());
                orderTicketVo.setFieldName(performanceVo.getFieldName());
                if (ticketVo.getIsShowCode() == 1) {
                    Date date = DateUtil.parse(ticketVo.getQrCodeShowTime(), DateUtil.Formatter.yyyyMMddHHmm.toString());
                    if (DateUtil.compareDay(date, DateUtil.now()) <= 0) {
                        orderTicketVo.setQrCode("");
                    }else{
                        orderTicketVo.setQrCode(orderTicketVo.getQrCode());
                    }
                } else {
                    orderTicketVo.setQrCode("");
                }


                // 数据脱敏
                for (KylinOrderTicketEntitiesVo item : kylinOrderTicketEntitiesVoList) {
                    if (item.getEnterIdCode().length() == 18) {
                        item.setEnterIdCode(item.getEnterIdCode().substring(0, 3) + "*************" + item.getEnterIdCode().substring(16));
                    }
                    if (item.getEnterMobile().length() == 11) {
                        item.setEnterMobile(item.getEnterMobile().substring(0, 3) + "****" + item.getEnterMobile().substring(7));
                    }
                }
                //计算 倒计时
                if (orderTicketVo.getStatus() == KylinTableStatusConst.ORDER_STATUS0) {
                    vo.setRestTime(DateUtil.intervalSeconds(
                            DateUtil.parse(orderTicketVo.getOverdueAt(), "yyyy-MM-dd HH:mm:ss"),
                            DateUtil.parse(DateUtil.getNowTime(), "yyyy-MM-dd HH:mm:ss")
                    ));
                } else {
                    vo.setRestTime(0L);
                }
                //快递
                if (null != expresses) {
                    vo.setExpress_number("");//expresses.getNumber()
                    vo.setExpress_company("");//expresses.getName()
                    vo.setKuaidi_status(-2);//expresses.getStatus()
                } else {
                    vo.setExpress_number("");
                    vo.setExpress_company("");
                    vo.setKuaidi_status(-2);
                }
                vo.setOrderTicketVo(orderTicketVo);
                vo.setEnterDescribe(dataUtils.getEnterInfo("1"));
            }
            log.info(new UserPathDao(LocalDateTime.now(),"订单列表",orderId,vo).toString());
            return vo;
        } catch (Exception e) {
            return vo;
        }
    }

    @Override
    public boolean checkOrderTime(String userId) {
        String lock = "order_lock:checkOrderTime:" + userId;
        if (redisLockUtil.tryLock(lock, 1, 3600)) {
            try {
                List<OrderScriptDto> dtoData = orderTicketsMapper.orderScriptDto(userId);
                LocalDateTime now = LocalDateTime.now();
                Long currentTime = System.currentTimeMillis();
                HashMap<String, Integer> mapSurplusGeneral = new HashMap<>();
                ArrayList<String> orderDataList = new ArrayList<>();
                ArrayList<String> orderIdList = new ArrayList<>();
                HashMap<String, Object> mapMongo = new HashMap<>();

                for (OrderScriptDto item : dtoData) {
                    if (item.getStatus().equals(KylinTableStatusConst.ORDER_STATUS0)) {
                        try {
                            //vo
                            mapMongo.put("status", KylinTableStatusConst.ORDER_STATUS2);
                            mapMongo.put("updatedAt", DateUtil.Formatter.yyyyMMddHHmmssSSS.format(now));
                            mapMongo.put("changeDate", now);
                            orderDataList.add(item.getOrderTicketsId() + "," + item.getUserId());
                            orderIdList.add(item.getOrderTicketsId());
                            mapSurplusGeneral.put(item.getTicketId(), mapSurplusGeneral.get(item.getTicketId()) == null ? item.getNumber() : mapSurplusGeneral.get(item.getTicketId()) + item.getNumber());
                        } catch (Exception e) {
                            log.debug("CHECK TIME SYNC = " + e.getMessage());
                            e.printStackTrace();
                            return false;
                        }
                    } else {
                    }
                }
                currentTime = System.currentTimeMillis() - currentTime;
                log.debug("FOR 循环 -> time:" + (currentTime) + "毫秒");
                if (orderDataList.size() > 0) {
                    //库存
                    for (Map.Entry<String, Integer> entry : mapSurplusGeneral.entrySet()) {
                        dataUtils.changeSurplusGeneral(entry.getKey(), entry.getValue());
                    }
                    currentTime = System.currentTimeMillis() - currentTime;
                    log.debug("redis 库存 -> time:" + (currentTime) + "毫秒");

                    //mysql
                    String orderStr = "";
                    for (int i = 0; i < orderIdList.size(); i++) {
                        String orderTicketId = orderIdList.get(i);
                        orderStr += "'" + orderTicketId + "',";
                    }

                    orderStr = orderStr.substring(0, orderStr.length() - 1);
                    LinkedList<String> sqls = new LinkedList();
                    sqls.add("UPDATE kylin_order_tickets SET updated_at = '" + now + "' WHERE  order_tickets_id in (" + orderStr + ") ");
                    sqls.add("UPDATE kylin_order_ticket_status SET `status` = 2,updated_at = '" + now + "' WHERE order_id in (" + orderStr + ") ");
                    sqls.add("UPDATE kylin_order_ticket_relations SET updated_at = '" + now + "' WHERE  order_id in (" + orderStr + ")");
                    String redisKey = "kylin:ORDER_CLOSE:" + IDGenerator.nextMilliId();
                    redisUtil.set(redisKey, sqls);
                    rabbitTemplate.convertAndSend(MQConst.EXCHANGES_LIQUIDNET_SQL_ORDER_CLOSE, MQConst.ROUTING_KEY_SQL_ORDER_CLOSE, redisKey);

                    currentTime = System.currentTimeMillis() - currentTime;
                    log.debug("mysql -> time:" + (currentTime) + "毫秒");

                    //mongo
                    mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateMany(
                            Query.query(Criteria.where("orderTicketsId").in(orderIdList)).getQueryObject(),
                            new BasicDBObject("$set", mongoConverter.convertToMongoType(mapMongo))
                    );
                    currentTime = System.currentTimeMillis() - currentTime;
                    log.debug("mongo -> time:" + (currentTime) + "毫秒");

                    Thread thread = new Thread(() -> {
                        //redis 列表
                        orderDataList.forEach(t -> {
                            String orderTicketId = t.split(",")[0];
                            String uid = t.split(",")[1];
                            KylinOrderTicketVo vo = dataUtils.getOrderTicketVo(orderTicketId);
                            vo.setStatus(2);
                            redisUtil.set(KylinRedisConst.ORDER + orderTicketId, vo);
                            mongoVoUtils.resetOrderListVo(uid, 2, orderTicketId, vo);
                            // redis 限购
                            for (int i = 0; i < vo.getEntitiesVoList().size(); i++) {
                                KylinOrderTicketEntitiesVo items = vo.getEntitiesVoList().get(i);
                                dataUtils.changeBuyInfo(items.getUserId(), items.getEnterIdCode(), items.getPerformanceId(), items.getTicketId(), -1);
                            }
                        });
                    });
                    thread.start();
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
            }
            redisLockUtil.unlock(lock);
        } else {
            log.debug("WARNING     LOCKING");
        }
        return true;
    }

    @Override
    public ResponseDto<Integer> checkOrderResult(String orderId) {
        String uid = CurrentUtil.getCurrentUid();
        KylinOrderTicketVo orderTicketData = dataUtils.getOrderTicketVo(orderId);
        if (!orderTicketData.getUserId().equals(uid)) {
            return null;
        }
        if (orderTicketData == null) {
            return ResponseDto.failure("订单不存在");
        } else {
            String returnCheckData = HttpUtil.get(checkUrl + "?code=" + orderTicketData.getPayCode(), null);
            PayResultVo checkVo = JsonUtils.fromJson(returnCheckData, PayResultVo.class);
            if (checkVo.getStatus() == 1) {
                return ResponseDto.success(1);
            } else {
                return ResponseDto.success(0);
            }
        }
    }

    @Override
    public ResponseDto<Integer> orderUnPayCount() {
        String uid = CurrentUtil.getCurrentUid();
        List<KylinOrderListVo> voList = dataUtils.getOrderList(uid);
        Integer unPayCount = 0;
        for (KylinOrderListVo item : voList) {
            if (item.getStatus() == 0) {
                unPayCount += 1;
            }

        }
        return ResponseDto.success(unPayCount);
    }

    public boolean checkAgent(String agentId, KylinTicketVo ticketData) {
        boolean isAgent = ticketData.getIsAgent() == 1;
        if (isAgent) {
            return redisUtil.sHasKey(KylinRedisConst.AGENT, agentId);
        } else {
            return true;
        }
    }

    private boolean sycDamaiOrder(String orderId) {
        try {
            KylinOrderTicketVo orderData = dataUtils.getOrderTicketVo(orderId);
            KylinPerformanceVo vo = dataUtils.getPerformanceVo(orderData.getPerformanceId());
            TaobaoClient client = taobaoTicketUtils.initTaobaoClient();
            int isSysDamai = 0;
            for (int x = 0; x < vo.getTicketTimeList().size(); x++) {
                KylinTicketTimesVo timeItem = vo.getTicketTimeList().get(x);
                for (int y = 0; y < timeItem.getTicketList().size(); y++) {
                    KylinTicketVo ticketItem = timeItem.getTicketList().get(y);
                    if (ticketItem.getTicketsId().equals(orderData.getTicketId())) {
                        isSysDamai = ticketItem.getSysDamai();
                        break;
                    }
                }
            }
            if (isSysDamai == 1) {
                KylinOrderTicketVo orderVo = dataUtils.getOrderTicketVo(orderId);
                List<KylinOrderTicketEntitiesVo> listData = orderVo.getEntitiesVoList();
                AlibabaDamaiMevOpenBatchpushticketRequest req = new AlibabaDamaiMevOpenBatchpushticketRequest();
                List<AlibabaDamaiMevOpenBatchpushticketRequest.ThirdTicketPushOpenParam> list2 = new ArrayList<AlibabaDamaiMevOpenBatchpushticketRequest.ThirdTicketPushOpenParam>();
                for (int i = 0; i < listData.size(); i++) {
                    KylinOrderTicketEntitiesVo item = listData.get(i);
                    AlibabaDamaiMevOpenBatchpushticketRequest.ThirdTicketPushOpenParam obj3 = new AlibabaDamaiMevOpenBatchpushticketRequest.ThirdTicketPushOpenParam();
                    list2.add(obj3);
                    obj3.setUserName(item.getEnterName());//用户名 入场人姓名
                    obj3.setCertificateNo(item.getEnterIdCode());//证件号 入场人身份证
                    obj3.setOrderUserMobile(item.getEnterMobile());//用户手机号 入场人手机号
                    obj3.setCertificateType(item.getEnterType().longValue());//证件内容 入场人证件type
                    obj3.setPayTime(DateUtils.parseDate(orderData.getTimePay(), new String[]{"yyyy-MM-dd HH:mm:ss"}));//支付时间
                    obj3.setPerformId(item.getTimemId().longValue());//场次id
                    obj3.setTicketItemId(item.getTicketsmId().longValue());
                    obj3.setVoucherId(item.getMid().longValue());//票单号 入场人id

                    obj3.setOrderId(Long.parseLong(orderData.getOrderTicketsId()));//订单id orderId
                    obj3.setMediumType(orderData.getGetTicketType().equals("express") ? 1L : 2L);//票类型 快递 电子
                    obj3.setSupplierSecret(taobaoTicketUtils.getSupplierSecret());
                    obj3.setSystemId(taobaoTicketUtils.getSystemId());
                    obj3.setSeatType(1L);
                    obj3.setTicketType(1L);//票类型
                }
                req.setThirdTicketSetOpenParamList(list2);
                if (list2.size() == 0) {
                    return true;
                } else {
                    AlibabaDamaiMevOpenBatchpushticketResponse rsp = client.execute(req);
                    return rsp.getResult().getSuccess();
                }
            }
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
