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

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dto.param.RefundApplyParam;
import com.liquidnet.service.kylin.dto.param.RefundBatchApplyParam;
import com.liquidnet.service.kylin.entity.*;
import com.liquidnet.service.kylin.mapper.KylinOrderRefundBatchesMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderRefundsMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketEntitiesMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketsMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

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

/**
 * <p>
 * 后台退款 服务实现类
 * </p>
 *
 * @author jiangxiulong
 * @since 2021-05-25 19:50 下午
 */
@Service
public class KylinRefundExecuteServiceImpl {

    @Autowired
    private KylinOrderTicketsMapper kylinOrderTicketsMapper;

    @Autowired
    private KylinOrderRefundsMapper kylinOrderRefundsMapper;

    @Autowired
    private KylinOrderTicketEntitiesMapper kylinOrderTicketEntitiesMapper;

    @Autowired
    private KylinOrderRefundBatchesMapper kylinOrderRefundBatchesMapper;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    private KylinOrderRefundsServiceImpl kylinOrderRefundsServiceImpl;

    @Async
    public void refundBatchApply(String targetId, String refundBatchId, String reason) {
        RefundApplyParam refundApplyParam = new RefundApplyParam();
        int count;
        int limitNum = 10;
        int mid = 0;
        Integer[] isPayment = {KylinTableStatusConst.ENTITIES_IS_PAYMENT1, KylinTableStatusConst.ENTITIES_IS_PAYMENT2, KylinTableStatusConst.ENTITIES_IS_PAYMENT4};
        do {
            List<KylinOrderTickets> orderList = kylinOrderTicketsMapper.getCanRefundOrderList(targetId, mid, limitNum);

            for (KylinOrderTickets order : orderList) {
                List<KylinOrderTicketEntities> entitiesList = kylinOrderTicketEntitiesMapper.selectList(
                        new UpdateWrapper<KylinOrderTicketEntities>().eq("order_id", order.getOrderTicketsId())
                                .in("is_payment", isPayment)
                );
                List<String> ticketEntityIds = entitiesList.stream().map(KylinOrderTicketEntities -> KylinOrderTicketEntities.getOrderTicketEntitiesId()).collect(Collectors.toList());

                refundApplyParam.setOrderRefundBatchesId(refundBatchId);
                refundApplyParam.setReason(reason);
                refundApplyParam.setOrderTicketsId(order.getOrderTicketsId());
                refundApplyParam.setTicketEntityIds(ticketEntityIds);
                if (null != order.getPriceExpress()) {
                    refundApplyParam.setRefundPriceExpress(order.getPriceExpress());
                }
                try {
                    ResponseDto res = kylinOrderRefundsServiceImpl.refundApply(refundApplyParam);
                } catch (Exception e) {

                }
            }

            count = orderList.size();
            KylinOrderTickets lastInfo = orderList.get(count - 1);
            mid = lastInfo.getMid();
        } while (count >= limitNum);

        KylinOrderRefundBatches updateBatchData = new KylinOrderRefundBatches();
        updateBatchData.setStatus(KylinTableStatusConst.STATUS_APPLY);
        updateBatchData.setUpdatedAt(LocalDateTime.now());
        kylinOrderRefundBatchesMapper.update(
                updateBatchData,
                new UpdateWrapper<KylinOrderRefundBatches>().eq("refund_batch_id", refundBatchId)
        );
    }

    @Async
    public void refundBatchStatus(RefundBatchApplyParam refundBatchApplyParam, String type) {
        String refundBatchId = refundBatchApplyParam.getRefundBatchId();
        Integer status = refundBatchApplyParam.getRefundStatus();
        // 处理查询订单状态
        Integer[] whereStatus = {};
        Integer whereType = KylinTableStatusConst.ORDER_REFUND_TYPE_APPLY;
        switch (type) {
            case "reapply":
                whereStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE};
                break;
            case "cancel":
                whereStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE};
                break;
            case "review":
                if (status == KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED) { // 通过申请
                    type = "approved";
                    whereStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE};
                }
                if (status == KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT) { // 驳回申请
                    type = "reject";
                    whereStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPLY, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE};
                }
                break;
            case "execute":
                if (status == KylinTableStatusConst.ORDER_REFUND_STATUS_UNFILLED) { // 执行退款
                    type = "unfilled";
                    whereStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED, KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE, KylinTableStatusConst.ORDER_REFUND_STATUS_ERROR};
                }
                if (status == KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE) { // 拒绝退款
                    type = "refuse";
                    whereStatus = new Integer[]{KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED, KylinTableStatusConst.ORDER_REFUND_STATUS_ERROR};
                }
                break;
        }

        int count = 0;
        int limitNum = 20;
        int mid = 0;
        do {
            List<KylinOrderRefunds> refundList = kylinOrderRefundsMapper.getRefundList(whereType, refundBatchId, whereStatus, mid, limitNum);

            List<String> refundIds = null;
            if (refundList != null && refundList.size() > 0) {
                refundIds = refundList.stream().map(KylinOrderRefunds -> KylinOrderRefunds.getOrderRefundsId()).collect(Collectors.toList());

                RefundApplyParam refundApplyParam = new RefundApplyParam();
                refundApplyParam.setIds(refundIds);
                refundApplyParam.setType(type);
                if (null != refundBatchApplyParam.getRefuse()) {
                    refundApplyParam.setRefuse(refundBatchApplyParam.getRefuse());
                }
                if (null != refundBatchApplyParam.getReject()) {
                    refundApplyParam.setReject(refundBatchApplyParam.getReject());
                }
                try {
                    ResponseDto res = kylinOrderRefundsServiceImpl.refundCheckStatus(refundApplyParam);
                } catch (Exception e) {

                }
            }

            count = refundList.size();
            if (count > 0) {
                KylinOrderRefunds lastInfo = refundList.get(count - 1);
                if (lastInfo != null) {
                    mid = lastInfo.getMid();
                }
            }
        } while (count >= limitNum);

        KylinOrderRefundBatches updateBatchData = new KylinOrderRefundBatches();

        switch (type) {
            case "cancel":
                updateBatchData.setStatus(KylinTableStatusConst.STATUS_CANCEL);
                break;
            case "reapply":
                updateBatchData.setStatus(KylinTableStatusConst.STATUS_APPLY);
                break;
            case "approved":
                updateBatchData.setStatus(KylinTableStatusConst.STATUS_OPERATE_ADOPT);
                break;
            case "reject":
                updateBatchData.setStatus(KylinTableStatusConst.STATUS_OPERATE_REJECT);
                break;
            case "unfilled":
                updateBatchData.setStatus(KylinTableStatusConst.STATUS_FINANCE_ADOPT);
                break;
            case "refuse":
                updateBatchData.setStatus(KylinTableStatusConst.STATUS_FINANCE_REJECT);
                break;
        }

        updateBatchData.setUpdatedAt(LocalDateTime.now());
        kylinOrderRefundBatchesMapper.update(
                updateBatchData,
                new UpdateWrapper<KylinOrderRefundBatches>().eq("refund_batch_id", refundBatchId)
        );
    }

}
