package com.liquidnet.client.admin.zhengzai.kylin.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.liquidnet.client.admin.common.utils.StringUtils;
import com.liquidnet.client.admin.zhengzai.kylin.utils.DataUtils;
import com.liquidnet.client.admin.zhengzai.kylin.utils.MongoVoUtils;
import com.liquidnet.client.admin.zhengzai.kylin.utils.TaobaoTicketUtils;
import com.liquidnet.commons.lang.util.*;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dto.param.RefundApplyParam;
import com.liquidnet.service.kylin.dto.param.RefundCallbackParam;
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.KylinOrderRefundsVo;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.*;
import com.mongodb.BasicDBObject;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.result.UpdateResult;
import lombok.extern.slf4j.Slf4j;
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.convert.MongoConverter;
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 org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单退款表 服务实现类 处理数据 退款后状态的变化
 * </p>
 *
 * @author jiaangxiulong
 * @since 2021-05-26
 */
@Slf4j
@Service
public class KylinRefundsStatusServiceImpl {

    @Value("${liquidnet.service.dragon.urls.refundApply}")
    private String refundApply;
    @Value("${liquidnet.service.platform.urls.ticketRefundNotify}")
    private String refundNotify;

    @Autowired
    private KylinOrderTicketsMapper kylinOrderTicketsMapper;

    @Autowired
    private KylinOrderTicketStatusMapper kylinOrderTicketStatusMapper;

    @Autowired
    private KylinOrderRefundsMapper kylinOrderRefundsMapper;

    @Autowired
    private KylinOrderTicketEntitiesMapper kylinOrderTicketEntitiesMapper;

    @Autowired
    private KylinOrderRefundsEntitiesMapper kylinOrderRefundsEntitiesMapper;

    @Autowired
    private KylinOrderTicketRelationsMapper kylinOrderTicketRelationsMapper;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    private MongoConverter mongoConverter;

    @Autowired
    private DataUtils dataUtils;

    @Autowired
    private MongoVoUtils mongoVoUtils;

    @Autowired
    private TaobaoTicketUtils taobaoTicketUtils;

    public Boolean orderTicketRefunding(
            RefundApplyParam refundApplyParam, KylinOrderTickets orderInfo, String orderTicketsId,
            BigDecimal RefundPriceExpress,
            List<String> ticketEntityIds, List<BigDecimal> entitiesPrice
            , String authId, String authName
    ) {
        if (CollectionUtil.isEmpty(ticketEntityIds)) {
            return false;
        }
        // 基础数据
        String reason = refundApplyParam.getReason();
        String orderRefundBatchesId = refundApplyParam.getOrderRefundBatchesId();
        // 本次退款票总金额
        BigDecimal entitiesPriceSum = entitiesPrice.stream().reduce(BigDecimal.ZERO, BigDecimal::add);

        // 更新数据
        // 订单状态表 和 缓存
        KylinOrderTicketStatus orderStatusTable = new KylinOrderTicketStatus();
        orderStatusTable.setStatus(KylinTableStatusConst.ORDER_STATUS3);
        orderStatusTable.setUpdatedAt(LocalDateTime.now());
        kylinOrderTicketStatusMapper.update(orderStatusTable, new UpdateWrapper<KylinOrderTicketStatus>()
                .eq("order_id", orderTicketsId));

        KylinOrderTicketVo kylinOrderTicketVo = new KylinOrderTicketVo();
        kylinOrderTicketVo.setStatus(KylinTableStatusConst.ORDER_STATUS3);
        kylinOrderTicketVo.setUpdatedAt(DateUtil.getNowTime());
        BasicDBObject orderObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketVo)));
        Document orderDoc = mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).findOneAndUpdate(
                Query.query(Criteria.where("orderTicketsId").is(orderTicketsId)).getQueryObject(),
                orderObject,
                new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
        );
        dataUtils.delOrderTicketRedis(orderTicketsId);

        // 订单入场人表 和 缓存
        for (String v : ticketEntityIds) {
            KylinOrderTicketEntities entitiesTable = new KylinOrderTicketEntities();
            entitiesTable.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT2);
            entitiesTable.setUpdatedAt(LocalDateTime.now());
            kylinOrderTicketEntitiesMapper.update(entitiesTable, new UpdateWrapper<KylinOrderTicketEntities>()
                    .eq("order_ticket_entities_id", v));

            mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderTicketEntitiesId").is(v)).getQueryObject(),
                    new Document("$set", new Document("isPayment", KylinTableStatusConst.ENTITIES_IS_PAYMENT2)
                            .append("updatedAt", DateUtil.getNowTime()))
            );

            dataUtils.delOrderTicketEntitiesRedis(v);
        }

        mongoVoUtils.resetOrderListVo(orderInfo.getUserId(), 2, orderTicketsId, null);

        // 退款明细
        KylinOrderRefunds kylinOrderRefunds = new KylinOrderRefunds();
        String orderRefundsId = IDGenerator.nextSnowId();
        kylinOrderRefunds.setOrderRefundsId(orderRefundsId);
        kylinOrderRefunds.setOrderTicketsId(orderTicketsId);
        kylinOrderRefunds.setOrderRefundBatchesId(orderRefundBatchesId);

        Integer refundCount = kylinOrderRefundsMapper.selectCount(
                new QueryWrapper<KylinOrderRefunds>()
                        .eq("order_tickets_id", orderTicketsId)
        );

        String orderRefundCode = orderInfo.getOrderCode();
        String codeNum = StringUtils.leftPad(String.valueOf(refundCount), 3, "0");
        kylinOrderRefunds.setOrderRefundCode(orderRefundCode.concat(codeNum));
        kylinOrderRefunds.setPrice(entitiesPriceSum);
        kylinOrderRefunds.setPriceExpress(RefundPriceExpress);
        kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY);

        kylinOrderRefunds.setType(KylinTableStatusConst.ORDER_REFUND_TYPE_APPLY);
        kylinOrderRefunds.setApplicantId(authId);
        kylinOrderRefunds.setApplicantName(authName);
        kylinOrderRefunds.setApplicantAt(LocalDateTime.now());
        kylinOrderRefunds.setReason(reason);
        kylinOrderRefunds.setCreatedAt(LocalDateTime.now());
        int rows = kylinOrderRefundsMapper.insert(kylinOrderRefunds);
        // 添加缓存
        KylinOrderRefundsVo kylinOrderRefundsVo = new KylinOrderRefundsVo();
        BeanUtils.copyProperties(kylinOrderRefunds, kylinOrderRefundsVo);
        mongoTemplate.insert(kylinOrderRefundsVo, KylinOrderRefundsVo.class.getSimpleName());

        // 退款入场人表
        KylinOrderRefundEntities kylinOrderRefundEntities = new KylinOrderRefundEntities();
        for (int i = 0; i <= ticketEntityIds.size() - 1; i++) {
            String orderRefundsEntitiesId = IDGenerator.nextSnowId();
            kylinOrderRefundEntities.setOrderRefundsEntitiesId(orderRefundsEntitiesId);
            kylinOrderRefundEntities.setOrderRefundsId(orderRefundsId);
            kylinOrderRefundEntities.setRefundPrice(entitiesPrice.get(i));
            kylinOrderRefundEntities.setOrderTicketEntitiesId(ticketEntityIds.get(i));
            kylinOrderRefundEntities.setCreatedAt(LocalDateTime.now());
            int rowsR = kylinOrderRefundsEntitiesMapper.insert(kylinOrderRefundEntities);
            // 添加缓存
            KylinOrderRefundEntitiesVo kylinOrderRefundEntitiesVo = new KylinOrderRefundEntitiesVo();
            BeanUtils.copyProperties(kylinOrderRefundEntities, kylinOrderRefundEntitiesVo);
            mongoTemplate.insert(kylinOrderRefundEntitiesVo, KylinOrderRefundEntitiesVo.class.getSimpleName());
        }

        List<String> orderRefundIds = new ArrayList<>();
        orderRefundIds.add(orderRefundsId);
        List<String> orderIds = new ArrayList<>();
        orderIds.add(orderTicketsId);
        dataUtils.delOrderRefundVo(orderRefundIds);
        dataUtils.delOrderRefundVoByOrderId(orderIds);

        return true;
    }

    public boolean orderTicketRefundCancel(List<KylinOrderRefunds> refundList, Boolean isUser) {
        for (KylinOrderRefunds refundInfo : refundList) {
            List<KylinOrderRefundEntities> refundEntities = kylinOrderRefundsEntitiesMapper.selectList(
                    new QueryWrapper<KylinOrderRefundEntities>().eq("order_refunds_id", refundInfo.getOrderRefundsId())
            );
            List<String> orderTicketEntitiesIdsArr = refundEntities.stream().map(KylinOrderTicketEntities -> KylinOrderTicketEntities.getOrderTicketEntitiesId()).collect(Collectors.toList());
            String orderTicketsId = refundInfo.getOrderTicketsId();
            String orderRefundsId = refundInfo.getOrderRefundsId();

            // 更新数据
            // 订单状态表 判断是退到正在退款 已付款 部分退款？(取消，完成，失败)
            int newStatus = 0;
//            Integer[] whereRefundingCount = {KylinTableStatusConst.ORDER_STATUS2, KylinTableStatusConst.ORDER_STATUS4, KylinTableStatusConst.ORDER_STATUS6};
            Integer[] whereRefundingCount = {KylinTableStatusConst.ORDER_REFUND_STATUS_CANCEL, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUNDED, KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT};
            int refundingCount = kylinOrderRefundsMapper.selectCount(
                    new QueryWrapper<KylinOrderRefunds>().eq("order_tickets_id", orderTicketsId)
                            .notIn("status", whereRefundingCount)
                            .ne("order_refunds_id", orderRefundsId)

            );
            if (refundingCount > 0) { // 存在其他正在退款的订单
                newStatus = KylinTableStatusConst.ORDER_STATUS3;
            } else {
                KylinOrderTickets orderInfo = kylinOrderTicketsMapper.selectOne(
                        new QueryWrapper<KylinOrderTickets>().eq("order_tickets_id", orderTicketsId)
                );
                if (orderInfo.getPriceRefund().compareTo(BigDecimal.ZERO) > 0) { // 已经有退完的 那就是部分退款了
                    newStatus = KylinTableStatusConst.ORDER_STATUS6;
                } else {
                    newStatus = KylinTableStatusConst.ORDER_STATUS1;
                }
            }

            KylinOrderTicketStatus orderStatusTable = new KylinOrderTicketStatus();
            orderStatusTable.setStatus(newStatus);
            orderStatusTable.setUpdatedAt(LocalDateTime.now());
            kylinOrderTicketStatusMapper.update(orderStatusTable, new UpdateWrapper<KylinOrderTicketStatus>()
                    .eq("order_id", orderTicketsId));

            KylinOrderTicketVo kylinOrderTicketVo = new KylinOrderTicketVo();
            kylinOrderTicketVo.setStatus(newStatus);
            kylinOrderTicketVo.setUpdatedAt(DateUtil.getNowTime());
            BasicDBObject orderObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketVo)));
            Document orderDoc = mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("orderTicketsId").is(orderTicketsId)).getQueryObject(),
                    orderObject,
                    new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );
            dataUtils.delOrderTicketRedis(orderTicketsId);
            KylinOrderTickets orderInfo = kylinOrderTicketsMapper.selectOne(
                    new QueryWrapper<KylinOrderTickets>().eq("order_tickets_id", orderTicketsId)
            );
            mongoVoUtils.resetOrderListVo(orderInfo.getUserId(), 2, orderTicketsId, null);

            // 入场人
            for (String entitiesId : orderTicketEntitiesIdsArr) {
                // 订单状态表 判断是退到正在退款 已付款 部分退款？(取消，完成，失败)
                int newIsPayment = 0;
                int refundingEntitiesCount = kylinOrderRefundsMapper.selectEntitiesCount(orderTicketsId, whereRefundingCount, orderRefundsId, entitiesId);
                if (refundingEntitiesCount > 0) { // 存在其他正在退款的该入场人订单
                    newIsPayment = KylinTableStatusConst.ENTITIES_IS_PAYMENT2;
                } else {
                    KylinOrderTicketEntities entitiesInfo = kylinOrderTicketEntitiesMapper.selectOne(
                            new QueryWrapper<KylinOrderTicketEntities>().eq("order_ticket_entities_id", entitiesId)
                    );
                    if (entitiesInfo.getRefundPrice().compareTo(BigDecimal.ZERO) > 0) { // 已经有退完的 那就是部分退款了
                        newIsPayment = KylinTableStatusConst.ENTITIES_IS_PAYMENT4;
                    } else {
                        newIsPayment = KylinTableStatusConst.ENTITIES_IS_PAYMENT1;
                    }
                }
                KylinOrderTicketEntities entitiesTable = new KylinOrderTicketEntities();
                entitiesTable.setIsPayment(newIsPayment);
                entitiesTable.setUpdatedAt(LocalDateTime.now());
                kylinOrderTicketEntitiesMapper.update(entitiesTable, new UpdateWrapper<KylinOrderTicketEntities>()
                        .eq("order_ticket_entities_id", entitiesId)
                        .eq("is_payment", KylinTableStatusConst.ENTITIES_IS_PAYMENT2)
                );

                mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).updateOne(
                        Query.query(Criteria.where("orderTicketEntitiesId").is(entitiesId)).getQueryObject(),
                        new Document("$set", new Document("isPayment", newIsPayment)
                                .append("updatedAt", DateUtil.getNowTime()))
                );

                dataUtils.delOrderTicketEntitiesRedis(entitiesId);
            }

            // 退款细节取消
            if (isUser) {
                KylinOrderRefunds kylinOrderRefunds = new KylinOrderRefunds();
                kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_CANCEL);
                kylinOrderRefunds.setUpdatedAt(LocalDateTime.now());
                kylinOrderRefundsMapper.update(kylinOrderRefunds, new UpdateWrapper<KylinOrderRefunds>()
                        .eq("order_refunds_id", orderRefundsId));
                // 修改缓存
                UpdateResult updateResult = 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", mongoConverter.convertToMongoType(LocalDateTime.now())))
                );
            } else { // 这里主要是防止批量审核同一个用户多个票 每次查询都还有正在退款的订单 导致拒绝了还是退款中状态 后期可想办法优化
                KylinOrderRefunds kylinOrderRefunds = KylinOrderRefunds.getNew();
                kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT);
                kylinOrderRefundsMapper.update(
                        kylinOrderRefunds,
                        new UpdateWrapper<KylinOrderRefunds>().in("order_refunds_id", orderRefundsId)
                );
            }

        }
        List<String> orderRefundIds = refundList.stream().map(
                KylinOrderRefunds -> KylinOrderRefunds.getOrderRefundsId()).collect(Collectors.toList()
        );
        List<String> orderIds = refundList.stream().map(
                KylinOrderRefunds -> KylinOrderRefunds.getOrderTicketsId()).collect(Collectors.toList()
        );
        dataUtils.delOrderRefundVo(orderRefundIds);
        dataUtils.delOrderRefundVoByOrderId(orderIds);

        return true;
    }

    public boolean orderRefundChangeStatus(List<KylinOrderRefunds> refundList, RefundApplyParam refundApplyParam, String authId, String authName) {
        KylinOrderRefunds kylinOrderRefunds = KylinOrderRefunds.getNew();
        switch (refundApplyParam.getType()) {
            case "reapply":
                kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY);
                kylinOrderRefunds.setApplicantId(authId);
                kylinOrderRefunds.setApplicantName(authName);
                kylinOrderRefunds.setApplicantAt(LocalDateTime.now());
                break;
            case "approved":
                kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED);
                kylinOrderRefunds.setAuditorId(authId);
                kylinOrderRefunds.setAuditorName(authName);
                kylinOrderRefunds.setAuditorAt(LocalDateTime.now());
                kylinOrderRefunds.setReject(refundApplyParam.getReject());
                break;
            case "reject":
                kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT);
                kylinOrderRefunds.setAuditorId(authId);
                kylinOrderRefunds.setAuditorName(authName);
                kylinOrderRefunds.setAuditorAt(LocalDateTime.now());
                kylinOrderRefunds.setReject(refundApplyParam.getReject());
                break;
            case "ticketAudit":
                kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_TICKET);
                kylinOrderRefunds.setTicketAuditId(authId);
                kylinOrderRefunds.setTicketAuditName(authName);
                kylinOrderRefunds.setTicketAuditAt(LocalDateTime.now());
                kylinOrderRefunds.setTicketAuditRemark(refundApplyParam.getTicketRemark());
                break;
            case "refuse":
                kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE);
                kylinOrderRefunds.setExecutorId(authId);
                kylinOrderRefunds.setExecutorName(authName);
                kylinOrderRefunds.setExecutorAt(LocalDateTime.now());
                kylinOrderRefunds.setRefuse(refundApplyParam.getRefuse());
                break;
        }

        kylinOrderRefunds.setUpdatedAt(LocalDateTime.now());
        List<String> orderRefundIds = refundList.stream().map(
                KylinOrderRefunds -> KylinOrderRefunds.getOrderRefundsId()).collect(Collectors.toList()
        );
        List<String> orderIds = refundList.stream().map(
                KylinOrderRefunds -> KylinOrderRefunds.getOrderTicketsId()).collect(Collectors.toList()
        );
        kylinOrderRefundsMapper.update(
                kylinOrderRefunds,
                new UpdateWrapper<KylinOrderRefunds>().in("order_refunds_id", orderRefundIds)
        );
        // 修改缓存
        KylinOrderRefundsVo kylinOrderRefundsVo = KylinOrderRefundsVo.getNew();
        BeanUtils.copyProperties(kylinOrderRefunds, kylinOrderRefundsVo);
        kylinOrderRefundsVo.setUpdatedAt(LocalDateTime.now());
        for (String refundId : orderRefundIds) {
            BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(kylinOrderRefundsVo));
            UpdateResult updateResult = mongoTemplate.getCollection(KylinOrderRefundsVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderRefundsId").is(refundId)).getQueryObject(),
                    object
            );
        }
        dataUtils.delOrderRefundVo(orderRefundIds);
        dataUtils.delOrderRefundVoByOrderId(orderIds);

        return true;
    }

    @Async
    public void orderTicketRefundUnfilled(List<KylinOrderRefunds> refundList, RefundApplyParam refundApplyParam, String authId, String authName) {
        KylinOrderRefunds kylinOrderRefunds = new KylinOrderRefunds();
        kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_UNFILLED);
        kylinOrderRefunds.setExecutorId(authId);
        kylinOrderRefunds.setExecutorName(authName);
        kylinOrderRefunds.setExecutorAt(LocalDateTime.now());
        kylinOrderRefunds.setRefuse(refundApplyParam.getRefuse());

        for (KylinOrderRefunds refund : refundList) {
            KylinOrderRefunds orderRefundsOld = kylinOrderRefundsMapper.selectOne(
                    Wrappers.lambdaQuery(KylinOrderRefunds.class)
                            .eq(KylinOrderRefunds::getOrderRefundsId, refund.getOrderRefundsId())
            );
            if (!Objects.equals(orderRefundsOld.getStatus(), KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED)
                && !Objects.equals(orderRefundsOld.getStatus(), KylinTableStatusConst.ORDER_REFUND_STATUS_TICKET)
                && !Objects.equals(orderRefundsOld.getStatus(), KylinTableStatusConst.ORDER_REFUND_STATUS_ERROR)
            ) {
                continue;
            }
            // 更新退款表
            kylinOrderRefunds.setUpdatedAt(LocalDateTime.now());
            kylinOrderRefundsMapper.update(
                    kylinOrderRefunds,
                    new UpdateWrapper<KylinOrderRefunds>().eq("order_refunds_id", refund.getOrderRefundsId())
            );
            // 修改缓存
            KylinOrderRefundsVo kylinOrderRefundsVo = new KylinOrderRefundsVo();
            BeanUtils.copyProperties(kylinOrderRefunds, kylinOrderRefundsVo);
            BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(kylinOrderRefundsVo));
            UpdateResult updateResult = mongoTemplate.getCollection(KylinOrderRefundsVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderRefundsId").is(refund.getOrderRefundsId())).getQueryObject(),
                    object
            );

            KylinOrderTickets oderInfo = kylinOrderTicketsMapper.selectOne(
                    new QueryWrapper<KylinOrderTickets>()
                            .eq("order_tickets_id", refund.getOrderTicketsId())
            );
            BigDecimal refundPrice = refund.getPrice().add(refund.getPriceExpress());
            MultiValueMap<String, String> params = new LinkedMultiValueMap();
            params.add("code", oderInfo.getPayCode());
            params.add("notifyUrl", refundNotify);
            params.add("orderCode", oderInfo.getOrderCode());
            params.add("orderRefundCode", refund.getOrderRefundCode());
            params.add("paymentId", oderInfo.getPaymentId());
            params.add("paymentType", oderInfo.getPaymentType());
            params.add("price", String.valueOf(refundPrice));
            params.add("priceTotal", String.valueOf(oderInfo.getPriceActual()));
            params.add("reason", "按需退款");

            MultiValueMap<String, String> headers = new LinkedMultiValueMap();
            // headers.add("Content-Type", "application/json;charset=UTF-8");
            headers.add("Accept", "application/json;charset=UTF-8");
            log.info("退款参数" + JsonUtils.toJson(params));
            // 请求pay
            String postResult = null;
            try {
                postResult = HttpUtil.post(refundApply, params, headers);
                log.info("退款res" + postResult);
                HashMap hashMapResult = JsonUtils.fromJson(postResult, HashMap.class);
                Boolean success = (Boolean) hashMapResult.get("success");
                if (!success) {
                    String message = (String) hashMapResult.get("message");
                    log.info("退款pay返回失败" + message);

                    KylinOrderRefunds kylinOrderRefundsFail = new KylinOrderRefunds();
                    kylinOrderRefundsFail.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_ERROR);
                    kylinOrderRefundsFail.setRefundError(message);
                    kylinOrderRefundsFail.setUpdatedAt(LocalDateTime.now());
                    kylinOrderRefundsMapper.update(
                            kylinOrderRefundsFail,
                            new UpdateWrapper<KylinOrderRefunds>().eq("order_refunds_id", refund.getOrderRefundsId())
                    );
                    // 修改缓存
                    KylinOrderRefundsVo kylinOrderRefundsVoFail = new KylinOrderRefundsVo();
                    BeanUtils.copyProperties(kylinOrderRefundsFail, kylinOrderRefundsVoFail);
                    BasicDBObject objectFail = new BasicDBObject("$set", mongoConverter.convertToMongoType(kylinOrderRefundsVoFail));
                    UpdateResult updateFailResult = mongoTemplate.getCollection(KylinOrderRefundsVo.class.getSimpleName()).updateOne(
                            Query.query(Criteria.where("orderRefundsId").is(refund.getOrderRefundsId())).getQueryObject(),
                            objectFail
                    );
//                    List<String> strings = Arrays.asList(refund.getOrderRefundsId());
//                    List<String> strings1 = Arrays.asList(refund.getOrderTicketsId());
//                    dataUtils.delOrderRefundVo(strings);
//                    dataUtils.delOrderRefundVoByOrderId(strings1);

                    continue;
                } else {
                    //获取订单详情
                    KylinOrderTicketVo orderTicketVo = dataUtils.getOrderTicketVo(refund.getOrderTicketsId());
                    //退优先卷
                    ArrayList<KylinOrderCoupons> orderCoupons = dataUtils.getOrderCoupon(refund.getOrderTicketsId());
                    if (orderCoupons.size() > 0) {
                        for (KylinOrderCoupons item : orderCoupons) {
                            if (item.getCouponType() == 101) {
                                dataUtils.backCoupon(item.getCouponCode(), orderTicketVo.getUserId());
                            }
                        }
                    }
                    // 同步大麦 票务平台
                    KylinOrderTicketVo orderData = dataUtils.getOrderTicketVo(refund.getOrderTicketsId());
                    KylinPerformanceVo vo = dataUtils.getPerformanceVo(orderData.getPerformanceId());
                    taobaoTicketUtils.refundDamaiOrder(orderData, vo);
                }
            } catch (Exception e) {
                log.info("退款请求pay失败e" + e.getMessage());
                continue;
            }
        }

        List<String> orderRefundIds = refundList.stream().map(
                KylinOrderRefunds -> KylinOrderRefunds.getOrderRefundsId()).collect(Collectors.toList()
        );
        List<String> orderIds = refundList.stream().map(
                KylinOrderRefunds -> KylinOrderRefunds.getOrderTicketsId()).collect(Collectors.toList()
        );
        dataUtils.delOrderRefundVo(orderRefundIds);
        dataUtils.delOrderRefundVoByOrderId(orderIds);
    }

    public boolean orderTicketRefunded(RefundCallbackParam refundCallbackParam, KylinOrderRefunds refundInfo) {
        MultiValueMap<String, String> params = CollectionUtil.linkedMultiValueMapStringString();
        params.add("status", "1");
        params.add("refundPrice", refundCallbackParam.getRefundPrice().toString());
        params.add("refundError", refundCallbackParam.getRefundError());
        params.add("refundCode", refundCallbackParam.getRefundCode());// PAY
        params.add("refundAt", refundCallbackParam.getRefundAt());
        params.add("orderRefundCode", refundInfo.getOrderRefundCode());
        params.add("refundId", refundCallbackParam.getRefundId());
        params.add("refundType", refundCallbackParam.getRefundType());

        MultiValueMap<String, String> headers = CollectionUtil.linkedMultiValueMapStringString();
        headers.add("Accept", "application/json;charset=UTF-8");

        log.info("订单主动完成退款orderTicketRefunded：[refundCallbackParam={}, [orderRefundCode={}, notifyUrl={}]",
                refundCallbackParam, refundInfo.getOrderRefundCode(), refundNotify);
        String returnData = HttpUtil.post(refundNotify, params, headers);
        log.info("订单主动完成退款orderTicketRefunded-platform结果：{}", returnData);

        return true;
    }

}
