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

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
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.base.UserPathDto;
import com.liquidnet.service.base.constant.MQConst;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dto.vo.admin.OrderRefundAddress;
import com.liquidnet.service.kylin.dto.vo.admin.OrderRefundPoundage;
import com.liquidnet.service.kylin.dto.vo.express.KylinOrderExpressVo;
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.mongo.KylinOrderRefundEntitiesVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketEntitiesVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinOrderTicketVo;
import com.liquidnet.service.kylin.dto.vo.mongo.KylinPerformanceVo;
import com.liquidnet.service.kylin.dto.vo.returns.*;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.service.IKylinOrderTicketsService;
import com.liquidnet.service.kylin.utils.*;
import com.mongodb.BasicDBObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.bson.Document;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

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 implements IKylinOrderTicketsService {

    @Autowired
    private DataUtils dataUtils;
    @Autowired
    private OrderUtils orderUtils;
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private QueueUtils queueUtils;
    @Autowired
    private KylinRefundsStatusServiceImpl refundsStatusService;

    @Value("${liquidnet.express.shunfeng.custid}")
    private String custid;
    @Value("${liquidnet.express.shunfeng.expressType}")
    private Integer expressType;
    @Value("${liquidnet.express.shunfeng.depositumInfo}")
    private String depositumInfo;

    @Autowired
    private ShunfengSignUtils shunfengSignUtils;

    @Override
    public PageInfo<List<KylinOrderListVo>> orderList() {
        //TODO 缺快递
        PageInfo<List<KylinOrderListVo>> mPageInfo = null;
        String uid = CurrentUtil.getCurrentUid();
        try {
            List<KylinOrderListVo> voList = dataUtils.getOrderList(uid);
            for (int i = 0; i < voList.size(); i++) {
                KylinOrderListVo item = voList.get(i);
                item.setStatus(item.getStatus());
                Integer orderExpressStatus = dataUtils.getOrderExpressInfo(item.getOrderTicketsId());
                item.setExpressStatus(orderExpressStatus);

                if (item.getStatus().equals(KylinTableStatusConst.ORDER_STATUS0)) {
                    try {
                        item.setRestTime(DateUtil.intervalSeconds(
                                DateUtil.parse(item.getOverdueAt(), "yyyy-MM-dd HH:mm:ss"),
                                DateUtil.parse(DateUtil.getNowTime(), "yyyy-MM-dd HH:mm:ss")
                        ));
                        if (item.getRestTime() <= 0L) {
                            item.setRestTime(0L);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    item.setRestTime(0L);
                }
                if (i >= 40) {
                    break;
                }
            }

            KylinOrderTicketVo orderTicketVo = dataUtils.getTransferOrder(uid);
            if (orderTicketVo != null) {
                voList.add(0, KylinOrderListVo.getNew().copy(orderTicketVo));
            }

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

            log.info(UserPathDto.setData("订单列表", "", voList));
            return mPageInfo;
        } catch (Exception e) {
            e.printStackTrace();
            return mPageInfo;
        }
    }

    @Override
    public OrderDetailsVo orderDetails(String orderId) {
        try {
            OrderDetailsVo vo = OrderDetailsVo.getNew();
            String uid = CurrentUtil.getCurrentUid();
            KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(orderId);
            if (orderTicketVo == null) {
                orderTicketVo = dataUtils.getTransferOrder(uid);
            }
            if (uid.equals("809406") || uid.equals("773650")) {
            } else {
                if (!orderTicketVo.getUserId().equals(uid)) {
                    return null;
                }
            }
            if (null != orderTicketVo) {
                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());

                List<KylinOrderRefundsVo> orderRefundsVoList = dataUtils.getOrderRefundVoByOrderId(orderId);

                if (ticketVo.getIsShowCode() == 1 && orderTicketVo.getStatus() != 0 && orderTicketVo.getStatus() != 2 && orderTicketVo.getStatus() != 4) {
                    LocalDateTime date = DateUtil.Formatter.yyyyMMddHHmmss.parse(ticketVo.getQrCodeShowTime());
                    if (LocalDateTime.now().isAfter(date)) {
                        orderTicketVo.setQrCode(orderTicketVo.getQrCode());
                        vo.setIsShowQrCode(ticketVo.getIsShowCode());
                        vo.setShowQrCodeTime(ticketVo.getQrCodeShowTime() == null ? "" : ticketVo.getQrCodeShowTime());
                    } else {
                        orderTicketVo.setQrCode("");
                        vo.setIsShowQrCode(ticketVo.getIsShowCode());
                        vo.setShowQrCodeTime(ticketVo.getQrCodeShowTime() == null ? "" : ticketVo.getQrCodeShowTime());
                    }
                } else {
                    orderTicketVo.setQrCode("");
                    vo.setIsShowQrCode(0);
                    vo.setShowQrCodeTime("");
                }
                // 数据脱敏
                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));
                    }
                }

                //计算 倒计时
                Date nowDate = DateUtil.parse(DateUtil.getNowTime(), "yyyy-MM-dd HH:mm:ss");
                if (orderTicketVo.getStatus().equals(KylinTableStatusConst.ORDER_STATUS0)) {
                    vo.setRestTime(DateUtil.intervalSeconds(
                            DateUtil.parse(orderTicketVo.getOverdueAt(), "yyyy-MM-dd HH:mm:ss"),
                            nowDate
                    ));
                    if (vo.getRestTime() <= 0L) {
                        vo.setRestTime(0L);
                    }
                } else {
                    vo.setRestTime(0L);
                }
                //计算 转赠倒计时
                if (orderTicketVo.getTransferTime() != null && (orderTicketVo.getTransferStatus().equals(1) || orderTicketVo.getTransferStatus().equals(4))) {
                    vo.setRestTransferTime(DateUtil.intervalSeconds(
                            DateUtil.parse(DateUtil.Formatter.yyyyMMddHHmmss.format(LocalDateTime.parse(orderTicketVo.getTransferTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")).plusMinutes(120)),
                                    "yyyy-MM-dd HH:mm:ss"),
                            nowDate
                    ));
                    if (vo.getRestTransferTime() <= 0L) {
                        vo.setRestTransferTime(0L);
                    }
                } else {
                    vo.setRestTransferTime(0L);
                }

                Integer orderExpressStatus = dataUtils.getOrderExpressInfo(orderTicketVo.getOrderTicketsId());
                vo.setExpressStatus(orderExpressStatus);

                List<OrderRefundListVo> orderRefundListVos = new ArrayList<>();
                BigDecimal lockPrice = BigDecimal.valueOf(0.00);
                for (KylinOrderRefundsVo item : orderRefundsVoList) {
                    if (item.getType().equals(1)) {
                        break;
                    }
                    OrderRefundListVo data = OrderRefundListVo.getNew();
                    if (item.getOrderRefundCode().length() > 20) {
                        data.setOrderRefundCode(item.getOrderRefundCode().substring(item.getOrderRefundCode().length() - 10));
                    }
                    data.setOrderRefundsId(item.getOrderRefundsId());
                    data.setStatus(item.getStatus());
                    data.setPrice(item.getPrice());
                    data.setIsMine(uid.equals(item.getApplicantId()) ? 1 : 0);
                    if (item.getStatus().equals(0) || item.getStatus().equals(1) || item.getStatus().equals(7) || item.getStatus().equals(3) || item.getStatus().equals(4)) {
                        lockPrice = lockPrice.add(item.getPrice());
                    }
                    orderRefundListVos.add(data);
                }

                //是否可退
                if (null != performanceVo.getIsCanRefund() && performanceVo.getIsCanRefund() == 1) {
                    LocalDateTime refundOpenDate = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getRefundOpenTime());
                    LocalDateTime refundCloseDate = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getRefundCloseTime());
                    if (LocalDateTime.now().isAfter(refundOpenDate) && LocalDateTime.now().isBefore(refundCloseDate)
                            && ticketVo.getCounts() == 1 && lockPrice.compareTo(orderTicketVo.getPriceActual()) != 0
                            && (orderTicketVo.getStatus().equals(1) || orderTicketVo.getStatus().equals(3) || orderTicketVo.getStatus().equals(6))
                            && (orderTicketVo.getTransferStatus().equals(0) || orderTicketVo.getTransferStatus().equals(5))) {
                        vo.setIsCanRefund(1);
                    } else {
                        vo.setIsCanRefund(0);
                    }
                } else {
                    vo.setIsCanRefund(0);
                }
                //是否可转
                if (null != performanceVo.getIsTransfer() && performanceVo.getIsTransfer() == 1) {
                    LocalDateTime transferStartTime = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getTransferStartTime());
                    LocalDateTime transferEndTime = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getTransferEndTime());
                    if (LocalDateTime.now().isAfter(transferStartTime) && LocalDateTime.now().isBefore(transferEndTime)
                            && orderTicketVo.getExpressAddress().trim().equals("")
                            && orderTicketVo.getStatus().equals(1) && orderTicketVo.getTransferStatus().equals(0)) {
                        vo.setIsCanTransfer(1);
                    } else {
                        vo.setIsCanTransfer(0);
                    }
                } else {
                    vo.setIsCanTransfer(0);
                }
                //是否可回退
                if (null != performanceVo.getIsCanRefund() && performanceVo.getIsCanRefund() == 1) {
                    LocalDateTime refundOpenDate = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getRefundOpenTime());
                    LocalDateTime refundCloseDate = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getRefundCloseTime());
                    if (LocalDateTime.now().isAfter(refundOpenDate) && LocalDateTime.now().isBefore(refundCloseDate)
                            && orderTicketVo.getTransferStatus().equals(3)) {
                        vo.setIsCanBack(1);
                    } else {
                        vo.setIsCanBack(0);
                    }
                } else {
                    vo.setIsCanBack(0);
                }

                orderTicketVo.setOrderRefundListVos(orderRefundListVos);
                if (orderTicketVo.getOrderCode().length() > 20) {
                    orderTicketVo.setOrderCode(orderTicketVo.getOrderCode().substring(orderTicketVo.getOrderCode().length() - 10));
                }
                vo.setOrderTicketVo(orderTicketVo);
                vo.setEnterDescribe(dataUtils.getEnterInfo(performanceVo.getType(), orderTicketVo.getGetTicketType(), orderTicketVo.getIsStudent(), ticketVo.getIsTrueName()));
                // 添加 优惠券相关
                vo.setOrderCouponsList(dataUtils.getOrderCoupon(orderId));
            }
            log.info(UserPathDto.setData("订单详情", orderId, vo));
            return vo;
        } catch (Exception e) {
            log.info("订单详情异常:", e);
            return null;
        }
    }

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

            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")
                ));
                if (item.getRestTime() <= 0L) {
                    item.setRestTime(0L);
                } else {
                    unPayCount += 1;
                }
            } else {
                item.setRestTime(0L);
            }
        }
        return ResponseDto.success(unPayCount);
    }

    @Override
    public ResponseDto<KylinOrderTicketPreVo> toOrderRefundDetails(String orderId) {
        try {
            // 订单 演出 订单退款数据
            KylinOrderTicketPreVo vo = KylinOrderTicketPreVo.getNew();
            String uid = CurrentUtil.getCurrentUid();
            KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(orderId);
            KylinPerformanceVo performanceVo = dataUtils.getPerformanceVo(orderTicketVo.getPerformanceId());
            List<KylinOrderRefundsVo> kylinOrderRefundsVoBaseList = dataUtils.getOrderRefundVoByOrderId(orderTicketVo.getOrderTicketsId());
            // 判断是否购买人
            if (uid.equals("809406") || uid.equals("773650")) {
            } else {
                if (!orderTicketVo.getUserId().equals(uid)) {
                    return ResponseDto.failure(ErrorMapping.get("20003"));
                }
            }
            // 入场人 数据脱敏/退款
            List<KylinOrderTicketEntitiesVo> kylinOrderTicketEntitiesVoList = orderTicketVo.getEntitiesVoList();
            List<KylinOrderTicketEntitiesPreRefundVo> kylinOrderTicketEntitiesPreRefundVos = ObjectUtil.getKylinOrderTicketEntitiesPreRefundVoArrayList();
            for (KylinOrderTicketEntitiesVo item : kylinOrderTicketEntitiesVoList) {
                KylinOrderTicketEntitiesPreRefundVo refundVo = KylinOrderTicketEntitiesPreRefundVo.getNew();
                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));
                }
                item.setPriceActual(orderTicketVo.getPriceActual().subtract(orderTicketVo.getPriceExpress()).divide(BigDecimal.valueOf(orderTicketVo.getNumber())));
                item.setPriceCanRefund(dataUtils.getCanRefundOrderEntitiesPrice(orderTicketVo, kylinOrderRefundsVoBaseList, item.getOrderTicketEntitiesId()));
                BeanUtils.copyProperties(item, refundVo);
                kylinOrderTicketEntitiesPreRefundVos.add(refundVo);
            }
            // FieldName
            orderTicketVo.setFieldName(performanceVo.getFieldName());
            // 短OrderCode
            if (orderTicketVo.getOrderCode().length() > 20) {
                orderTicketVo.setOrderCode(orderTicketVo.getOrderCode().substring(orderTicketVo.getOrderCode().length() - 10));
            }
            // 手续费相关
            ArrayList<OrderRefundPoundage> refundPoundage = dataUtils.getRefundPoundage(performanceVo.getIsRefundPoundage());
            // 券
            ArrayList<KylinOrderCoupons> orderCoupon = dataUtils.getOrderCoupon(orderId);
            // 快递地址
            OrderRefundAddress refundAddress = dataUtils.getRefundAddress(orderTicketVo.getGetTicketType());
            // 整理返回数据
            BeanUtils.copyProperties(orderTicketVo, vo);
            vo.setIsRefundPoundage(performanceVo.getIsRefundPoundage());
            vo.setRefundPoundageList(refundPoundage);
            vo.setOrderCouponList(orderCoupon);
            vo.setRefundAddress(refundAddress);
            vo.setIsTrueName(performanceVo.getIsTrueName());
            vo.setEntitiesPreRefundVos(kylinOrderTicketEntitiesPreRefundVos);
            return ResponseDto.success(vo);
        } catch (Exception e) {
            log.error("toOrderRefundDetailsException", e);
            return ResponseDto.failure(ErrorMapping.get("20030"));
        }
    }

    @Override
    public ResponseDto<OrderRefundVo> orderRefundDetails(String orderId, String orderRefundId) {
        try {
            OrderRefundVo vo = OrderRefundVo.getNew();
            String uid = CurrentUtil.getCurrentUid();
            KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(orderId);
            KylinPerformanceVo performanceVo = dataUtils.getPerformanceVo(orderTicketVo.getPerformanceId());

            if (uid.equals("809406") || uid.equals("773650")) {
            } else {
                if (!orderTicketVo.getUserId().equals(uid)) {
                    return ResponseDto.failure(ErrorMapping.get("20003"));
                }
            }
            orderTicketVo.setFieldName(performanceVo.getFieldName());
            if (orderTicketVo.getOrderCode().length() > 20) {
                orderTicketVo.setOrderCode(orderTicketVo.getOrderCode().substring(orderTicketVo.getOrderCode().length() - 10));
            }
            KylinOrderRefundsVo kylinOrderRefundsVoBase = dataUtils.getOrderRefundVo(orderRefundId);
            if (kylinOrderRefundsVoBase.getOrderRefundCode().length() > 20) {
                kylinOrderRefundsVoBase.setOrderRefundCode(kylinOrderRefundsVoBase.getOrderRefundCode().substring(kylinOrderRefundsVoBase.getOrderRefundCode().length() - 10));
            }
            vo.setKylinOrderRefundsVoBaseList(kylinOrderRefundsVoBase);
            vo.setOrderTicketVo(orderTicketVo);
            vo.setKylinOrderExpressVo(dataUtils.getOrderRefundExpressInfo(orderId));
            return ResponseDto.success(vo);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseDto.failure(ErrorMapping.get("20030"));
        }
    }

    @Override
    public String sendOrderRefund(String orderId, String orderTicketEntitiesId, String reason, String picList, Integer sendExpressType, String expressNumber, String expressContacts, String expressPhone, String sendExpressAddress, String appointmentTime) {
        KylinOrderTicketEntitiesVo orderTicketEntitiesVo = null;
        try {
            String uid = CurrentUtil.getCurrentUid();
            KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(orderId);
            List<KylinOrderRefundsVo> kylinOrderRefundsVoBaseList = dataUtils.getOrderRefundVoByOrderId(orderTicketVo.getOrderTicketsId());
            if (uid.equals("809406") || uid.equals("773650")) {
            } else {
                if (!orderTicketVo.getUserId().equals(uid)) {
                    return "无权查看";
                }
            }

            if (!orderTicketVo.getPayStatus().equals(1)) {
                return "暂不支持退款";
            }

            KylinPerformanceVo performanceVo = dataUtils.getPerformanceVo(orderTicketVo.getPerformanceId());
            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;
                    }
                }
            }

            if (null != performanceVo.getIsCanRefund() && performanceVo.getIsCanRefund() == 1) {
                LocalDateTime refundOpenDate = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getRefundOpenTime());
                LocalDateTime refundCloseDate = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getRefundCloseTime());
                if (LocalDateTime.now().isAfter(refundOpenDate) && LocalDateTime.now().isBefore(refundCloseDate)
                        && ticketVo.getCounts() == 1) {

                } else {
                    return "暂不支持退款";
                }
            } else {
                return "暂不支持退款";
            }

            List<KylinOrderTicketEntitiesVo> entitiesVos = orderTicketVo.getEntitiesVoList();
            for (KylinOrderTicketEntitiesVo item : entitiesVos) {
                if (item.getOrderTicketEntitiesId().equals(orderTicketEntitiesId)) {
                    orderTicketEntitiesVo = item;
                }
            }
            if (null == orderTicketEntitiesVo) {
                return "订单不存在";
            }

            BigDecimal refundSinglePrice = dataUtils.getCanRefundOrderEntitiesPrice(orderTicketVo, kylinOrderRefundsVoBaseList, orderTicketEntitiesId);
            if (refundSinglePrice.compareTo(BigDecimal.ZERO) <= 0) {
                return "申请金额不得小于0";
            }

            Map token = CurrentUtil.getTokenClaims();
            String username = StringUtils.defaultString(((String) token.get("nickname")), "");
            String result = refundsStatusService.userOrderTicketRefunding(orderTicketVo, refundSinglePrice.doubleValue(), orderTicketEntitiesId, reason, picList, uid, username, kylinOrderRefundsVoBaseList.size());
            if (result != "") {
                // 退款申请成功 异步去快递下单
                expressPlace(sendExpressType, expressNumber, expressContacts, expressPhone, sendExpressAddress, appointmentTime, orderTicketVo, performanceVo);
                return result;
            } else {
                return "申请失败";
            }
        } catch (Exception e) {
            e.printStackTrace();
            return "申请失败";
        }
    }

    @Async
    public void expressPlace(Integer sendExpressType, String expressNumber, String expressContacts, String expressPhone, String sendExpressAddress, String appointmentTime, KylinOrderTicketVo orderTicketVo, KylinPerformanceVo performanceVo) {
        if (sendExpressType == 1) { // 上门取件
            // 请求下单数据
            Map<String, String> hBody = new HashMap<>();
            hBody.put("custid", custid);
            hBody.put("jContact", expressContacts);
            hBody.put("jMobile", expressPhone);
            hBody.put("jAddress", sendExpressAddress);
            hBody.put("sendStartTime", appointmentTime);

            Integer isRefundExpress = performanceVo.getIsRefundExpress();
            if (isRefundExpress == 1) { // 1用户承担 0无 公司月结
                hBody.put("payMethod", "1");// 运费付款方式：0-寄付月结；1-寄付现结；2-收方付；3-第三方付；
            } else {
                hBody.put("payMethod", "2");// 运费付款方式：0-寄付月结；1-寄付现结；2-收方付；3-第三方付；
            }
            hBody.put("expressType", expressType.toString());// 顺丰特快
            hBody.put("depositumInfo", depositumInfo);
            hBody.put("isDoCall", "1");  // 是否通过手持终端通知顺丰收派员上门收件，支持以下值：1-要求；0-不要求

            String orderExpressId = IDGenerator.nextSnowId();
            String OrderExpressCode = "NEWUR" + orderExpressId;
            hBody.put("orderId", OrderExpressCode);
            hBody.put("depositumNo", orderTicketVo.getNumber().toString());

            OrderRefundAddress refundAddress = dataUtils.getRefundAddress(orderTicketVo.getGetTicketType());
            hBody.put("dContact", refundAddress.getName());
            hBody.put("dTel", refundAddress.getPhone());
            hBody.put("dAddress", refundAddress.getAddress());

            // 生成签名并请求
            String result = shunfengSignUtils.generateSignatureAndRequestNew(hBody, "/public/order/v1/placeOrder");
            HashMap hashMap = new HashMap();
            try {
                hashMap = JsonUtils.fromJson(result, HashMap.class);
            } catch (Exception e) {
                log.info("expressPlaceExceptionInfo sendExpressType:[{}], sendExpressAddress:[{}], appointmentTime:[{}], expressNumber:[{}], orderTicketVo:[{}]", sendExpressType, sendExpressAddress, appointmentTime, expressNumber, orderTicketVo);
                log.error("expressPlaceExceptionError", e);
            }
            if (null == hashMap.get("succ") || hashMap.get("succ").equals("fail")) {
                String msg = "";
                if (null == hashMap.get("succ")) {
                    msg = result;
                } else {
                    msg = (String) hashMap.get("msg");
                }
                log.info("expressPlaceExceptionInfo sendExpressType:[{}], sendExpressAddress:[{}], appointmentTime:[{}], expressNumber:[{}], orderTicketVo:[{}]", sendExpressType, sendExpressAddress, appointmentTime, expressNumber, orderTicketVo);
                log.error("expressPlaceResultError", msg);
            } else {
                HashMap hashMapResult = (HashMap) hashMap.get("result");
                // 生成预快递单 REDIS 队列入数据库
                LocalDateTime now = LocalDateTime.now();
                LinkedList<String> sqls = CollectionUtil.linkedListString();
                sqls.add(SqlMapping.get("kylin_order_refund.refundOrderExpress"));
                LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
                sqlsDataA.add(new Object[]{
                        orderExpressId, orderTicketVo.getPerformanceId(), orderTicketVo.getOrderTicketsId(), OrderExpressCode, hashMapResult.get("mailno"), expressType, hashMapResult.get("filter_result"), hashMapResult.get("remark"), KylinTableStatusConst.ORDER_EXPRESS_STATUS2
                        , 2, sendExpressType, expressContacts, expressPhone, sendExpressAddress, appointmentTime
                        , hashMapResult.get("proName"), hashMapResult.get("cargoTypeCode"), hashMapResult.get("limitTypeCode"), hashMapResult.get("expressTypeCode"), hashMapResult.get("goodsValueTotal"), hashMapResult.get("goodsNumber")
                        , now
                });
                queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_ORDER_REFUND_EXPRESS.getKey(),
                        SqlMapping.gets(sqls, sqlsDataA));

                KylinOrderExpressVo kylinOrderExpressVo = KylinOrderExpressVo.getNew();
                kylinOrderExpressVo.setOrderExpressId(orderExpressId);
                kylinOrderExpressVo.setOrderTicketsId(orderTicketVo.getOrderTicketsId());
                kylinOrderExpressVo.setOrderExpressCode(OrderExpressCode);
                kylinOrderExpressVo.setMailno((String) hashMapResult.get("mailno"));
                kylinOrderExpressVo.setExpressStatus(KylinTableStatusConst.ORDER_EXPRESS_STATUS2);
                kylinOrderExpressVo.setSendExpressType(sendExpressType);
                dataUtils.setOrderRefundExpressInfo(orderTicketVo.getOrderTicketsId(), kylinOrderExpressVo);
            }
        } else if (sendExpressType == 2) { // 自主发货
            // 生成预快递单 REDIS 队列入数据库
            String orderExpressId = IDGenerator.nextSnowId();
            String OrderExpressCode = "NEWUR" + orderExpressId;
            LocalDateTime now = LocalDateTime.now();
            LinkedList<String> sqls = CollectionUtil.linkedListString();
            sqls.add(SqlMapping.get("kylin_order_refund.refundOrderExpress"));
            LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
            sqlsDataA.add(new Object[]{
                    orderExpressId, orderTicketVo.getPerformanceId(), orderTicketVo.getOrderTicketsId(), OrderExpressCode, expressNumber, expressType, "", "", KylinTableStatusConst.ORDER_EXPRESS_STATUS2
                    , 2, sendExpressType, expressContacts, expressPhone, sendExpressAddress, appointmentTime
                    , "", "", "", "", "", ""
                    , now
            });
            queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_ORDER_REFUND_EXPRESS.getKey(),
                    SqlMapping.gets(sqls, sqlsDataA));

            KylinOrderExpressVo kylinOrderExpressVo = KylinOrderExpressVo.getNew();
            kylinOrderExpressVo.setOrderExpressId(orderExpressId);
            kylinOrderExpressVo.setOrderTicketsId(orderTicketVo.getOrderTicketsId());
            kylinOrderExpressVo.setOrderExpressCode(OrderExpressCode);
            kylinOrderExpressVo.setMailno(expressNumber);
            kylinOrderExpressVo.setExpressStatus(KylinTableStatusConst.ORDER_EXPRESS_STATUS2);
            kylinOrderExpressVo.setSendExpressType(sendExpressType);
            dataUtils.setOrderRefundExpressInfo(orderTicketVo.getOrderTicketsId(), kylinOrderExpressVo);
        }
    }

    @Override
    public ResponseDto<Boolean> orderRefundWithdraw(String orderRefundsId) {

        LinkedList<String> sqls = CollectionUtil.linkedListString();
        LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
        LinkedList<Object[]> sqlsDataB = CollectionUtil.linkedListObjectArr();
        LinkedList<Object[]> sqlsDataC = CollectionUtil.linkedListObjectArr();

        LocalDateTime time = LocalDateTime.now();
        String strTime = DateUtil.Formatter.yyyyMMddHHmmss.format(time);
        try {
            KylinOrderRefundsVo orderRefundsVo = dataUtils.getOrderRefundVo(orderRefundsId);
            if (!orderRefundsVo.getStatus().equals(0)) {
                return ResponseDto.failure(ErrorMapping.get("20020"));
            }
            List<KylinOrderRefundEntitiesVo> refundEntities = orderRefundsVo.getOrderRefundEntitiesVoList();
            String orderTicketsId = orderRefundsVo.getOrderTicketsId();
            KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(orderTicketsId);

            // 更新数据
            // 订单状态表 判断是退到正在退款 已付款 部分退款？(取消，完成，失败)
            int newStatus;
            int refundingCount = 0;
            List<KylinOrderRefundsVo> orderRefundsVoList = dataUtils.getOrderRefundVoByOrderId(orderTicketsId);
            for (KylinOrderRefundsVo item : orderRefundsVoList) {
                int status = item.getStatus();
                log.info("status = " + status);
                if (status != 2 && status != 4 && status != 5 && !item.getOrderRefundsId().equals(orderRefundsId)) {
                    refundingCount += 1;
                }
            }

            if (refundingCount > 0) { // 存在其他正在退款的订单
                newStatus = KylinTableStatusConst.ORDER_STATUS3;
            } else {
                if (orderTicketVo.getPriceRefund().doubleValue() > 0) { // 已经有退完的 那就是部分退款了
                    newStatus = KylinTableStatusConst.ORDER_STATUS6;
                } else if (orderTicketVo.getStatus() != 2) {
                    newStatus = KylinTableStatusConst.ORDER_STATUS1;
                } else {
                    newStatus = KylinTableStatusConst.ORDER_STATUS2;
                }
            }

            KylinOrderTicketStatus orderStatusTable = KylinOrderTicketStatus.getNew();
            log.info("newStatus = " + newStatus);
            orderStatusTable.setStatus(newStatus);
            orderStatusTable.setUpdatedAt(time);
            LocalDateTime now = LocalDateTime.now();
            sqlsDataA.add(new Object[]{
                    orderStatusTable.getStatus(), orderStatusTable.getUpdatedAt(), orderTicketsId, now, now
            });

            KylinOrderTicketVo kylinOrderTicketVo = KylinOrderTicketVo.getNew();
            kylinOrderTicketVo.setStatus(newStatus);
            kylinOrderTicketVo.setUpdatedAt(strTime);
            kylinOrderTicketVo.setChangeDate(time);
            BasicDBObject orderObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketVo)));
            mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderTicketsId").is(orderTicketsId)).getQueryObject(),
                    orderObject
            );

            // 入场人
            for (KylinOrderRefundEntitiesVo item : refundEntities) {
                // 订单状态表 判断是退到正在退款 已付款 部分退款？(取消，完成，失败)
                int newIsPayment = 0;
                int refundingEntitiesCount = 0;
                for (KylinOrderRefundsVo item2 : orderRefundsVoList) {
                    int status = item2.getStatus();
                    if (!item2.getOrderRefundsId().equals(orderRefundsId) && (status != 2 && status != 4 && status != 5)) {
                        for (KylinOrderRefundEntitiesVo item3 : item2.getOrderRefundEntitiesVoList()) {
                            if (item3.getOrderTicketEntitiesId().equals(item.getOrderTicketEntitiesId())) {
                                refundingEntitiesCount += 1;
                            }
                        }
                    }

                    /*for (KylinOrderRefundEntitiesVo item3 : item2.getOrderRefundEntitiesVoList()) {
                        if (item3.getOrderTicketEntitiesId().equals(item.getOrderTicketEntitiesId())) {
                            entitiesAllPrice.add(item3.getRefundPrice());
                        }
                    }*/

                }

                KylinOrderTicketEntitiesVo entitiesVo = null;
                for (KylinOrderTicketEntitiesVo entitiesVo1 : orderTicketVo.getEntitiesVoList()) {
                    if (entitiesVo1.getOrderTicketEntitiesId().equals(item.getOrderTicketEntitiesId())) {
                        entitiesVo = entitiesVo1;
                        break;
                    }
                }

                log.info("getRefundPrice =" + item.getRefundPrice());
                if (refundingEntitiesCount > 0) { // 存在其他正在退款的该入场人订单
                    newIsPayment = KylinTableStatusConst.ENTITIES_IS_PAYMENT2;
                } else {
                    if (orderTicketVo.getPriceRefund().compareTo(BigDecimal.ZERO) > 0) { // 已经有退完的 那就是部分退款了
                        newIsPayment = KylinTableStatusConst.ENTITIES_IS_PAYMENT4;
                    } else {
                        newIsPayment = KylinTableStatusConst.ENTITIES_IS_PAYMENT1;
                    }
                }
                KylinOrderTicketEntities entitiesTable = KylinOrderTicketEntities.getNew();
                entitiesTable.setIsPayment(newIsPayment);
                entitiesTable.setUpdatedAt(time);

                log.info("sqlsDataB data = " + entitiesTable.getIsPayment());

                sqlsDataB.add(new Object[]{
                        entitiesTable.getIsPayment(), entitiesTable.getUpdatedAt(), item.getOrderTicketEntitiesId(), now, now
                });

                KylinOrderTicketEntitiesVo kylinOrderTicketEntitiesVo = KylinOrderTicketEntitiesVo.getNew();
                kylinOrderTicketEntitiesVo.setIsPayment(newIsPayment);
                kylinOrderTicketEntitiesVo.setUpdatedAt(strTime);
                kylinOrderTicketEntitiesVo.setChangeDate(time);
//                for (KylinOrderRefundEntitiesVo item2:orderRefundsVo.getOrderRefundEntitiesVoList()){
//                    if(item2.getOrderTicketEntitiesId().equalsIgnoreCase(item.getOrderTicketEntitiesId())){
//                        log.info("entitiesVo.getRefundPrice() = "+entitiesVo.getRefundPrice());
//                        log.info("item2.getRefundPrice() = "+item2.getRefundPrice());
                kylinOrderTicketEntitiesVo.setRefundPrice(entitiesVo.getRefundPrice());
//                    }
//                }

                log.info("entitiesVo.getRefundPrice() = " + entitiesVo.getRefundPrice());
                BasicDBObject entitiesObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketEntitiesVo)));
                mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).updateOne(
                        Query.query(Criteria.where("orderTicketEntitiesId").is(item.getOrderTicketEntitiesId())).getQueryObject(),
                        entitiesObject
                );

                dataUtils.delOrderTicketEntitiesRedis(item.getOrderTicketEntitiesId());
            }

            orderUtils.resetOrderListVo(orderTicketVo.getUserId(), 2, orderTicketsId, null);

            // 退款细节取消
            KylinOrderRefunds kylinOrderRefunds = KylinOrderRefunds.getNew();
            kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_CANCEL);
            kylinOrderRefunds.setUpdatedAt(LocalDateTime.now());

            mongoTemplate.getCollection(KylinOrderRefundsVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderRefundsId").is(orderRefundsId)).getQueryObject(),
                    new Document("$set", new Document("status", KylinTableStatusConst.ORDER_REFUND_STATUS_CANCEL).append("updatedAt", time))
            );

            sqlsDataC.add(new Object[]{
                    KylinTableStatusConst.ORDER_REFUND_STATUS_CANCEL, time, orderRefundsId
            });

            dataUtils.delOrderRefundVo(orderRefundsId);
            dataUtils.delOrderRefundVoByOrderId(orderTicketsId);
            dataUtils.delOrderTicketRedis(orderTicketsId);
            orderUtils.resetOrderListVo(CurrentUtil.getCurrentUid(), 2, orderTicketsId, null);


            sqls.add(SqlMapping.get("kylin_order_ticket_status.withDraw"));
            sqls.add(SqlMapping.get("kylin_order_ticket_entities.withDraw"));
            sqls.add(SqlMapping.get("kylin_order_refund.withDraw"));
            queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_ORDER_WITHDRAW.getKey(),
                    SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataC));
            return ResponseDto.success(true);
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseDto.failure(ErrorMapping.get("20020"));
        }
    }

    @Override
    public ResponseDto<String> orderTransfer(String orderId, String transferUid, String transferMobile) {
        String uid = CurrentUtil.getCurrentUid();
        KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(orderId);
        LocalDateTime now = LocalDateTime.now();
        if (null != orderTicketVo) {
            if (!orderTicketVo.getUserId().equals(uid)) {
                return ResponseDto.success("无权查看");
            }
            if (!orderTicketVo.getTransferStatus().equals(0)) {
                return ResponseDto.failure("已转票一次，无法再次转票");
            }
            Boolean isCanTransfer;
            KylinPerformanceVo performanceVo = dataUtils.getPerformanceVo(orderTicketVo.getPerformanceId());

            //判断是否可转增
            if (null != performanceVo.getIsTransfer() && performanceVo.getIsTransfer() == 1) {
                LocalDateTime transferStartTime = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getTransferStartTime());
                LocalDateTime transferEndTime = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getTransferEndTime());
                if (LocalDateTime.now().isAfter(transferStartTime) && LocalDateTime.now().isBefore(transferEndTime)
                        && orderTicketVo.getStatus().equals(1) && orderTicketVo.getTransferStatus().equals(0)) {
                    isCanTransfer = true;
                } else {
                    isCanTransfer = false;
                }
            } else {
                isCanTransfer = false;
            }
            if (!isCanTransfer) {
                return ResponseDto.failure("该订单不支持转赠");
            }

            //判断对方是否有转赠订单
            if (dataUtils.hasTransferOrder(transferUid)) {
                return ResponseDto.failure("该用户有待接收的转赠订单，暂不能转赠");
            }

            LinkedList<String> sqls = CollectionUtil.linkedListString();
            //持久化数据
            sqls.add(SqlMapping.get("kylin_order_task.insert"));
            LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
            sqlsDataA.add(new Object[]{
                    orderTicketVo.getOrderTicketsId(), 10, now
            });

            String transferTime = DateUtil.Formatter.yyyyMMddHHmmss.format(LocalDateTime.now());
            //修改被转赠订单 redis
            orderTicketVo.setTransferStatus(1);
            orderTicketVo.setTransferTime(transferTime);
            orderTicketVo.setTransferUid(transferUid);

            dataUtils.setOrderTicketVo(orderTicketVo.getOrderTicketsId(), orderTicketVo);
            orderUtils.resetOrderListVo(uid, 2, orderTicketVo.getOrderTicketsId(), orderTicketVo);
            //修改被转赠订单 mongo
            mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderTicketsId").is(orderTicketVo.getOrderTicketsId())).getQueryObject(),
                    new Document("$set", new Document("transferStatus", orderTicketVo.getTransferStatus())
                            .append("transferUid", transferUid).append("transferTime", transferTime).append("updatedAt", DateUtil.Formatter.yyyyMMddHHmmss.format(now)))
            );
            //修改被转赠订单 mysql
            sqls.add(SqlMapping.get("kylin_order_ticket_status.transfer.update"));
            LinkedList<Object[]> sqlsDataB = CollectionUtil.linkedListObjectArr();
            sqlsDataB.add(new Object[]{
                    1, now, orderTicketVo.getOrderTicketsId(), now, now
            });
            sqls.add(SqlMapping.get("kylin_order_ticket_relation.transfer.update"));
            LinkedList<Object[]> sqlsDataC = CollectionUtil.linkedListObjectArr();
            sqlsDataC.add(new Object[]{
                    transferUid, orderTicketVo.getOrderTicketsId(), now, orderTicketVo.getOrderTicketsId(), now, now
            });

            //生成被转赠订单独立redis
            orderTicketVo.setOrderTicketsId(IDGenerator.nextSnowId());
            orderTicketVo.setQrCode(IDGenerator.ticketQrCode(orderTicketVo.getOrderTicketsId()));
            orderTicketVo.setTransferId(orderId);
            orderTicketVo.setTransferStatus(4);
            orderTicketVo.setUserId(transferUid);
            orderTicketVo.setUserMobile(transferMobile);
            dataUtils.setTransferOrder(transferUid, orderTicketVo);

            //入库
            queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_TRANSFER.getKey(),
                    SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataC));

        } else {
            return ResponseDto.failure("转票失败");
        }
        return ResponseDto.success("转票成功");
    }

    @Override
    public ResponseDto<String> orderTransferWithdraw(String orderId) {
        String uid = CurrentUtil.getCurrentUid();
        KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(orderId);
        LocalDateTime now = LocalDateTime.now();
        if (null != orderTicketVo) {
            if (!orderTicketVo.getUserId().equals(uid)) {
                return ResponseDto.success("无权查看");
            }
            if (!orderTicketVo.getTransferStatus().equals(1)) {
                return ResponseDto.failure("无法撤回");
            }
            LinkedList<String> sqls = CollectionUtil.linkedListString();
            //删除持久化数据
            sqls.add(SqlMapping.get("kylin_order_task.delete"));
            LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
            sqlsDataA.add(new Object[]{
                    orderTicketVo.getOrderTicketsId()
            });
            //修改被转赠订单 redis
            orderTicketVo.setTransferStatus(0);
            dataUtils.setOrderTicketVo(orderTicketVo.getOrderTicketsId(), orderTicketVo);
            orderUtils.resetOrderListVo(uid, 2, orderTicketVo.getOrderTicketsId(), orderTicketVo);
            //修改被转赠订单 mongo
            mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderTicketsId").is(orderTicketVo.getOrderTicketsId())).getQueryObject(),
                    new Document("$set", new Document("transferStatus", orderTicketVo.getTransferStatus()).append("updatedAt", DateUtil.Formatter.yyyyMMddHHmmss.format(now)))
            );
            //修改被转赠订单 mysql
            sqls.add(SqlMapping.get("kylin_order_ticket_status.transfer.update"));
            LinkedList<Object[]> sqlsDataB = CollectionUtil.linkedListObjectArr();
            sqlsDataB.add(new Object[]{
                    0, now, orderTicketVo.getOrderTicketsId(), now, now
            });
            sqls.add(SqlMapping.get("kylin_order_ticket_relation.transfer.update"));
            LinkedList<Object[]> sqlsDataC = CollectionUtil.linkedListObjectArr();
            sqlsDataC.add(new Object[]{
                    "", "", now, orderTicketVo.getOrderTicketsId(), now, now
            });
            //删除被转赠订单独立redis
            dataUtils.delTransferOrder(orderTicketVo.getTransferUid());
            //入库
            queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_TRANSFER.getKey(),
                    SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataC));
        } else {
            return ResponseDto.failure("撤回失败");
        }
        return ResponseDto.success("撤回成功");
    }

    @Override
    public ResponseDto<String> orderTransferAccept(String enterIdList) {
        String uid = CurrentUtil.getCurrentUid();
        Integer enterSize;
        if (enterIdList == null || enterIdList.equals("")) {
            enterSize = 0;
            enterIdList = "";
        } else {
            enterSize = enterIdList.split(",").length;
        }
        KylinOrderTicketVo orderTicketVo = dataUtils.getTransferOrder(uid);
        if (orderTicketVo == null) {
            return ResponseDto.failure("无订单");
        }
        if (!orderTicketVo.getTransferStatus().equals(4)) {
            return ResponseDto.failure("无法接收");
        }
        LocalDateTime now = LocalDateTime.now();
        if (orderTicketVo != null) {
            KylinPerformanceVo performanceData = dataUtils.getPerformanceVo(orderTicketVo.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(orderTicketVo.getTimeId())) {
                    ticketTimesData = timeItem;
                    for (int y = 0; y < ticketTimesData.getTicketList().size(); y++) {
                        KylinTicketVo ticketItem = ticketTimesData.getTicketList().get(y);
                        if (ticketItem.getTicketsId().equals(orderTicketVo.getTicketId())) {
                            ticketData = ticketItem;
                            break;
                        }
                    }
                    break;
                }
            }

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

            //实名判断
            if (isTrueName == 1 && enterSize <= 0) {
                return ResponseDto.failure(ErrorMapping.get("20015"));//需要实名 未实名
            }
            if (isTrueName == 1 && enterSize != orderTicketVo.getNumber()) {
                return ResponseDto.failure(ErrorMapping.get("20015"));//入场人数量错误
            }

            //学生票 判断
            List<AdamEntersVo> entersVoList = ObjectUtil.cloneArrayListObject();
            if (isTrueName == 1) {
                List<AdamEntersVo> adamEnters = orderUtils.getEnters(enterIdList, uid);
                if (adamEnters == null) {
                    return ResponseDto.failure("入场人数据异常");//乱七八糟异常
                }
                for (AdamEntersVo item : adamEnters) {
                    entersVoList.add(item);
                    if (ticketData.getIsStudent() == 1) {
                        if (!item.getType().equals(1)) {
                            return ResponseDto.failure("学生票优惠核验失败，无法转票");
                        }
                        int age = IDCard.getAgeByIdCard(item.getIdCard());
                        if (age > 25) {
                            return ResponseDto.failure(ErrorMapping.get("20017"));//学生票年龄问题
                        }
                    }
                }
            }

            //限购判断 如果实名 则身份证维度限购 如果不实名则数量限购
            if (entersVoList.size() > 0) {
                for (int i = 0; i < entersVoList.size(); i++) {
                    String res1 = orderUtils.judgeOrderLimit(performanceData.getType(), uid, entersVoList.get(i).getIdCard(), performanceData.getPerformancesId(), ticketData.getTicketsId(), performanceLimit, performanceMemberLimit, ticketLimit, ticketMemberLimit, 1, 1, 0, isTrueName);
                    if (!res1.equals("")) {
                        return ResponseDto.failure(res1);//乱七八糟异常
                    }
                }
            } else {
                String res1 = orderUtils.judgeOrderLimit(performanceData.getType(), uid, "", performanceData.getPerformancesId(), ticketData.getTicketsId(), performanceLimit, performanceMemberLimit, ticketLimit, ticketMemberLimit, orderTicketVo.getNumber(), orderTicketVo.getNumber(), 0, isTrueName);
                if (!res1.equals("")) {
                    return ResponseDto.failure(res1);//乱七八糟异常
                }
            }

            LinkedList<String> sqls = CollectionUtil.linkedListString();
            //删除持久化数据
            sqls.add(SqlMapping.get("kylin_order_task.delete"));
            LinkedList<Object[]> sqlsDataE = CollectionUtil.linkedListObjectArr();
            sqlsDataE.add(new Object[]{
                    orderTicketVo.getTransferId()
            });

            String source = orderTicketVo.getOrderType();
            String version = orderTicketVo.getOrderVersion();

            //生成订单 order_ticket
            KylinOrderTickets orderTickets = KylinOrderTickets.getNew();
            String orderTicketId = orderTicketVo.getOrderTicketsId();
            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(orderTicketVo.getPerformanceTitle());
            orderTickets.setOrderCode(IDGenerator.ticketOrderCode(orderTicketId));
            orderTickets.setPayCode(orderTicketVo.getPayCode());
            orderTickets.setQrCode(orderTicketVo.getQrCode());
            orderTickets.setOrderType(source);
            orderTickets.setOrderVersion(version);
            orderTickets.setNumber(orderTicketVo.getNumber());
            orderTickets.setPrice(orderTicketVo.getPrice());
            orderTickets.setPriceMember(orderTicketVo.getPriceMember());
            orderTickets.setPriceTotal(orderTicketVo.getPriceTotal());
            orderTickets.setPriceActual(orderTickets.getPriceActual() == null ? BigDecimal.ZERO : orderTickets.getPriceActual());
            orderTickets.setPriceVoucher(orderTicketVo.getPriceVoucher());
            orderTickets.setPriceExpress(orderTicketVo.getPriceExpress());
            orderTickets.setPriceRefund(orderTicketVo.getPriceRefund());
            orderTickets.setRefundNumber(orderTicketVo.getRefundNumber());
            orderTickets.setPayType(orderTicketVo.getPayType());
            orderTickets.setPaymentType(orderTicketVo.getPaymentType());
            orderTickets.setTimePay(orderTicketVo.getTimePay());
            orderTickets.setPaymentId("TRANSFER");

            orderTickets.setExpressContacts(orderTicketVo.getExpressContacts());
            orderTickets.setExpressAddress(orderTicketVo.getExpressAddress());
            orderTickets.setExpressPhone(orderTicketVo.getExpressPhone());
            orderTickets.setCity("");//            orderTickets.setCity(addressesVo.getCity());
            orderTickets.setProvince("");//            orderTickets.setProvince(addressesVo.getProvince());
            orderTickets.setCounty("");//            orderTickets.setCounty(addressesVo.getCounty());
            orderTickets.setGetTicketType(orderTicketVo.getGetTicketType());
            orderTickets.setCouponType(orderTicketVo.getCouponType());
            orderTickets.setGetTicketDescribe(orderTicketVo.getGetTicketDescribe());
            orderTickets.setPayCountdownMinute(orderTicketVo.getPayCountdownMinute());
            orderTickets.setCreatedAt(now);
            orderTickets.setUpdatedAt(null);

            //生成订单 order_ticket_status
            KylinOrderTicketStatus orderTicketStatus = KylinOrderTicketStatus.getNew();
            String orderTicketStatusId = IDGenerator.nextSnowId();
            orderTicketStatus.setOrderTicketStatusId(orderTicketStatusId);
            orderTicketStatus.setOrderId(orderTicketId);
            orderTicketStatus.setExpressType(orderTicketVo.getExpressType());
            orderTicketStatus.setTransferStatus(3);
            orderTicketStatus.setStatus(orderTicketVo.getStatus());
            orderTicketStatus.setIsStudent(orderTicketVo.getIsStudent());
            orderTicketStatus.setPayStatus(orderTicketVo.getPayStatus());
            orderTicketStatus.setCreatedAt(now);
            orderTicketStatus.setUpdatedAt(null);
            sqls.add(SqlMapping.get("kylin_order_ticket_status.add"));
            LinkedList<Object[]> sqlsDataB = CollectionUtil.linkedListObjectArr();
            sqlsDataB.add(orderTicketStatus.getAddObject());

            //生成订单 order_ticket_relation
            KylinOrderTicketRelations orderTicketRelations = KylinOrderTicketRelations.getNew();
            String orderTicketRelationId = IDGenerator.nextSnowId();
            orderTicketRelations.setOrderTicketRelationsId(orderTicketRelationId);
            orderTicketRelations.setOrderId(orderTicketId);
            orderTicketRelations.setTransferId(orderTicketVo.getTransferId());
            orderTicketRelations.setLiveId(orderTicketVo.getLiveId());
            orderTicketRelations.setAgentId(orderTicketVo.getAgentId());
            orderTicketRelations.setIsMember(orderTicketVo.getIsMember());
            orderTicketRelations.setPerformanceId(performanceData.getPerformancesId());
            orderTicketRelations.setTimeId(ticketTimesData.getTimeId());
            orderTicketRelations.setTicketId(ticketData.getTicketsId());
            orderTicketRelations.setCreatedAt(now);
            orderTicketRelations.setUpdatedAt(null);
            sqls.add(SqlMapping.get("kylin_order_ticket_relation.add"));
            LinkedList<Object[]> sqlsDataC = CollectionUtil.linkedListObjectArr();
            sqlsDataC.add(orderTicketRelations.getAddObject());

            //生成票
            KylinOrderTicketEntities orderTicketEntities = KylinOrderTicketEntities.getNew();
            LinkedList<Object[]> sqlsDataD = CollectionUtil.linkedListObjectArr();
            sqls.add(SqlMapping.get("kylin_order_ticket_entities.add"));
            for (int i = 0; i < orderTicketVo.getEntitiesVoList().size(); i++) {
                KylinOrderTicketEntitiesVo entitiesVo = orderTicketVo.getEntitiesVoList().get(i);
                String orderTicketEntitiesId = entitiesVo.getOrderTicketEntitiesId();
                orderTicketEntities.setOrderTicketEntitiesId(IDGenerator.nextSnowId());
                orderTicketEntities.setOrderId(orderTicketId);
                orderTicketEntities.setTicketId(ticketData.getTicketsId());
                orderTicketEntities.setUserId(uid);
                orderTicketEntities.setPerformanceId(performanceData.getPerformancesId());
                orderTicketEntities.setTimeId(ticketTimesData.getTicketTimesId());
                orderTicketEntities.setEnterType(entitiesVo.getEnterType());

                if (entersVoList.size() > 0) {
                    orderTicketEntities.setEnterName(entersVoList.get(i).getName());
                    orderTicketEntities.setEnterMobile(entersVoList.get(i).getMobile());
                    orderTicketEntities.setEnterIdCode(entersVoList.get(i).getIdCard());
                } else {
                    orderTicketEntities.setEnterName(entitiesVo.getEnterName());
                    orderTicketEntities.setEnterMobile(entitiesVo.getEnterMobile());
                    orderTicketEntities.setEnterIdCode(entitiesVo.getEnterIdCode());
                }

                orderTicketEntities.setStatus(entitiesVo.getStatus());
                orderTicketEntities.setSysDamai(entitiesVo.getSysDamai());
                orderTicketEntities.setCheckClient(entitiesVo.getCheckClient());
                orderTicketEntities.setIsPayment(entitiesVo.getIsPayment());
                orderTicketEntities.setRefundPrice(entitiesVo.getRefundPrice());
                orderTicketEntities.setComment("");
                orderTicketEntities.setCreatedAt(now);
                orderTicketEntities.setUpdatedAt(null);
                sqlsDataD.add(orderTicketEntities.getAddObject());
                // 生成vo
                KylinOrderTicketEntitiesVo orderTicketEntitiesVo = KylinOrderTicketEntitiesVo.getNew();
                BeanUtils.copyProperties(orderTicketEntities, orderTicketEntitiesVo);
                orderTicketEntitiesVo.setPerformanceTitle(performanceData.getTitle());
                orderTicketEntitiesVo.setTicketTitle(ticketData.getTitle());
                orderTicketEntitiesVo.setUseStart(ticketData.getUseStart());
                orderTicketEntitiesVo.setUseEnd(ticketData.getUseEnd());
                orderTicketEntitiesVo.setCreatedAt(orderTicketEntities.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                orderTicketEntitiesVo.setUpdatedAt(null);
                orderTicketEntitiesVo.setChangeDate(orderTicketEntities.getCreatedAt());
                mongoTemplate.insert(orderTicketEntitiesVo, KylinOrderTicketEntitiesVo.class.getSimpleName());
                dataUtils.changeBuyInfo(orderTicketEntitiesVo.getUserId(), orderTicketEntitiesVo.getEnterIdCode(), orderTicketEntitiesVo.getPerformanceId(), orderTicketEntitiesVo.getTicketId(), 1);
            }

            orderTickets.setPayType(orderTicketVo.getPayType());
            orderTickets.setPayCode(orderTicketVo.getPayCode());

            sqls.add(SqlMapping.get("kylin_order_ticket.add"));
            LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
            sqlsDataA.add(orderTickets.getAddObject());
            //删除被转赠订单独立redis
            dataUtils.delTransferOrder(uid);
            // 生成vo
            orderTicketVo.setTransferStatus(3);
            orderTicketVo.setOrderCode(orderTickets.getOrderCode());
            orderTicketVo.setCreatedAt(orderTickets.getCreatedAt().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            orderTicketVo.setChangeDate(orderTickets.getCreatedAt());
            orderUtils.resetOrderListVo(uid, 1, orderTicketVo.getOrderTicketsId(), orderTicketVo);
            mongoTemplate.insert(orderTicketVo, KylinOrderTicketVo.class.getSimpleName());

            //原来vo
            KylinOrderTicketVo orderTicketVoTransfer = dataUtils.getOrderTicketVo(orderTicketVo.getTransferId());
            orderTicketVoTransfer.setTransferStatus(2);
            orderTicketVoTransfer.setChangeDate(now);
            orderTicketVoTransfer.setUpdatedAt(DateUtil.Formatter.yyyyMMddHHmmss.format(now));
            dataUtils.setOrderTicketVo(orderTicketVoTransfer.getOrderTicketsId(), orderTicketVoTransfer);
            orderUtils.resetOrderListVo(orderTicketVoTransfer.getUserId(), 2, orderTicketVoTransfer.getOrderTicketsId(), orderTicketVoTransfer);
            //原订单mongo
            mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderTicketsId").is(orderTicketVoTransfer.getOrderTicketsId())).getQueryObject(),
                    new Document("$set", new Document("transferStatus", orderTicketVoTransfer.getTransferStatus()).append("updatedAt", DateUtil.Formatter.yyyyMMddHHmmss.format(now)))
            );
            //sql
            sqls.add(SqlMapping.get("kylin_order_ticket_status.transfer.update"));
            LinkedList<Object[]> sqlsDataA2 = CollectionUtil.linkedListObjectArr();
            sqlsDataA2.add(new Object[]{
                    orderTicketVoTransfer.getTransferStatus(), now, orderTicketVoTransfer.getOrderTicketsId(), now, now
            });

            // 执行sql
            String sqlData = SqlMapping.gets(sqls, sqlsDataE, sqlsDataB, sqlsDataC, sqlsDataD, sqlsDataA, sqlsDataA2);
            queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_TRANSFER_RESULT.getKey(),
                    sqlData);
            log.info(UserPathDto.setData("接收转赠订单", enterIdList, "SUCCESS"));
        } else {
            return ResponseDto.failure("接收失败");
        }
        return ResponseDto.success("接收成功");
    }

    @Override
    public ResponseDto<String> orderTransferReject() {
        String uid = CurrentUtil.getCurrentUid();
        KylinOrderTicketVo orderTicketVo = dataUtils.getTransferOrder(uid);
        LocalDateTime now = LocalDateTime.now();
        if (null != orderTicketVo) {
            if (!orderTicketVo.getUserId().equals(uid)) {
                return ResponseDto.success("无权查看");
            }
            if (!orderTicketVo.getTransferStatus().equals(4)) {
                return ResponseDto.failure("无法拒收");
            }
            KylinOrderTicketVo orderTicketVoTransfer = dataUtils.getOrderTicketVo(orderTicketVo.getTransferId());

            LinkedList<String> sqls = CollectionUtil.linkedListString();
            //删除持久化数据
            sqls.add(SqlMapping.get("kylin_order_task.delete"));
            LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
            sqlsDataA.add(new Object[]{
                    orderTicketVo.getTransferId()
            });
            //修改被转赠订单 redis
            orderTicketVoTransfer.setTransferStatus(0);
            dataUtils.setOrderTicketVo(orderTicketVoTransfer.getOrderTicketsId(), orderTicketVoTransfer);
            orderUtils.resetOrderListVo(orderTicketVoTransfer.getUserId(), 2, orderTicketVoTransfer.getOrderTicketsId(), orderTicketVoTransfer);
            //修改被转赠订单 mongo
            mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderTicketsId").is(orderTicketVoTransfer.getOrderTicketsId())).getQueryObject(),
                    new Document("$set", new Document("transferStatus", orderTicketVoTransfer.getTransferStatus()).append("updatedAt", DateUtil.Formatter.yyyyMMddHHmmss.format(now)))
            );
            //修改被转赠订单 mysql
            sqls.add(SqlMapping.get("kylin_order_ticket_status.transfer.update"));
            LinkedList<Object[]> sqlsDataB = CollectionUtil.linkedListObjectArr();
            sqlsDataB.add(new Object[]{
                    0, now, orderTicketVoTransfer.getOrderTicketsId(), now, now
            });
            sqls.add(SqlMapping.get("kylin_order_ticket_relation.transfer.update"));
            LinkedList<Object[]> sqlsDataC = CollectionUtil.linkedListObjectArr();
            sqlsDataC.add(new Object[]{
                    "", "", now, orderTicketVoTransfer.getOrderTicketsId(), now, now
            });
            //删除被转赠订单独立redis
            dataUtils.delTransferOrder(orderTicketVo.getUserId());
            //入库
            queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_TRANSFER_RESULT.getKey(),
                    SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataC));
        } else {
            return ResponseDto.failure("拒收失败");
        }
        return ResponseDto.success("拒收成功");
    }

    @Override
    public ResponseDto<String> orderTransferBack(String orderId) {
        KylinOrderTicketVo vo = dataUtils.getOrderTicketVo(orderId);
        KylinOrderTicketVo vo2 = dataUtils.getOrderTicketVo(vo.getTransferId());
        LocalDateTime now = LocalDateTime.now();
        LinkedList<String> sqls = CollectionUtil.linkedListString();

        //必须开启退款
        String performanceId = vo.getPerformanceId();
        KylinPerformanceVo performanceVo = dataUtils.getPerformanceVo(performanceId);
        LocalDateTime refundOpenDate = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getRefundOpenTime());
        LocalDateTime refundCloseDate = DateUtil.Formatter.yyyyMMddHHmmss.parse(performanceVo.getRefundCloseTime());
        if (!(performanceVo.getIsCanRefund().equals(1) && LocalDateTime.now().isAfter(refundOpenDate) && LocalDateTime.now().isBefore(refundCloseDate))) {
            return ResponseDto.failure("未开启退款，不支持回退");
        }
        if (!vo.getTransferStatus().equals(3)) {
            return ResponseDto.failure("无法退回");
        }

        //修改 自己的订单 vo
        //redis
        vo.setTransferStatus(6);
        dataUtils.setOrderTicketVo(orderId, vo);
        orderUtils.resetOrderListVo(vo.getUserId(), 2, orderId, vo);
        //mongo
        mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("orderTicketsId").is(orderId)).getQueryObject(),
                new Document("$set", new Document("transferStatus", vo.getTransferStatus()).append("updatedAt", DateUtil.Formatter.yyyyMMddHHmmss.format(now)))
        );
        //mysql
        sqls.add(SqlMapping.get("kylin_order_ticket_status.transfer.update"));
        LinkedList<Object[]> sqlsDataA = CollectionUtil.linkedListObjectArr();
        sqlsDataA.add(new Object[]{
                vo.getTransferStatus(), now, orderId, now, now
        });
        sqls.add(SqlMapping.get("kylin_order_ticket_relation.transfer.update"));
        LinkedList<Object[]> sqlsDataB = CollectionUtil.linkedListObjectArr();
        sqlsDataB.add(new Object[]{
                vo.getTransferUid(), vo.getTransferId(), now, orderId, now, now
        });

        //修改 回退订单 vo2
        //redis
        vo2.setTransferStatus(5);
        dataUtils.setOrderTicketVo(vo2.getOrderTicketsId(), vo2);
        orderUtils.resetOrderListVo(vo2.getUserId(), 2, vo2.getOrderTicketsId(), vo2);
        //mongo
        mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("orderTicketsId").is(vo2.getOrderTicketsId())).getQueryObject(),
                new Document("$set", new Document("transferStatus", vo2.getTransferStatus()).append("updatedAt", DateUtil.Formatter.yyyyMMddHHmmss.format(now)))
        );
        //mysql
        sqls.add(SqlMapping.get("kylin_order_ticket_status.transfer.update"));
        LinkedList<Object[]> sqlsDataA2 = CollectionUtil.linkedListObjectArr();
        sqlsDataA2.add(new Object[]{
                vo2.getTransferStatus(), now, vo2.getOrderTicketsId(), now, now
        });
        sqls.add(SqlMapping.get("kylin_order_ticket_relation.transfer.update"));
        LinkedList<Object[]> sqlsDataB2 = CollectionUtil.linkedListObjectArr();
        sqlsDataB2.add(new Object[]{
                vo2.getTransferUid(), vo2.getTransferId(), now, vo2.getOrderTicketsId(), now, now
        });
        //入库
        queueUtils.sendMsgByRedis(MQConst.KylinQueue.SQL_TRANSFER_RESULT.getKey(),
                SqlMapping.gets(sqls, sqlsDataA, sqlsDataB, sqlsDataA2, sqlsDataB2));
        return ResponseDto.success("回退成功");
    }

}
