package com.jeequan.jeepay.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.entity.TransferOrder;
import com.jeequan.jeepay.core.entity.TransferSubject;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.db.entity.TransferSubjectEntity;
import com.jeequan.jeepay.db.entity.TransferWalletEntity;
import com.jeequan.jeepay.service.mapper.TransferWalletMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Map;

/**
 * <p>
 * 转账对象钱包 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2024-04-29
 */
@RequiredArgsConstructor
@Service
public class TransferWalletService extends ServiceImpl<TransferWalletMapper, TransferWalletEntity> {

    private final TransferOrderService transferOrderService;
    private final TransferSubjectService transferSubjectService;

    /**
     * 计算剩余的额度
     */
    public void leftQuota(TransferWalletEntity transferWallet) {
        transferWallet.setZfbMonthLeft(transferWallet.getZfbMonthMax());
        transferWallet.setBankCardMonthLeft(transferWallet.getBankCardMonthMax());
        transferWallet.setWxMonthLeft(transferWallet.getWxMonthMax());
        transferWallet.setZfbDayLeft(transferWallet.getZfbDayMax());
        transferWallet.setBankCardDayLeft(transferWallet.getBankCardDayMax());
        transferWallet.setWxDayLeft(transferWallet.getWxDayMax());

        Date current = new Date();
        Map<String, Long> accumulatedMonth = transferOrderService.accumulated(DateField.MONTH, current,
                TransferOrder.TRANSFER_TYPE_OUT, transferWallet.getTransSubjectId(), transferWallet.getId(),
                TransferOrder.STATE_INIT, TransferOrder.STATE_ING, TransferOrder.STATE_SUCCESS);

        Map<String, Long> accumulatedDay = transferOrderService.accumulated(DateField.DAY_OF_YEAR, current,
                TransferOrder.TRANSFER_TYPE_OUT, transferWallet.getTransSubjectId(), transferWallet.getId(),
                TransferOrder.STATE_INIT, TransferOrder.STATE_ING, TransferOrder.STATE_SUCCESS);

        accumulatedMonth.forEach((key, value) -> {
            switch (key) {
                case TransferOrder.ENTRY_ALIPAY_CASH:
                    transferWallet.setZfbMonthLeft(transferWallet.getZfbMonthMax() - value);
                    break;
                case TransferOrder.ENTRY_BANK_CARD:
                    transferWallet.setBankCardMonthLeft(transferWallet.getBankCardMonthMax() - value);
                    break;
                case TransferOrder.ENTRY_WX_CASH:
                    transferWallet.setWxMonthLeft(transferWallet.getWxMonthMax() - value);
                    break;
            }
        });

        accumulatedDay.forEach((key, value) -> {
            switch (key) {
                case TransferOrder.ENTRY_ALIPAY_CASH:
                    transferWallet.setZfbDayLeft(transferWallet.getZfbDayMax() - value);
                    break;
                case TransferOrder.ENTRY_BANK_CARD:
                    transferWallet.setBankCardDayLeft(transferWallet.getBankCardDayMax() - value);
                    break;
                case TransferOrder.ENTRY_WX_CASH:
                    transferWallet.setWxDayLeft(transferWallet.getWxDayMax() - value);
                    break;
            }
        });
    }

    public TransferWalletEntity getBySubjectId(String transSubjectId, String transChannelMchNo) {
        return lambdaQuery()
                .eq(!ObjUtil.isEmpty(transSubjectId), TransferWalletEntity::getTransSubjectId, transSubjectId)
                .eq(!ObjUtil.isEmpty(transSubjectId), TransferWalletEntity::getTransChannelMchNo, transChannelMchNo)
                .orderByDesc(TransferWalletEntity::getId).last("limit 1")
                .one();
    }

    public TransferWalletEntity getByApplyId(String transApplyId, String walletApplyId) {
        return lambdaQuery()
                .eq(!ObjUtil.isEmpty(transApplyId), TransferWalletEntity::getTransApplyId, transApplyId)
                .eq(!ObjUtil.isEmpty(walletApplyId), TransferWalletEntity::getWalletApplyId, walletApplyId)
                .orderByDesc(TransferWalletEntity::getId).last("limit 1")
                .one();
    }

    public void configQuota(TransferWalletEntity reqParam) {
        Assert.notEmpty(reqParam.getTransSubjectId(), "参数【transSubjectId】不能为空");

        TransferSubjectEntity transferSubject = transferSubjectService.getById(reqParam.getTransSubjectId());
        Assert.notNull(transferSubject, "未获取到代付转账方信息");
        if (transferSubject.getSubjectType().equals(TransferSubject.SUBJECT_TYPE_RECEIVER)) {
            throw new BizException("未获取到代付转账方信息");
        }

        TransferWalletEntity transWallet = lambdaQuery()
                .eq(TransferWalletEntity::getTransSubjectId, reqParam.getTransSubjectId())
                .eq(TransferWalletEntity::getTransChannelMchNo, transferSubject.getTransChannelMchNo())
                .one();
        Assert.notNull(transWallet, "未获取到钱包配置信息");

        TransferWalletEntity updateInfo = new TransferWalletEntity();
        updateInfo.setId(transWallet.getId());
        // 微信额度
        updateInfo.setWxMonthMax(reqParam.getWxMonthMax());
        updateInfo.setWxDayMax(reqParam.getWxDayMax());
        updateInfo.setWxCorOnceMax(reqParam.getWxCorOnceMax());
        updateInfo.setWxPriOnceMax(reqParam.getWxPriOnceMax());
        // 支付宝额度
        updateInfo.setZfbMonthMax(reqParam.getZfbMonthMax());
        updateInfo.setZfbDayMax(reqParam.getZfbDayMax());
        updateInfo.setZfbCorOnceMax(reqParam.getZfbCorOnceMax());
        updateInfo.setZfbPriOnceMax(reqParam.getZfbPriOnceMax());
        // 银行账户额度
        updateInfo.setBankCardMonthMax(reqParam.getBankCardMonthMax());
        updateInfo.setBankCardDayMax(reqParam.getBankCardDayMax());
        updateInfo.setBankCardCorOnceMax(reqParam.getBankCardCorOnceMax());
        updateInfo.setBankCardPriOnceMax(reqParam.getBankCardPriOnceMax());

        updateById(updateInfo);
    }
}
