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.client.admin.common.utils.ShiroUtils;
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.KylinOrderRefunds;
import com.liquidnet.service.kylin.entity.KylinPerformances;
import com.liquidnet.service.kylin.mapper.KylinOrderRefundBatchesMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderRefundsMapper;
import com.liquidnet.service.kylin.mapper.KylinOrderTicketsMapper;
import com.liquidnet.service.kylin.mapper.KylinPerformancesMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
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.Arrays;
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
@Slf4j
public class KylinRefundPerformancesAdminServiceImpl {

    @Autowired
    private KylinOrderTicketsMapper kylinOrderTicketsMapper;

    @Autowired
    private KylinOrderRefundBatchesMapper kylinOrderRefundBatchesMapper;

    @Autowired
    private KylinOrderRefundsMapper kylinOrderRefundsMapper;

    @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);
        BigDecimal totalPriceRefundAlipay = new BigDecimal(0.0);
        Integer totalRefundNumberAlipay = 0;
        BigDecimal totalPriceRefundWepay = new BigDecimal(0);
        Integer totalRefundNumberWepay = 0;
        if (null != orderStatisAlipay || null != orderStatisWepay) {
            if (null != orderStatisAlipay) {
                totalPriceRefundAlipay = (BigDecimal) orderStatisAlipay.get("total_price_refund");
                Long totalRefundNumberAlipayBigDecimal = (Long) orderStatisAlipay.get("total_refund_number");
                totalRefundNumberAlipay = totalRefundNumberAlipayBigDecimal.intValue();
                if (null == totalPriceRefundAlipay) {
                    totalPriceRefundAlipay = new BigDecimal(0);
                }
            }

            if (null != orderStatisWepay) {
                totalPriceRefundWepay = (BigDecimal) orderStatisWepay.get("total_price_refund");
                Long totalRefundNumberWepayBigDecimal = (Long) orderStatisWepay.get("total_refund_number");
                totalRefundNumberWepay = totalRefundNumberWepayBigDecimal.intValue();
                if (null == totalPriceRefundWepay) {
                    totalPriceRefundWepay = new BigDecimal(0);
                }
            }
            if (totalPriceRefundAlipay.compareTo(BigDecimal.ZERO) <= 0 && totalPriceRefundWepay.compareTo(BigDecimal.ZERO) <= 0) {
                return ResponseDto.failure("演出退款金额为0，无需退款");
            }
        } else {
            return ResponseDto.failure("演出暂无需要退款的订单");
        }

        KylinOrderRefundBatches refundBatchesInfo = kylinOrderRefundBatchesMapper.selectLastOne(targetId);
        if (refundBatchesInfo == null ||
                refundBatchesInfo.getStatus() == KylinTableStatusConst.STATUS_CANCEL ||
                refundBatchesInfo.getStatus() == KylinTableStatusConst.STATUS_FINANCE_ADOPT ||
                refundBatchesInfo.getStatus() == KylinTableStatusConst.STATUS_OPERATE_REJECT
        ) {
            // 添加演出退款记录
            String refundBatchId = IDGenerator.nextSnowId();
            KylinOrderRefundBatches createData = new KylinOrderRefundBatches();
            createData.setRefundBatchId(refundBatchId);
            createData.setTargetId(targetId);
            createData.setStatus(KylinTableStatusConst.STATUS_APPLY11);
            createData.setTotalNum(totalRefundNumberAlipay + totalRefundNumberWepay);
            createData.setTotalAlipay(totalPriceRefundAlipay);
            createData.setTotalWepay(totalPriceRefundWepay);
            createData.setCreatedAt(LocalDateTime.now());
            int resNum = kylinOrderRefundBatchesMapper.insert(createData);
            if (resNum > 0) {
                // 开始执行批量提交审核 分批处理退款申请
                String authId = ShiroUtils.getUserId().toString();
                String authName = ShiroUtils.getLoginName();
                kylinRefundExecuteServiceImpl.refundBatchApply(targetId, refundBatchId, refundBatchApplyParam.getReason(), authId, authName);
                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_APPLY11;
                break;
            case "cancel":
                paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_APPLY, KylinTableStatusConst.STATUS_OPERATE_ADOPT};
                batchUpdateStatus = KylinTableStatusConst.STATUS_CANCEL22;
                break;
            case "review":
                batchUpdateStatus = batchStatus;
                if (batchStatus == KylinTableStatusConst.STATUS_OPERATE_ADOPT44) { // 通过申请
                    paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_APPLY, KylinTableStatusConst.STATUS_FINANCE_REJECT};
                    orderUpdateStatus = KylinTableStatusConst.ORDER_REFUND_STATUS_APPROVED;
                }
                if (batchStatus == KylinTableStatusConst.STATUS_OPERATE_REJECT33) { // 驳回申请
                    paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_APPLY, KylinTableStatusConst.STATUS_FINANCE_REJECT};
                    orderUpdateStatus = KylinTableStatusConst.ORDER_REFUND_STATUS_REJECT;
                }
                break;
            case "execute":
                batchUpdateStatus = batchStatus;
                if (batchStatus == KylinTableStatusConst.STATUS_FINANCE_ADOPT66) { // 执行退款
                    paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_OPERATE_ADOPT};
                    orderUpdateStatus = KylinTableStatusConst.ORDER_REFUND_STATUS_UNFILLED;
                }
                if (batchStatus == KylinTableStatusConst.STATUS_FINANCE_REJECT55) { // 拒绝退款
                    paymentTypeAlipayArray = new Integer[]{KylinTableStatusConst.STATUS_OPERATE_ADOPT};
                    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 {
                KylinOrderRefundBatches params = new KylinOrderRefundBatches();
                params.setStatus(batchUpdateStatus);
                params.setUpdatedAt(LocalDateTime.now());
                kylinOrderRefundBatchesMapper.update(params, new UpdateWrapper<KylinOrderRefundBatches>().eq("refund_batch_id", refundBatchId));

                if (null != orderUpdateStatus) {
                    refundBatchApplyParam.setRefundStatus(orderUpdateStatus);
                }
                String authId = ShiroUtils.getUserId().toString();
                String authName = ShiroUtils.getLoginName();
                kylinRefundExecuteServiceImpl.refundBatchStatus(refundBatchApplyParam, type, authId, authName);
            } catch (Exception e) {
                return ResponseDto.failure("操作失败");
            }

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

    public ResponseDto ticketAuditAll(RefundBatchApplyParam refundBatchApplyParam) {
        return ResponseDto.success();
    }

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

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

        Integer totalRefundNum = kylinOrderRefundsMapper.selectCount(
                new QueryWrapper<KylinOrderRefunds>()
                        .eq("order_refund_batches_id", refundBatchId)
        );

        Integer totalCompleteRefundNum = kylinOrderRefundsMapper.selectCount(
                new QueryWrapper<KylinOrderRefunds>()
                        .eq("order_refund_batches_id", refundBatchId)
                        .eq("status", KylinTableStatusConst.ORDER_REFUND_STATUS_REFUNDED)
        );

        kylinOrderRefundBatchesVo.setTotalRefundNum(totalRefundNum);
        kylinOrderRefundBatchesVo.setTotalCompleteRefundNum(totalCompleteRefundNum);

        return kylinOrderRefundBatchesVo;
    }

    public PageInfo<OrderRefundBatchDao> refundList(RefundBatchSearchParam refundBatchSearchParam) {
        PageInfo<OrderRefundBatchDao> pageInfoTmp = null;
        try {
            PageHelper.startPage(refundBatchSearchParam.getPageNum(), refundBatchSearchParam.getPageSize());
            if (!refundBatchSearchParam.getStatus().isEmpty()) {
                refundBatchSearchParam.setStatusStr(Arrays.asList(refundBatchSearchParam.getStatus().split(",")));
            }
            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;
    }

}
