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.liquidnet.client.admin.common.utils.ShiroUtils;
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.commons.lang.util.*;
import com.liquidnet.service.base.UserPathDto;
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.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.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

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

    @Value("${liquidnet.url-refund.apply}")
    private String applyUrl;
    @Value("${liquidnet.url-refund.notify}")
    private String notifyUrl;

    @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;

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

        // TODO: 2021/5/27 事物 and 部分退款
        // 更新数据
        // 订单状态表 和 缓存
        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);
        mongoVoUtils.resetOrderListVo(orderInfo.getUserId(), 2, orderTicketsId, null);


        // 订单入场人表 和 缓存
        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));

            KylinOrderTicketEntitiesVo kylinOrderTicketEntitiesVo = new KylinOrderTicketEntitiesVo();
            kylinOrderTicketEntitiesVo.setIsPayment(KylinTableStatusConst.ENTITIES_IS_PAYMENT2);
            kylinOrderTicketEntitiesVo.setUpdatedAt(DateUtil.getNowTime());
            BasicDBObject entitiesObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketEntitiesVo)));
            Document entitiesDoc = mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).findOneAndUpdate(
                    Query.query(Criteria.where("orderTicketEntitiesId").is(v)).getQueryObject(),
                    entitiesObject,
                    new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
            );

            dataUtils.delOrderTicketEntitiesRedis(v);
        }

        // 退款明细
        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);
        if (RefundPriceExpress.compareTo(BigDecimal.ZERO) > 0 && entitiesPriceSum.compareTo(BigDecimal.ZERO) > 0) {
            kylinOrderRefunds.setRefundCate(KylinTableStatusConst.ORDER_REFUND_CATE3);
        } else if (RefundPriceExpress.compareTo(BigDecimal.ZERO) > 0) {
            kylinOrderRefunds.setRefundCate(KylinTableStatusConst.ORDER_REFUND_CATE2);
        } else if (entitiesPriceSum.compareTo(BigDecimal.ZERO) > 0) {
            kylinOrderRefunds.setRefundCate(KylinTableStatusConst.ORDER_REFUND_CATE1);
        }
        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)
                );

                KylinOrderTicketEntitiesVo kylinOrderTicketEntitiesVo = new KylinOrderTicketEntitiesVo();
                kylinOrderTicketEntitiesVo.setIsPayment(newIsPayment);
                kylinOrderTicketEntitiesVo.setUpdatedAt(DateUtil.getNowTime());
                BasicDBObject entitiesObject = new BasicDBObject("$set", JSON.parse(JsonUtils.toJson(kylinOrderTicketEntitiesVo)));
                Document entitiesDoc = mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).findOneAndUpdate(
                        Query.query(Criteria.where("orderTicketEntitiesId").is(entitiesId)).getQueryObject(),
                        entitiesObject,
                        new FindOneAndUpdateOptions().returnDocument(ReturnDocument.AFTER)
                );

                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", 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()
        );
        dataUtils.delOrderRefundVo(orderRefundIds);
        dataUtils.delOrderRefundVoByOrderId(orderIds);

        return true;
    }

    public boolean orderRefundChangeStatus(List<KylinOrderRefunds> refundList, String type, String reject, String refuse) {
        String authId = ShiroUtils.getUserId().toString();
        String authName = ShiroUtils.getLoginName();
        KylinOrderRefunds kylinOrderRefunds = new KylinOrderRefunds();
        switch (type) {
            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(reject);
                break;
            case "reject":
                kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT);
                kylinOrderRefunds.setAuditorId(authId);
                kylinOrderRefunds.setAuditorName(authName);
                kylinOrderRefunds.setAuditorAt(LocalDateTime.now());
                kylinOrderRefunds.setReject(reject);
                break;
            case "refuse":
                kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE);
                kylinOrderRefunds.setExecutorId(authId);
                kylinOrderRefunds.setExecutorName(authName);
                kylinOrderRefunds.setExecutorAt(LocalDateTime.now());
                kylinOrderRefunds.setRefuse(refuse);
                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 = new KylinOrderRefundsVo();
        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
            );
        }
        /*BasicDBObject object = new BasicDBObject("$set", mongoConverter.convertToMongoType(kylinOrderRefundsVo));
        UpdateResult updateResult = mongoTemplate.getCollection(KylinOrderRefundsVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("orderRefundsId").in(orderRefundIds)).getQueryObject(),
                object
        );*/
        dataUtils.delOrderRefundVo(orderRefundIds);
        dataUtils.delOrderRefundVoByOrderId(orderIds);

        return true;
    }

    @Async
    public void orderTicketRefundUnfilled(List<KylinOrderRefunds> refundList, String refuse, 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(refuse);
        kylinOrderRefunds.setUpdatedAt(LocalDateTime.now());

        for (KylinOrderRefunds refund : refundList) {
            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", notifyUrl);
            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.getPriceTotal()));
            params.add("reason", refund.getReason());

            /*String sign = StringUtils.Ksort(params);
            sign = sign.concat("&key=").concat("R7tXY9smPQPG9Ku5yI0u6sfnlckmk04V");
            // sign = MD5.getStrMD5(sign);
            sign = sign.toUpperCase();
            params.add("sign", sign);*/
            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(applyUrl, 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);
                    kylinOrderRefunds.setUpdatedAt(LocalDateTime.now());
                    kylinOrderRefundsMapper.update(
                            kylinOrderRefundsFail,
                            new UpdateWrapper<KylinOrderRefunds>().eq("order_refunds_id", refund.getOrderRefundsId())
                    );
                    // 修改缓存
                    KylinOrderRefundsVo kylinOrderRefundsVo = new KylinOrderRefundsVo();
                    BeanUtils.copyProperties(kylinOrderRefundsFail, 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
                    );
                    List<String> strings = Arrays.asList(refund.getOrderRefundsId());
                    List<String> strings1 = Arrays.asList(refund.getOrderTicketsId());
                    dataUtils.delOrderRefundVo(strings);
                    dataUtils.delOrderRefundVoByOrderId(strings1);

                    continue;
                }
            } catch (Exception e) {
                log.info("退款请求pay失败e" + e.getMessage());
                continue;
            }
            // 更新退款表
            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
            );
        }

        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) {
        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();

        KylinOrderTicketRelations orderRelations = kylinOrderTicketRelationsMapper.selectOne(
                new QueryWrapper<KylinOrderTicketRelations>().eq("order_id", orderTicketsId)
        );

        // 更新数据
        // 订单状态表
        KylinOrderTickets orderInfo = kylinOrderTicketsMapper.selectOne(
                new QueryWrapper<KylinOrderTickets>().eq("order_tickets_id", orderTicketsId)
        );
        KylinOrderTicketStatus orderStatusTable = new KylinOrderTicketStatus();
        int newStatus = 0;
        if (refundCallbackParam.getRefundPrice().add(orderInfo.getPriceRefund()).compareTo(orderInfo.getPriceActual()) == 0) {
            newStatus = KylinTableStatusConst.ORDER_STATUS4;
        } else {
            newStatus = KylinTableStatusConst.ORDER_STATUS6;
        }
        orderStatusTable.setStatus(newStatus);
        orderStatusTable.setUpdatedAt(LocalDateTime.now());
        kylinOrderTicketStatusMapper.update(
                orderStatusTable, new UpdateWrapper<KylinOrderTicketStatus>()
                        .eq("order_id", orderTicketsId)
        );

        // 入场人
        BigDecimal priceActual = orderInfo.getPriceActual();
        BigDecimal priceExpress = orderInfo.getPriceExpress();
        int allEntitiesCount = kylinOrderTicketEntitiesMapper.selectCount(// 总入场人数量 排出未付款的 用来计算单入场人的价格
                new QueryWrapper<KylinOrderTicketEntities>()
                        .eq("order_id", orderTicketsId)
                        .ne("is_payment", KylinTableStatusConst.ENTITIES_IS_PAYMENT0)
        );
        BigDecimal onePrice = priceActual.subtract(priceExpress).divide(BigDecimal.valueOf(allEntitiesCount));//单价
        int refundNumber = 0;
        for (String entitiesId : orderTicketEntitiesIdsArr) {
            KylinOrderTicketEntities EntitiesInfo = kylinOrderTicketEntitiesMapper.selectOne(//已退完成的
                    new QueryWrapper<KylinOrderTicketEntities>()
                            .eq("order_ticket_entities_id", entitiesId)
            );
            BigDecimal refundedPrice = EntitiesInfo.getRefundPrice();

            KylinOrderRefundEntities refundEntitiesInfo = kylinOrderRefundsEntitiesMapper.selectOne(
                    new QueryWrapper<KylinOrderRefundEntities>()
                            .eq("order_refunds_id", refundInfo.getOrderRefundsId())
                            .eq("order_ticket_entities_id", entitiesId)
            );

            KylinOrderTicketEntities entitiesTable = new KylinOrderTicketEntities();
            BigDecimal priceNew = refundEntitiesInfo.getRefundPrice().add(refundedPrice);
            int isPayment = 0;
            if (priceNew.compareTo(onePrice) == 0) {
                isPayment = KylinTableStatusConst.ENTITIES_IS_PAYMENT3;
                refundNumber++;
            } else {
                isPayment = KylinTableStatusConst.ENTITIES_IS_PAYMENT4;
            }
            entitiesTable.setIsPayment(isPayment);
            entitiesTable.setUpdatedAt(LocalDateTime.now());
            entitiesTable.setRefundPrice(priceNew);
            Integer[] entitiesTableIsPayment = {KylinTableStatusConst.ENTITIES_IS_PAYMENT2, KylinTableStatusConst.ENTITIES_IS_PAYMENT4};
            kylinOrderTicketEntitiesMapper.update(entitiesTable, new UpdateWrapper<KylinOrderTicketEntities>()
                    .eq("order_ticket_entities_id", entitiesId)
                    .in("is_payment", entitiesTableIsPayment)
            );

            HashMap<String, Object> EntitiesVo = new HashMap<>();
            EntitiesVo.put("updatedAt", DateUtil.getNowTime());
            EntitiesVo.put("refundPrice", priceNew);
            EntitiesVo.put("isPayment", isPayment);
            BasicDBObject EntitiesVov = new BasicDBObject("$set", mongoConverter.convertToMongoType(EntitiesVo));
            UpdateResult updateResult = mongoTemplate.getCollection(KylinOrderTicketEntitiesVo.class.getSimpleName()).updateOne(
                    Query.query(Criteria.where("orderTicketEntitiesId").is(entitiesId)).getQueryObject(),
                    EntitiesVov
            );

            dataUtils.delOrderTicketEntitiesRedis(entitiesId);
        }

        // 订单表
        BigDecimal price = orderInfo.getPriceRefund().add(refundCallbackParam.getRefundPrice());
        Integer num = orderInfo.getRefundNumber() + refundNumber;
        KylinOrderTickets update = new KylinOrderTickets();
        update.setRefundNumber(num);
        update.setPriceRefund(price);
        update.setUpdatedAt(LocalDateTime.now());
        kylinOrderTicketsMapper.update(
                update, new UpdateWrapper<KylinOrderTickets>()
                        .eq("order_tickets_id", orderTicketsId)
        );

        HashMap<String, Object> orderVo = new HashMap<>();
        orderVo.put("updatedAt", DateUtil.getNowTime());
        orderVo.put("priceRefund", price);
        orderVo.put("status", newStatus);
        orderVo.put("refundNumber", num);
        BasicDBObject orderVov = new BasicDBObject("$set", mongoConverter.convertToMongoType(orderVo));
        UpdateResult orderUpdateResult = mongoTemplate.getCollection(KylinOrderTicketVo.class.getSimpleName()).updateOne(
                Query.query(Criteria.where("orderTicketsId").is(orderTicketsId)).getQueryObject(),
                orderVov
        );
        dataUtils.delOrderTicketRedis(orderTicketsId);
        mongoVoUtils.resetOrderListVo(orderInfo.getUserId(), 2, orderTicketsId, null);

        // 退款单完成
        KylinOrderRefunds kylinOrderRefunds = new KylinOrderRefunds();
        kylinOrderRefunds.setStatus(KylinTableStatusConst.ORDER_REFUND_STATUS_REFUNDED);
        kylinOrderRefunds.setRefundCode(refundCallbackParam.getRefundCode());
        kylinOrderRefunds.setRefundType(refundCallbackParam.getRefundType());
        kylinOrderRefunds.setRefundId(refundCallbackParam.getRefundId());
        kylinOrderRefunds.setRefundAt(refundCallbackParam.getRefundAt());
        kylinOrderRefunds.setUpdatedAt(LocalDateTime.now());
        kylinOrderRefundsMapper.update(
                kylinOrderRefunds,
                new UpdateWrapper<KylinOrderRefunds>().in("order_refunds_id", refundInfo.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(refundInfo.getOrderRefundsId())).getQueryObject(),
                object
        );

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

        if (refundInfo.getType() == KylinTableStatusConst.ORDER_REFUND_TYPE_APPLY) {
            // 退还库存
            for (String entitiesId : orderTicketEntitiesIdsArr) {
                KylinOrderTicketEntities entitiesInfo = kylinOrderTicketEntitiesMapper.selectOne(
                        new QueryWrapper<KylinOrderTicketEntities>().eq("order_ticket_entities_id", entitiesId)
                );
                if (entitiesInfo.getIsPayment() == KylinTableStatusConst.ENTITIES_IS_PAYMENT3) {
                    dataUtils.changeSurplusGeneral(entitiesInfo.getTicketId(), 1);
                    log.info(UserPathDto.setData("changeBuyInfo", "UserId=" + orderInfo.getUserId() + "idCard=" + entitiesInfo.getEnterIdCode() + " PerformanceId=" + orderRelations.getPerformanceId() + " TicketId=" + entitiesInfo.getTicketId(), "info"));
                    dataUtils.changeBuyInfo(orderInfo.getUserId(), entitiesInfo.getEnterIdCode(), orderRelations.getPerformanceId(), entitiesInfo.getTicketId(), -1);
                }
            }
        }

        return true;
    }

}
