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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.liquidnet.common.cache.redis.util.RedisUtil;
import com.liquidnet.commons.lang.util.BeanUtil;
import com.liquidnet.commons.lang.util.IDGenerator;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.kylin.constant.KylinTableStatusConst;
import com.liquidnet.service.kylin.dao.OrderRefundBatchDao;
import com.liquidnet.service.kylin.dto.param.RefundBatchApplyParam;
import com.liquidnet.service.kylin.dto.param.RefundBatchSearchParam;
import com.liquidnet.service.kylin.dto.vo.returns.KylinOrderRefundBatchesVo;
import com.liquidnet.service.kylin.entity.KylinOrderRefundBatches;
import com.liquidnet.service.kylin.entity.KylinPerformances;
import com.liquidnet.service.kylin.mapper.KylinOrderRefundBatchesMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketsMapper;
import com.liquidnet.service.kylin.mapper.KylinPerformancesMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;

/**
 * <p>
 * 后台退款 服务实现类
 * status 0待付款，1已付款，2已关闭，3正在退款，4已退款, 5待关闭
 * pay_status 支付状态:0未支付 1已支付 2支付失败等
 * </p>
 *
 * @author jiangxiulong
 * @since 2021-05-25 11:26 上午
 */
@Service
public class KylinRefundPerformancesAdminServiceImpl {

    @Autowired
    private KylinOrderTicketsMapper kylinOrderTicketsMapper;

    @Autowired
    private KylinOrderRefundBatchesMapper kylinOrderRefundBatchesMapper;

    @Autowired
    private KylinPerformancesMapper kylinPerformancesMapper;

    @Autowired
    private KylinRefundExecuteServiceImpl kylinRefundExecuteServiceImpl;

    @Autowired
    RedisUtil redisUtil;

    public ResponseDto refundBatchApply(RefundBatchApplyParam refundBatchApplyParam) {
        String targetId = refundBatchApplyParam.getTargetId();
        // 查询需要退的金额和数量
        String[] paymentTypeAlipay = {"APPALIPAY", "WAPALIPAY", "alipay"};
        HashMap<String, Object> orderStatisAlipay = kylinOrderTicketsMapper.getPerformanceRefundOrderStatis(targetId, paymentTypeAlipay);
        String[] paymentTypeWepay = {"APPWEPAY", "APPLETWEPAY", "WAPWEPAY", "JSWEPAY", "wepay"};
        HashMap<String, Object> orderStatisWepay = kylinOrderTicketsMapper.getPerformanceRefundOrderStatis(targetId, paymentTypeWepay);
        Double totalPriceRefundAlipay = 0.0;
        Integer totalRefundNumberAlipay = 0;
        Double totalPriceRefundWepay = 0.0;
        Integer totalRefundNumberWepay = 0;
        if (null != orderStatisAlipay || null != orderStatisWepay) {
            totalPriceRefundAlipay = (Double) orderStatisAlipay.get("total_price_refund");
            totalRefundNumberAlipay = (Integer) orderStatisAlipay.get("total_refund_number");
            totalPriceRefundWepay = (Double) orderStatisWepay.get("total_price_refund");
            totalRefundNumberWepay = (Integer) orderStatisWepay.get("total_refund_number");
            if (totalPriceRefundAlipay <= 0 || totalPriceRefundWepay <= 0) {
                return ResponseDto.failure("演出退款金额为0，无需退款");
            }
        } else {
            return ResponseDto.failure("演出暂无需要退款的订单");
        }

        KylinOrderRefundBatches refundBatchesInfo = kylinOrderRefundBatchesMapper.selectOne(
                new QueryWrapper<KylinOrderRefundBatches>().eq("target_id", targetId).orderByDesc("refund_batch_id")
        );
        if (refundBatchesInfo == null  ||
                refundBatchesInfo.getStatus() == KylinTableStatusConst.STATUS_CANCEL ||
                refundBatchesInfo.getStatus() == KylinTableStatusConst.STATUS_FINANCE_ADOPT
        ) {
            // 添加演出退款记录
            String refundBatchId = IDGenerator.nextSnowId().toString();

            KylinOrderRefundBatches createData = new KylinOrderRefundBatches();
            createData.setRefundBatchId(refundBatchId);
            createData.setTargetId(targetId);
            createData.setStatus(KylinTableStatusConst.STATUS_APPLY);
            createData.setTotalNum(totalRefundNumberAlipay + totalRefundNumberWepay);
            if (null != totalPriceRefundAlipay) {
                createData.setTotalAlipay(BigDecimal.valueOf(totalPriceRefundAlipay));
            }
            if (null != totalPriceRefundWepay) {
                createData.setTotalWepay(BigDecimal.valueOf(totalPriceRefundWepay));
            }
            createData.setCreatedAt(LocalDateTime.now());

            int resNum = kylinOrderRefundBatchesMapper.insert(createData);
            if (resNum > 0) {
                // 开始执行批量提交审核 分批处理退款申请
                kylinRefundExecuteServiceImpl.refundBatchApply(targetId, refundBatchId, refundBatchApplyParam.getReason());
                return ResponseDto.success();
            } else {
                return ResponseDto.failure("操作失败");
            }
        } else {
            return ResponseDto.failure("该演出已经提交过申请，请刷新申请列表查看");
        }
    }

    public ResponseDto refundBatchCheckStatus(RefundBatchApplyParam refundBatchApplyParam) {
        String refundBatchId = refundBatchApplyParam.getRefundBatchId();
        String type = refundBatchApplyParam.getType();
        Integer batchStatus = refundBatchApplyParam.getStatus();
        Integer[] paymentTypeAlipayArray = null;
        Integer batchUpdateStatus = 0;
        Integer orderUpdateStatus = 0;
        switch (type) {
            case "reapply":
                paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_OPERATE_REJECT, KylinTableStatusConst.STATUS_FINANCE_REJECT};
                batchUpdateStatus = KylinTableStatusConst.STATUS_APPLY;
                break;
            case "cancel":
                paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_APPLY, KylinTableStatusConst.STATUS_OPERATE_REJECT, KylinTableStatusConst.STATUS_FINANCE_REJECT};
                batchUpdateStatus = KylinTableStatusConst.STATUS_CANCEL;
                break;
            case "review":
                batchUpdateStatus = batchStatus;
                if (batchStatus == KylinTableStatusConst.STATUS_OPERATE_ADOPT) { // 通过申请
                    paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_APPLY};
                    orderUpdateStatus = KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED;
                }
                if (batchStatus == KylinTableStatusConst.STATUS_OPERATE_REJECT) { // 驳回申请
                    paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_APPLY};
                    orderUpdateStatus = KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT;
                }
                break;
            case "execute":
                batchUpdateStatus = batchStatus;
                if (batchStatus == KylinTableStatusConst.STATUS_FINANCE_ADOPT) { // 执行退款
                    paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_OPERATE_ADOPT, KylinTableStatusConst.STATUS_FINANCE_REJECT};
                    orderUpdateStatus = KylinTableStatusConst.ORDER_REFUND_STATUS_UNFILLED;
                }
                if (batchStatus == KylinTableStatusConst.STATUS_FINANCE_REJECT) { // 拒绝退款
                    paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_OPERATE_ADOPT, KylinTableStatusConst.STATUS_FINANCE_REJECT};
                    orderUpdateStatus = KylinTableStatusConst.ORDER_REFUND_STATUS_REFUSE;
                }
                break;
            default:
                return ResponseDto.failure("type异常，无法操作");
        }
        KylinOrderRefundBatches refundBatchesInfo = kylinOrderRefundBatchesMapper.selectOne(
                new UpdateWrapper<KylinOrderRefundBatches>().eq("refund_batch_id", refundBatchId).in("status", paymentTypeAlipayArray)
        );
        if (null != refundBatchesInfo) {
            // 开始执行批量提交审核 分批处理退款申请
            try {
                if (null != orderUpdateStatus) {
                    refundBatchApplyParam.setRefundStatus(orderUpdateStatus);
                }
                kylinRefundExecuteServiceImpl.refundBatchStatus(refundBatchApplyParam, type);
            } catch (Exception e) {
                return ResponseDto.failure("操作失败");
            }

            KylinOrderRefundBatches params = new KylinOrderRefundBatches();
            params.setStatus(batchUpdateStatus);
            kylinOrderRefundBatchesMapper.update(params, new UpdateWrapper<KylinOrderRefundBatches>().eq("refund_batch_id", refundBatchId));

            return ResponseDto.success();
        } else {
            return ResponseDto.failure("当前状态下不允许此操作");
        }
    }

    public KylinOrderRefundBatchesVo detail(String orderRefundId) {
        KylinOrderRefundBatches data = kylinOrderRefundBatchesMapper.selectOne(
                new UpdateWrapper<KylinOrderRefundBatches>()
                        .eq("refund_batch_id", orderRefundId)
        );

        KylinOrderRefundBatchesVo kylinOrderRefundBatchesVo = new KylinOrderRefundBatchesVo();
        BeanUtils.copyProperties(data, kylinOrderRefundBatchesVo);

        return kylinOrderRefundBatchesVo;
    }

    public PageInfo<OrderRefundBatchDao> refundList(RefundBatchSearchParam refundBatchSearchParam) {
        PageInfo<OrderRefundBatchDao> pageInfoTmp = null;
        try {
            PageHelper.startPage(refundBatchSearchParam.getPageNum(), refundBatchSearchParam.getPageSize());
            List<OrderRefundBatchDao> voList = kylinOrderRefundBatchesMapper.misRefundBatchList(BeanUtil.convertBeanToMap(refundBatchSearchParam));
            for (OrderRefundBatchDao item : voList) {
                KylinPerformances info = kylinPerformancesMapper.selectOne(
                        new UpdateWrapper<KylinPerformances>()
                                .eq("performances_id", item.getTargetId())
                );
                item.setPerformancesInfo(info);
                item.setStatusName(item.getStatus());
            }
            pageInfoTmp = new PageInfo(voList);
        } catch (Exception e) {
            return null;
        }
        return pageInfoTmp;
    }

}
