
package com.tmerclub.cloud.multishop.service.impl;

import com.tmerclub.cloud.api.auth.constant.SysTypeEnum;
import com.tmerclub.cloud.api.auth.feign.AccountFeignClient;
import com.tmerclub.cloud.api.auth.vo.AuthAccountVO;
import com.tmerclub.cloud.api.biz.feign.NotifyFeignClient;
import com.tmerclub.cloud.api.multishop.vo.ShopBankCardVO;
import com.tmerclub.cloud.api.multishop.vo.ShopDetailVO;
import com.tmerclub.cloud.api.payment.allinpay.order.resp.PayByBackSmsResp;
import com.tmerclub.cloud.api.payment.allinpay.order.resp.WithdrawApplyResp;
import com.tmerclub.cloud.api.payment.constant.PaySysType;
import com.tmerclub.cloud.api.payment.feign.AllinpayFeignClient;
import com.tmerclub.cloud.api.platform.feign.ConfigFeignClient;
import com.tmerclub.cloud.api.platform.vo.SysConfigApiVO;
import com.tmerclub.cloud.common.constant.*;
import com.tmerclub.cloud.common.database.dto.PageDTO;
import com.tmerclub.cloud.common.database.util.PageUtil;
import com.tmerclub.cloud.common.database.vo.PageVO;
import com.tmerclub.cloud.common.exception.LuckException;
import com.tmerclub.cloud.common.leaf.manager.SegmentManager;
import com.tmerclub.cloud.common.response.ResponseEnum;
import com.tmerclub.cloud.common.response.ServerResponseEntity;
import com.tmerclub.cloud.common.rocketmq.config.RocketMqConstant;
import com.tmerclub.cloud.common.security.AuthUserContext;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.common.util.DateUtils;
import com.tmerclub.cloud.common.util.Json;
import com.tmerclub.cloud.constant.DistributedIdKey;
import com.tmerclub.cloud.multishop.constant.*;
import com.tmerclub.cloud.multishop.dto.AllinpayShopWithdrawCashDTO;
import com.tmerclub.cloud.multishop.dto.ShopWithdrawCashConfigDto;
import com.tmerclub.cloud.multishop.dto.ShopWithdrawCashDTO;
import com.tmerclub.cloud.multishop.mapper.ShopWalletMapper;
import com.tmerclub.cloud.multishop.mapper.ShopWithdrawCashMapper;
import com.tmerclub.cloud.multishop.model.ShopWithdrawCash;
import com.tmerclub.cloud.multishop.mongo.MongoShopWalletLogBO;
import com.tmerclub.cloud.multishop.service.*;
import com.tmerclub.cloud.multishop.vo.ShopWalletVO;
import com.tmerclub.cloud.multishop.vo.ShopWithdrawCashVO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.client.producer.SendStatus;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 商家提现申请信息
 *
 * @author tmerclub
 */
@Service
public class ShopWithdrawCashServiceImpl implements ShopWithdrawCashService {
    private static final Logger logger = LoggerFactory.getLogger(ShopWithdrawCashServiceImpl.class);

    @Autowired
    private ShopWithdrawCashMapper shopWithdrawCashMapper;
    @Autowired
    private ShopDetailService shopDetailService;
    @DubboReference
    private NotifyFeignClient sendNotifyFeignClient;
    @DubboReference
    private AccountFeignClient accountFeignClient;
    @Autowired
    private ShopWalletService shopWalletService;
    @Autowired
    private ShopBankCardService shopBankCardService;
    @Autowired
    private ShopWalletMapper shopWalletMapper;
    @Autowired
    private RocketMQTemplate addShopWalletLogTemplate;
    @Autowired
    private SegmentManager segmentManager;
    @DubboReference
    private ConfigFeignClient configFeignClient;
    @Autowired
    private ShopAllinpayService shopAllinpayService;
    @DubboReference
    private AllinpayFeignClient allinpayFeignClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void apply(ShopWithdrawCashDTO shopWithdrawCashDTO, Long shopId) {
        Integer paySysType = shopAllinpayService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        Date now = new Date();
        this.checkWithdrawInfo(shopWithdrawCashDTO, shopId);
        ShopWithdrawCash shopWithdrawCash = BeanUtil.map(shopWithdrawCashDTO, ShopWithdrawCash.class);
        shopWithdrawCash.setUpdateTime(now);
        shopWithdrawCash.setCreateTime(now);
        shopWithdrawCash.setStatus(ShopWithdrawCashStatus.WAITAUDIT.value());
        shopWithdrawCash.setShopId(shopId);
        shopWithdrawCash.setPaySysType(paySysType);
        this.checkConfig(shopWithdrawCash);
        ShopWalletVO shopWallet = shopWalletService.getByShopId(shopId);
        if (shopWithdrawCash.getAmount() > shopWallet.getSettledAmount()) {
            // 可提现金额不足
            throw new LuckException("可提现金额不足");
        }
        // 插入提现申请记录
        shopWithdrawCashMapper.save(shopWithdrawCash);

        // 更新钱包，添加提现日志
        changeWalletAndAddLog(shopId, paySysType, now, shopWithdrawCash);
    }

    private void changeWalletAndAddLog(Long shopId, Integer paySysType, Date now, ShopWithdrawCash shopWithdrawCash) {
        // 更新钱包的结算金额和冻结金额
        updateShopWalletByApply(shopWithdrawCash);

        List<MongoShopWalletLogBO> shopWalletLogList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        // 保存提现记录
        this.saveShopWalletLog(shopWithdrawCash.getAmount(), shopId, now, ShopWalletChangeReason.APPLY_CASH, shopWalletLogList, paySysType);

        // 用mq批量保存钱包日志
        SendStatus sendWalletLogStatus = addShopWalletLogTemplate.syncSend(RocketMqConstant.ADD_SHOP_WALLET_LOG_TOPIC, new GenericMessage<>(shopWalletLogList)).getSendStatus();
        if (!Objects.equals(sendWalletLogStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String allinpayApply(AllinpayShopWithdrawCashDTO allinpayShopWithdrawCashDTO, Long shopId) {
        Long amount = allinpayShopWithdrawCashDTO.getAmount();
        // 校验提现条件
        this.checkAllinpay(shopId, amount);
        ShopWithdrawCash shopWithdrawCash = new ShopWithdrawCash();
        shopWithdrawCash.setAmount(amount);
        shopWithdrawCash.setShopId(shopId);
        shopWithdrawCash.setPayingCardNo(allinpayShopWithdrawCashDTO.getBankCardNo());
        shopWithdrawCash.setPaySysType(PaySysType.ALLINPAY.value());
        this.checkConfig(shopWithdrawCash);
        // 提现订单支付成功的条件为：status = OK且payStatus = success。
        String bizUserId = AllinpayConstant.SHOP + shopId;
        ServerResponseEntity<WithdrawApplyResp> withdrawApplyResponse = allinpayFeignClient.withdrawApply(bizUserId, amount, allinpayShopWithdrawCashDTO.getBankCardNo(), SysTypeEnum.MULTISHOP.value());
        if (!withdrawApplyResponse.isSuccess()) {
            throw new LuckException(withdrawApplyResponse.getMsg());
        }
        // 保存至数据库，确认支付后更新状态
        String bizOrderNo = withdrawApplyResponse.getData().getBizOrderNo();
        shopWithdrawCash.setAllinpayStatus(AllinpayWithdrawCashStatusType.APPLY_SUCCESS.value());
        shopWithdrawCash.setBizOrderNo(bizOrderNo);
        shopWithdrawCashMapper.save(shopWithdrawCash);
        // 更新钱包，添加提现日志
        changeWalletAndAddLog(shopId, PaySysType.ALLINPAY.value(), new Date(), shopWithdrawCash);
        return bizOrderNo;
    }

    @Override
    public void confirmWithdrawPay(AllinpayShopWithdrawCashDTO shopWithdrawCashDTO, Long shopId) {
        ShopWithdrawCash shopWithdrawCash = shopWithdrawCashMapper.getByBizOrderNo(shopWithdrawCashDTO.getBizOrderNo());
        if (Objects.isNull(shopWithdrawCash)) {
            throw new LuckException("提现记录不存在");
        }
        if (!Objects.equals(shopId, shopWithdrawCash.getShopId())) {
            throw new LuckException("当前提现订单号不属于该店铺");
        }
        if (!Objects.equals(shopWithdrawCash.getAllinpayStatus(), AllinpayWithdrawCashStatusType.APPLY_SUCCESS.value())
                && !Objects.equals(shopWithdrawCash.getAllinpayStatus(), AllinpayWithdrawCashStatusType.WAIT_PAY.value())) {
            throw new LuckException("申请状态异常，请刷新重试");
        }
        String bizUserId = AllinpayConstant.SHOP + shopId;
        ServerResponseEntity<PayByBackSmsResp> payResponse = allinpayFeignClient.payByBackSms(bizUserId, shopWithdrawCash.getBizOrderNo(), shopWithdrawCashDTO.getVerificationCode());
        if (!payResponse.isSuccess()) {
            throw new LuckException(payResponse.getMsg());
        }
        PayByBackSmsResp payByBackSmsResp = payResponse.getData();
        String payFailMessage = payByBackSmsResp.getPayFailMessage();
        String payStatus = payByBackSmsResp.getPayStatus();
        if (Objects.equals(payStatus, AllinpayPayStatus.UNPAY.value())) {
            // 收银宝快捷短信验证码输入错误场景，允许商户继续调用确认支付
            shopWithdrawCash.setAllinpayStatus(AllinpayWithdrawCashStatusType.WAIT_PAY.value());
            shopWithdrawCash.setPayFailMessage(payFailMessage);
            logger.error("提现订单{}提现失败，原因为：{}", payByBackSmsResp.getBizOrderNo(), payFailMessage);
            shopWithdrawCashMapper.update(shopWithdrawCash);
        }
    }

    private void allinpayFail(Long shopId, ShopWithdrawCash shopWithdrawCash, Long amount, String bizOrderNo, String payFailMessage, List<MongoShopWalletLogBO> list) {
        shopWithdrawCash.setAllinpayStatus(AllinpayWithdrawCashStatusType.CASH_FAIL.value());
        shopWithdrawCash.setPayFailMessage(payFailMessage);
        logger.error("商家提现订单{}提现失败，原因为：{}", bizOrderNo, payFailMessage);
        boolean subFreezeAmount = shopWalletMapper.subFreezeAmount(shopId, amount, shopWithdrawCash.getPaySysType()) > 0;
        if (!subFreezeAmount) {
            throw new LuckException("商家确认支付失败，冻结金额异常");
        }
        // 增加结算金额到主分片(不增加总结算金额)
        boolean addSettledAmount = shopWalletMapper.addSettledAmount(shopId, amount, shopWithdrawCash.getPaySysType(), false) > 0;
        if (!addSettledAmount) {
            throw new LuckException("商家确认支付失败，结算金额异常");
        }
        // 保存日志
        this.saveShopWalletLog(amount, shopId, new Date(), ShopWalletChangeReason.REFUSE_CASH, list, shopWithdrawCash.getPaySysType());
    }

    private void allinpaySuccess(Long shopId, ShopWithdrawCash shopWithdrawCash, Long amount, List<MongoShopWalletLogBO> list) {
        shopWithdrawCash.setAllinpayStatus(AllinpayWithdrawCashStatusType.CASH_SUCCESS.value());
        // 更新店铺结算金额
        boolean subFreezeAmountSuccess = shopWalletMapper.subFreezeAmount(shopId, amount, shopWithdrawCash.getPaySysType()) > 0;
        if (!subFreezeAmountSuccess) {
            throw new LuckException("冻结金额不足，提现失败");
        }
        // 保存日志
        this.saveShopWalletLog(amount, shopId, new Date(), ShopWalletChangeReason.PASS_CASH, list, shopWithdrawCash.getPaySysType());
    }

    @Override
    public void resendPaySms(String bizOrderNo, Long shopId) {
        ShopWithdrawCash shopWithdrawCash = shopWithdrawCashMapper.getByBizOrderNo(bizOrderNo);
        if (Objects.isNull(shopWithdrawCash)) {
            throw new LuckException("提现记录不存在");
        }
        if (!Objects.equals(shopId, shopWithdrawCash.getShopId())) {
            throw new LuckException("当前提现订单号不属于该店铺");
        }
        if (!Objects.equals(shopWithdrawCash.getAllinpayStatus(), AllinpayWithdrawCashStatusType.WAIT_PAY.value())) {
            throw new LuckException("提现申请不在未支付状态，请刷新重试");
        }
        ServerResponseEntity<Void> response = allinpayFeignClient.resendPaySms(bizOrderNo);
        if (!response.isSuccess()) {
            throw new LuckException(response.getMsg());
        }
    }

    @Override
    public void withdrawBack(String bizOrderNo, String payStatus, String bizUserId, String payFailMessage) {
        ShopWithdrawCash shopWithdrawCash = shopWithdrawCashMapper.getByBizOrderNo(bizOrderNo);
        if (Objects.isNull(shopWithdrawCash)) {
            throw new LuckException("提现记录不存在");
        }
        if (Objects.equals(shopWithdrawCash.getAllinpayStatus(), AllinpayWithdrawCashStatusType.CASH_SUCCESS.value())) {
            return;
        }
        Long shopId = shopWithdrawCash.getShopId();
        Long amount = shopWithdrawCash.getAmount();
        List<MongoShopWalletLogBO> list = new ArrayList<>(Constant.INITIAL_CAPACITY);
        if (Objects.equals(payStatus, AllinpayPayStatus.OK.value())) {
            allinpaySuccess(shopId, shopWithdrawCash, amount, list);
        } else if (Objects.equals(payStatus, AllinpayPayStatus.ERROR.value())) {
            allinpayFail(shopId, shopWithdrawCash, amount, bizOrderNo, payFailMessage, list);
        }
        shopWithdrawCashMapper.update(shopWithdrawCash);
        // 用mq批量保存钱包日志
        SendStatus sendWalletLogStatus = addShopWalletLogTemplate.syncSend(RocketMqConstant.ADD_SHOP_WALLET_LOG_TOPIC, new GenericMessage<>(list)).getSendStatus();
        if (!Objects.equals(sendWalletLogStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }
    }

    private void checkAllinpay(Long shopId, Long amount) {
        if (!shopAllinpayService.getIsAllinpay()) {
            throw new LuckException("当前不支持通联提现");
        }
        if (amount < 1) {
            throw new LuckException("提现金额不能少于1.00元");
        }
        ShopDetailVO shopDetail = shopDetailService.getByShopId(shopId);
        if (Objects.equals(shopDetail.getIsBindPhone(), 0) ||
                !Objects.equals(shopDetail.getCompanyInfoProcessStatus(), CompanyInfoProcessStatus.SUCCESS.value()) ||
                !Objects.equals(shopDetail.getIdCardCollectProcessStatus(), IdCardCollectProcessStatus.ALL.value())) {
            throw new LuckException("店铺信息未通过审核，无法提现");
        }
    }

    /**
     * 更新钱包金额
     */
    private void updateShopWalletByApply(ShopWithdrawCash shopWithdrawCash) {
        Long shopId = shopWithdrawCash.getShopId();
        Long changeAmount = shopWithdrawCash.getAmount();
        if (Objects.equals(changeAmount, 0L)) {
            return;
        }
        // 1.增加冻结金额
        boolean addFreezeAmountSuccess = shopWalletMapper.addFreezeAmount(shopId, changeAmount, shopWithdrawCash.getPaySysType()) > 0;
        if (!addFreezeAmountSuccess) {
            throw new LuckException("提现申请发生异常");
        }
        // 2.减少结算金额
        boolean isSuccess = shopWalletService.subSettledAmount(shopId, changeAmount, shopWithdrawCash.getPaySysType());
        if (!isSuccess) {
            throw new LuckException("可提现金额不足");
        }
    }

    @Override
    public PageVO<ShopWithdrawCashVO> pageByParam(PageDTO pageDTO, ShopWithdrawCashDTO shopWithdrawCashDTO) {
        shopWithdrawCashDTO.setPaySysType(shopAllinpayService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value());
        return PageUtil.doPage(pageDTO, () -> shopWithdrawCashMapper.listByParam(shopWithdrawCashDTO));
    }

    @Override
    public ShopWithdrawCashVO getDetailByCashId(Long cashId) {
        return shopWithdrawCashMapper.getDetailByCashId(cashId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void auditWithdrawCash(ShopWithdrawCashDTO shopWithdrawCashDTO, Long userId) {
        if (shopAllinpayService.getIsAllinpay()) {
            throw new LuckException("开启通联后，平台无需审核商家提现信息");
        }
        ShopWithdrawCashVO shopWithdrawCashVO = shopWithdrawCashMapper.getDetailByCashId(shopWithdrawCashDTO.getCashId());
        if (Objects.isNull(shopWithdrawCashVO)) {
            throw new LuckException("未找到申请信息");
        }
        if (!Objects.equals(shopWithdrawCashVO.getStatus(), ShopWithdrawCashStatus.WAITAUDIT.value())) {
            throw new LuckException("该申请已被审核");
        }

        this.checkAuditInfo(shopWithdrawCashDTO, shopWithdrawCashDTO.getShopId());
        ShopWithdrawCash shopWithdrawCash = BeanUtil.map(shopWithdrawCashVO, ShopWithdrawCash.class);
        Date now = new Date();
        shopWithdrawCash.setAuditorId(userId);
        shopWithdrawCash.setAuditingTime(now);
        shopWithdrawCash.setStatus(shopWithdrawCashDTO.getStatus());
        shopWithdrawCash.setRemarks(shopWithdrawCashDTO.getRemarks());
        shopWithdrawCash.setPayingAccount(shopWithdrawCashDTO.getPayingAccount());
        shopWithdrawCash.setPayingTime(shopWithdrawCashDTO.getPayingTime());
        shopWithdrawCash.setPayingCardNo(shopWithdrawCashDTO.getPayingCardNo());
        Long shopId = shopWithdrawCash.getShopId();
        Long changeAmount = shopWithdrawCash.getAmount();

        ShopWalletChangeReason shopWalletChangeReason = ShopWalletChangeReason.PASS_CASH;
        List<MongoShopWalletLogBO> shopWalletLogList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        if (!Objects.equals(changeAmount, 0L)) {
            switch (Objects.requireNonNull(ShopWithdrawCashStatus.instance(shopWithdrawCash.getStatus()))) {
                case SUCCESSAUDIT:
                    // 审核通过, 减去冻结的金额
                    boolean subFreezeAmountSuccess = shopWalletMapper.subFreezeAmount(shopId, changeAmount, PaySysType.DEFAULT.value()) > 0;
                    if (!subFreezeAmountSuccess) {
                        throw new LuckException("冻结金额不足，提现失败");
                    }
                    break;
                case FAILAUDIT:
                    // 审核不通过，将冻结的金额返回到已结算金额
                    boolean subFreezeAmount = shopWalletMapper.subFreezeAmount(shopId, changeAmount, PaySysType.DEFAULT.value()) > 0;
                    if (!subFreezeAmount) {
                        throw new LuckException("审核失败，冻结金额异常");
                    }
                    // 增加结算金额到主分片(不增加总结算金额)
                    boolean addSettledAmount = shopWalletMapper.addSettledAmount(shopId, changeAmount, PaySysType.DEFAULT.value(), false) > 0;
                    if (!addSettledAmount) {
                        throw new LuckException("审核失败，结算金额异常");
                    }
                    shopWalletChangeReason = ShopWalletChangeReason.REFUSE_CASH;
                    break;
                default:
                    // 审核状态有误
                    throw new LuckException("审核状态有误");
            }
        }
        // 保存日志
        this.saveShopWalletLog(changeAmount, shopId, now, shopWalletChangeReason, shopWalletLogList, PaySysType.DEFAULT.value());
        // 用mq批量保存钱包日志
        SendStatus sendWalletLogStatus = addShopWalletLogTemplate.syncSend(RocketMqConstant.ADD_SHOP_WALLET_LOG_TOPIC, new GenericMessage<>(shopWalletLogList)).getSendStatus();
        if (!Objects.equals(sendWalletLogStatus, SendStatus.SEND_OK)) {
            throw new LuckException(ResponseEnum.EXCEPTION);
        }

        if (shopWithdrawCashMapper.updateByIdAndStatus(shopWithdrawCash, shopWithdrawCash.getCashId(), ShopWithdrawCashStatus.WAITAUDIT.value()) != 1) {
            throw new LuckException("该申请已被审核");
        }
    }

    private void checkConfig(ShopWithdrawCash shopWithdrawCash) {
        ShopWithdrawCashConfigDto config = getConfig();
        if (shopWithdrawCash.getAmount() < config.getWithdrawCashLeast()) {
            throw new LuckException("商家提现金额过少，最低提现:" + config.getWithdrawCashLeast() / 100);
        }
        if (Objects.nonNull(config.getWithdrawCashMax()) && shopWithdrawCash.getAmount() > config.getWithdrawCashMax()) {
            throw new LuckException("商家提现金额过大,最高提现:" + config.getWithdrawCashMax() / 100);
        }
        Integer frequency = config.getFrequency();
        String date;
        Date startTimes;
        Date endTimes;
        if (frequency.equals(WithdrawCashType.WEEKEND.value())) {
            date = WithdrawCashType.WEEKEND.date();
            startTimes = DateUtils.getCurrentWeekStartTimes(new Date());
            endTimes = DateUtils.getCurrentWeekEndTimes(new Date());
        } else if (frequency.equals(WithdrawCashType.MONTH.value())) {
            date = WithdrawCashType.MONTH.date();
            startTimes = DateUtils.getMonthFirstOrLastDay(new Date(), 0);
            endTimes = DateUtils.getMonthFirstOrLastDay(new Date(), 1);
        } else {
            date = WithdrawCashType.YEAR.date();
            startTimes = DateUtils.getCurrentYearStartTime(new Date());
            endTimes = DateUtils.getCurrentYearEndTime(new Date());
        }
        int count = shopWithdrawCashMapper.getWithdrawCashCount(startTimes, endTimes, shopWithdrawCash);
        if (count + 1 > config.getNumber()) {
            throw new LuckException("超出提现频率限制,当前频率为:" + date + " " + config.getNumber() + "次");
        }
    }


    @Override
    public void saveConfig(ShopWithdrawCashConfigDto shopWithdrawCashDto) {
        checkParam(shopWithdrawCashDto);
        SysConfigApiVO sysConfigApiVO = new SysConfigApiVO();
        sysConfigApiVO.setParamKey(Constant.SHOP_WITHDRWA);
        sysConfigApiVO.setRemark("商家提现配置");
        sysConfigApiVO.setParamValue(Json.toJsonString(shopWithdrawCashDto));
        configFeignClient.saveOrUpdateSysConfig(sysConfigApiVO);
    }

    @Override
    public ShopWithdrawCashConfigDto getConfig() {

        ShopWithdrawCashConfigDto shopWithdrawCashConfigDto = Json.parseObject(configFeignClient.getConfig(Constant.SHOP_WITHDRWA).getData(), ShopWithdrawCashConfigDto.class);
        if (Objects.isNull(shopWithdrawCashConfigDto)) {
            shopWithdrawCashConfigDto = new ShopWithdrawCashConfigDto();
            shopWithdrawCashConfigDto.setWithdrawCashLeast(100.0D);
            shopWithdrawCashConfigDto.setFrequency(1);
            shopWithdrawCashConfigDto.setNumber(1);
        }
        return shopWithdrawCashConfigDto;
    }

    @Override
    public void checkDrawCashAmount(Long amount) {
        // 基础数值检查 - 小于100
        ShopWithdrawCashConfigDto config = this.getConfig();
        if (amount < config.getWithdrawCashLeast()) {
            throw new LuckException("提现金额不能少于" + config.getWithdrawCashLeast() / 100 + "元");
        }
        // 系统配置检查
        ShopWithdrawCash shopWithdrawCash = new ShopWithdrawCash();
        shopWithdrawCash.setAmount(amount);
        this.checkConfig(shopWithdrawCash);
    }

    private void checkParam(ShopWithdrawCashConfigDto shopWithdrawCashDto) {
        Double least = shopWithdrawCashDto.getWithdrawCashLeast();
        Double max = shopWithdrawCashDto.getWithdrawCashMax();
        Integer frequency = shopWithdrawCashDto.getFrequency();
        Integer number = shopWithdrawCashDto.getNumber();
        if (Objects.isNull(least) || least < 1) {
            throw new LuckException("商家最少金额设置错误");
        }
        if (Objects.nonNull(max) && max < least) {
            throw new LuckException("商家最大金额设置错误");
        }
        boolean isError = Objects.isNull(frequency) || (!frequency.equals(WithdrawCashType.WEEKEND.value()) && !frequency.equals(WithdrawCashType.MONTH.value()) && !frequency.equals(WithdrawCashType.YEAR.value()));
        if (isError) {
            throw new LuckException("商家提现频率设置错误");
        }
        if (Objects.isNull(number) || number < 1) {
            throw new LuckException("商家提现次数设置错误");
        }
    }

    private void saveShopWalletLog(Long changeAmount, Long shopId, Date now, ShopWalletChangeReason shopWalletChangeReason, List<MongoShopWalletLogBO> shopWalletLogList, Integer paySysType) {

        // 插入结算金额修改记录【提现申请/提现申请被拒绝】
        if (Objects.equals(shopWalletChangeReason, ShopWalletChangeReason.APPLY_CASH) || Objects.equals(shopWalletChangeReason, ShopWalletChangeReason.REFUSE_CASH)) {
            MongoShopWalletLogBO shopWalletLog = new MongoShopWalletLogBO();
            Long walletLogId = segmentManager.getSegmentId(DistributedIdKey.tmerclub_SHOP_WALLET_LOG);
            shopWalletLog.setWalletLogId(walletLogId);
            shopWalletLog.setCreateTime(now);
            shopWalletLog.setUpdateTime(now);
            shopWalletLog.setShopId(shopId);
            shopWalletLog.setPaySysType(paySysType);
            shopWalletLog.setReason(shopWalletChangeReason.value());
            shopWalletLog.setShopChangeAmount(Math.abs(changeAmount));
            shopWalletLog.setShopIoType(Objects.equals(shopWalletChangeReason, ShopWalletChangeReason.APPLY_CASH) ? ShopWalletIoType.EXPENDITURE.value() : ShopWalletIoType.INCOME.value());
            shopWalletLog.setAmountType(ShopWalletAmountType.SETTLED_AMOUNT.value());
            shopWalletLogList.add(shopWalletLog);
        }

        // 插入冻结金额修改记录
        MongoShopWalletLogBO shopWalletLog = new MongoShopWalletLogBO();
        shopWalletLog.setWalletLogId(segmentManager.getSegmentId(DistributedIdKey.tmerclub_SHOP_WALLET_LOG));
        shopWalletLog.setPaySysType(paySysType);
        shopWalletLog.setCreateTime(now);
        shopWalletLog.setUpdateTime(now);
        shopWalletLog.setShopId(shopId);
        shopWalletLog.setReason(shopWalletChangeReason.value());
        shopWalletLog.setShopChangeAmount(Math.abs(changeAmount));
        shopWalletLog.setShopIoType(!Objects.equals(shopWalletChangeReason, ShopWalletChangeReason.APPLY_CASH) ? ShopWalletIoType.EXPENDITURE.value() : ShopWalletIoType.INCOME.value());
        shopWalletLog.setAmountType(ShopWalletAmountType.FREEZE_AMOUNT.value());
        shopWalletLogList.add(shopWalletLog);
    }

    private void checkWithdrawInfo(ShopWithdrawCashDTO shopWithdrawCashDTO, Long shopId) {
        Integer sysType = AuthUserContext.get().getSysType();
        ServerResponseEntity<AuthAccountVO> merchantInfoRes = accountFeignClient.getAccountInfoByTenantId(shopId, sysType);
        if (!merchantInfoRes.isSuccess() || Objects.isNull(merchantInfoRes.getData())) {
            throw new LuckException("商家信息获取出错");
        }
        if (shopWithdrawCashDTO.getAmount() < 1) {
            throw new LuckException("提现金额不能少于1.00元");
        }
        ServerResponseEntity<Boolean> sendNotifyResponse = sendNotifyFeignClient.checkValidCode(merchantInfoRes.getData().getPhone(), shopWithdrawCashDTO.getValidCode(), SendTypeEnum.VALID);
        if (!sendNotifyResponse.isSuccess() || !sendNotifyResponse.getData()) {
            throw new LuckException("验证码有误或已过期");
        }
        checkAuditInfo(shopWithdrawCashDTO, shopId);
    }

    private void checkAuditInfo(ShopWithdrawCashDTO shopWithdrawCashDTO, Long shopId) {
        ShopDetailVO shopDetailVO = shopDetailService.getByShopId(shopId);
        if (Objects.isNull(shopDetailVO)) {
            throw new LuckException("店铺不存在");
        }
        ShopBankCardVO shopBankCard = shopBankCardService.getByShopBankCardId(shopWithdrawCashDTO.getShopBankCardId());
        if (Objects.isNull(shopBankCard) || !Objects.equals(shopBankCard.getShopId(), shopId)) {
            throw new LuckException("银行卡信息错误");
        }
    }
}
