package com.sqx.modules.pay.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sqx.common.exception.SqxException;
import com.sqx.common.utils.PageUtils;
import com.sqx.common.utils.Result;
import com.sqx.modules.app.dao.MsgDao;
import com.sqx.modules.app.dao.UserDao;
import com.sqx.modules.app.entity.*;
import com.sqx.modules.app.service.UserInfoService;
import com.sqx.modules.app.service.UserMoneyDetailsService;
import com.sqx.modules.app.service.UserMoneyService;
import com.sqx.modules.app.service.UserService;
import com.sqx.modules.common.entity.CommonInfo;
import com.sqx.modules.common.service.CommonInfoService;
import com.sqx.modules.invite.entity.InviteMoney;
import com.sqx.modules.invite.service.InviteMoneyService;
import com.sqx.modules.message.dao.MessageInfoDao;
import com.sqx.modules.message.entity.MessageInfo;
import com.sqx.modules.pay.dao.CashOutDao;
import com.sqx.modules.pay.entity.CashOut;
import com.sqx.modules.pay.entity.WithdrawTypeEnum;
import com.sqx.modules.pay.service.CashOutService;
import com.sqx.modules.pay.wuyou.BaseResp;
import com.sqx.modules.pay.wuyou.WuyouPay;
import com.sqx.modules.sys.entity.SysUserEntity;
import com.sqx.modules.sys.service.SysUserService;
import com.sqx.modules.utils.AliPayOrderUtil;
import com.sqx.modules.utils.AmountCalUtils;
import com.sqx.modules.utils.ParamPageUtils;
import com.sqx.modules.utils.excel.ExcelData;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import weixin.popular.api.MessageAPI;
import weixin.popular.bean.message.templatemessage.TemplateMessage;
import weixin.popular.bean.message.templatemessage.TemplateMessageItem;
import weixin.popular.bean.message.templatemessage.TemplateMessageResult;
import weixin.popular.support.TokenManager;

import javax.websocket.SendResult;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 提现申请记录
 */
@Service
@Slf4j
public class CashOutServiceImpl extends ServiceImpl<CashOutDao, CashOut> implements CashOutService {

    /**
     * 提现申请记录
     */
    @Autowired
    private CashOutDao cashOutDao;
    /**
     * 通用配置
     */
    @Autowired
    private CommonInfoService commonInfoService;
    /**
     * app用户
     */
    @Autowired
    private UserService userService;
    @Autowired
    private MessageInfoDao messageInfoDao;
    @Autowired
    private UserMoneyService userMoneyService;
    @Autowired
    private UserMoneyDetailsService userMoneyDetailsService;
    @Autowired
    private InviteMoneyService inviteMoneyService;
    @Autowired
    private SysUserService sysUserService;
    private final UserInfoService userInfoService;
    @Autowired
    private MsgDao msgDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private WuyouPay wuyouPay;

    public CashOutServiceImpl(UserInfoService userInfoService) {
        this.userInfoService = userInfoService;
    }

    @Override
    public PageUtils selectCashOutList(Integer page, Integer limit, CashOut cashOut,@Param("isApp") boolean isApp) {
        PageHelper.startPage(page, limit);
        return PageUtils.page(new PageInfo<>(baseMapper.selectCashOutPage(cashOut, isApp)));
    }

    @Override
    public ExcelData excelPayDetails(CashOut cashOut1) {
        List<CashOut> cashOutList = baseMapper.selectCashOutList(cashOut1);
        ExcelData data = new ExcelData();
        data.setName("提现列表");
        List<String> titles = new ArrayList<>();
        titles.add("编号");
        titles.add("用户类型");
        titles.add("用户名称");
        titles.add("支付宝账号");
        titles.add("支付宝名称");
        titles.add("提现金币");
        titles.add("状态");
        titles.add("拒绝原因");
        titles.add("申请时间");
        titles.add("转账/拒绝时间");
        titles.add("转账订单号");
        data.setTitles(titles);
        List<List<Object>> rows = new ArrayList<>();
        for (CashOut cashOut : cashOutList) {
            List<Object> row = new ArrayList<>();
            row.add(cashOut.getId());
            if (cashOut.getUserType() == 1) {
                row.add("用户");
                row.add(cashOut.getUserName());
            } else {
                row.add("分销商");
                row.add(cashOut.getSysUserName());
            }
            row.add(cashOut.getZhifubao());
            row.add(cashOut.getZhifubaoName());
            row.add(cashOut.getMoney());

            if (cashOut.getState() == -1) {
                row.add("已拒绝");
            } else if (cashOut.getState() == 0) {
                row.add("待转账");
            } else {
                row.add("成功");
            }
            row.add(cashOut.getRefund() == null ? "" : cashOut.getRefund());
            row.add(cashOut.getCreateAt());
            row.add(StringUtils.isEmpty(cashOut.getOutAt()) ? "" : cashOut.getOutAt());
            row.add(cashOut.getOrderNumber());
            rows.add(row);
        }
        data.setRows(rows);
        return data;
    }


    @Override
    public CashOut selectById(Long id) {
        return cashOutDao.selectById(id);
    }

    @Override
    public int saveBody(CashOut cashOut) {
        return cashOutDao.insert(cashOut);
    }


    @Override
    public int update(CashOut cashOut) {
        return cashOutDao.updateById(cashOut);
    }


    @Override
    public void cashOutSuccess(String openId, String date, String money, String payWay, String url) {
        UserEntity userByWxId = userService.queryByWxOpenId(openId);
        if (userByWxId != null) {
            MessageInfo messageInfo = new MessageInfo();
            messageInfo.setState(String.valueOf(5));
            messageInfo.setIsSee("0");
            messageInfo.setContent("您好，您的提现转账成功，请注意查收！提现金币【" + money + "元】！支付宝收款账号 " + payWay + "感谢您的使用！如有疑问请在公众号中发送您的问题联系客服");
            messageInfo.setTitle("提现成功通知");
            messageInfo.setUserName(userByWxId.getUserName());
            messageInfo.setUserId(String.valueOf(userByWxId.getUserId()));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date now = new Date();
            messageInfo.setCreateAt(sdf.format(now));
            messageInfoDao.insert(messageInfo);
            if (userByWxId.getClientid() != null) {
                userService.pushToSingle("提现成功通知", "您好，您的提现转账成功，请注意查收！提现金币【" + money + "元】！支付宝收款账号 " + payWay + "感谢您的使用！如有疑问请在公众号中发送您的问题联系客服", userByWxId.getClientid());
            }
        }


        CommonInfo three = commonInfoService.findOne(39);
        String apkey = "";
        if (three != null) {
            apkey = three.getValue();
        }
        LinkedHashMap<String, TemplateMessageItem> data = new LinkedHashMap<>();
        data.put("first", new TemplateMessageItem("您好，您的提现转账成功，请注意查收", "#d71345"));
        data.put("keyword1", new TemplateMessageItem(money + " 元", "#d71345"));
        data.put("keyword2", new TemplateMessageItem(date, "#d71345"));
        data.put("remark", new TemplateMessageItem("支付宝收款账号 " + payWay + "感谢您的使用！如有疑问请在公众号中发送您的问题联系客服", null));
        sendWxMessage(apkey, data, openId, url);
    }

    /**
     * 退款成功通知
     */
    @Override
    public void refundSuccess(UserEntity userByWxId, String date, String money, String url, String content) {
        MessageInfo messageInfo = new MessageInfo();
        messageInfo.setState(String.valueOf(5));
        messageInfo.setIsSee("0");
        messageInfo.setContent(content);
        messageInfo.setTitle("提现失败提醒");
        messageInfo.setUserName(userByWxId.getUserName());
        messageInfo.setUserId(String.valueOf(userByWxId.getUserId()));
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date now = new Date();
        messageInfo.setCreateAt(sdf.format(now));
        messageInfoDao.insert(messageInfo);
        if (userByWxId.getClientid() != null) {
            userService.pushToSingle("提现失败提醒", content, userByWxId.getClientid());
        }
        CommonInfo three = commonInfoService.findOne(77);
        String apkey = "";
        if (three != null) {
            apkey = three.getValue();
        }
        LinkedHashMap<String, TemplateMessageItem> data = new LinkedHashMap<>();
        data.put("first", new TemplateMessageItem("您好，您发起的提现失败了", "#d71345"));
        data.put("keyword1", new TemplateMessageItem(money + " 元", "#d71345"));
        data.put("keyword2", new TemplateMessageItem(date, "#d71345"));
        data.put("keyword3", new TemplateMessageItem(content, "#d71345"));
        data.put("remark", new TemplateMessageItem("请您按照失败原因修改相关信息后，重新提现！", null));
        sendWxMessage(apkey, data, userByWxId.getOpenId(), url);
    }

    @Override
    public Double selectCashOutSum(Long userId, Date startTime, Date endTime) {
        return cashOutDao.selectCashOutSum(userId, startTime, endTime);
    }

    @Override
    public Double sumMoney(String start, String end, Integer flag) {
        return cashOutDao.sumMoney(start, end, flag);
    }

    @Override
    public Integer countMoney(String start, String end, Integer flag) {
        return cashOutDao.countMoney(start, end, flag);
    }

    @Override
    public Integer stayMoney(String start, String end, Integer flag) {
        return cashOutDao.stayMoney(start, end, flag);
    }

    @Override
    public void updateMayMoney(int i, Long userId, Double money) {
        cashOutDao.updateMayMoney(i, userId, money);
    }


    @Override
    public List<CashOut> selectCashOutLimit3() {
        return cashOutDao.selectCashOutLimit3();
    }

    private void sendWxMessage(String templateId, LinkedHashMap<String, TemplateMessageItem> data, String openid, String url) {
        TemplateMessage templateMessage = new TemplateMessage();
        templateMessage.setTouser(openid);
        templateMessage.setTemplate_id(templateId);
        templateMessage.setData(data);
        templateMessage.setUrl(url);
        TemplateMessageResult templateMessageResult = MessageAPI.messageTemplateSend(getWxToken(), templateMessage);
        if (templateMessageResult.isSuccess()) {
            new SendResult();
        } else {
            new SendResult();
        }
    }

    private String getWxToken() {
        try {
            //微信appid
            CommonInfo one = commonInfoService.findOne(5);
            return TokenManager.getToken(one.getValue());
        } catch (Exception e) {
            throw new RuntimeException("GET_ACCESS_TOKEN_FAIL");
        }
    }


    @Override
    @Transactional
    public Result cashMoney(Long userId, Double money) {
        if (money == null || money <= 0.00) {
            return Result.error("请不要输入小于0的数字,请输入正确的提现金币！");
        }
        //最低提现金币
        CommonInfo one = commonInfoService.findOne(112);
        if (one != null && money < Double.parseDouble(one.getValue())) {
            return Result.error("输入金币不满足最低提现金币，请重新输入！");
        }
        //最高提现金币
        CommonInfo one2 = commonInfoService.findOne(153);
        if (one2 != null && money >= Double.parseDouble(one2.getValue())) {
            return Result.error(-100, "输入金币过大，不能大于" + one2.getValue() + "，请重新输入！");
        }
        //手续费
        CommonInfo one1 = commonInfoService.findOne(152);
        double mul = AmountCalUtils.mul(money, Double.parseDouble(one1.getValue()));
        if (mul < 0.01) {
            mul = 0.01;
        }
//        UserMoney userMoney=userMoneyService.selectUserMoneyByUserId(userId);
        InviteMoney inviteMoney = inviteMoneyService.selectInviteMoneyByUserId(userId);
        UserEntity userEntity = userService.selectUserById(userId);
        // 提现判断金币是否足够  金币=提现金币+手续费
        Double moneySum = AmountCalUtils.add(new BigDecimal(money), new BigDecimal(mul)).doubleValue();
        // 用户金币足够
        if (inviteMoney.getMoney() >= moneySum) {
            //扣除可提现金币
            inviteMoneyService.updateInviteMoneyCashOut(2, moneySum, userId);
            //增加金币操作记录
            UserMoneyDetails userMoneyDetails = new UserMoneyDetails();
            userMoneyDetails.setUserId(userId);
            userMoneyDetails.setTitle("提现：" + money);
            userMoneyDetails.setContent("支付宝提现：" + money + "，手续费：" + mul + ",总计：" + moneySum);
            userMoneyDetails.setType(2);
            // ✅
            userMoneyDetails.setClassify(4);
            userMoneyDetails.setMoney(new BigDecimal(moneySum));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            userMoneyDetails.setCreateTime(sdf.format(new Date()));
            userMoneyDetails.setMoneyType(1);
            userMoneyDetailsService.save(userMoneyDetails);
            CashOut cashOut = new CashOut();
            cashOut.setState(0);
            cashOut.setZhifubao(userEntity.getZhiFuBao());
            cashOut.setZhifubaoName(userEntity.getZhiFuBaoName());
            cashOut.setMoney(money.toString());
            cashOut.setCreateAt(sdf.format(new Date()));
            cashOut.setUserId(userEntity.getUserId());
            cashOut.setRate(mul);
            cashOut.setOrderNumber(String.valueOf(System.currentTimeMillis()));
            cashOut.setUserType(1);
            baseMapper.insert(cashOut);
//            inviteMoneyDao.updateInviteMoneyCashOut(1,money,userId);
            return Result.success("提现成功，将在三个工作日内到账，请耐心等待！");
        } else {
            return Result.error("金币不足，请输入正确的提现金币！");
        }
    }

    @Override
    @Transactional
    public Result sysCashMoney(Long userId, Double money) {
        if (money == null || money <= 0.00) {
            return Result.error("请不要输入小于0的数字,请输入正确的提现金币！");
        }
        //最低提现金币
        CommonInfo one = commonInfoService.findOne(112);
        if (one != null && money < Double.parseDouble(one.getValue())) {
            return Result.error("输入金币不满足最低提现金币，请重新输入！");
        }
        //最高提现金币
        CommonInfo one2 = commonInfoService.findOne(153);
        if (one2 != null && money >= Double.parseDouble(one2.getValue())) {
            return Result.error(-100, "输入金币过大，不能大于" + one2.getValue() + "，请重新输入！");
        }
        //手续费
        CommonInfo one1 = commonInfoService.findOne(152);
        double mul = AmountCalUtils.mul(money, Double.parseDouble(one1.getValue()));
        if (mul < 0.01) {
            mul = 0.01;
        }
        UserMoney userMoney = userMoneyService.selectSysUserMoneyByUserId(userId);

        SysUserEntity sysUserEntity = sysUserService.getById(userId);
        //提现判断金币是否足够   金币=提现金币+手续费
        double moneySum = AmountCalUtils.add(new BigDecimal(money), new BigDecimal(mul)).doubleValue();
        // 用户金币足够
        if (userMoney.getMoney().doubleValue() >= moneySum) {
            //扣除可提现金币
            userMoneyService.updateSysMoney(2, userId, moneySum);
            //增加金币操作记录
            UserMoneyDetails userMoneyDetails = new UserMoneyDetails();
            userMoneyDetails.setSysUserId(userId);
            userMoneyDetails.setTitle("提现：" + money);
            userMoneyDetails.setContent("提现：" + money + "，手续费：" + mul + ",总计：" + moneySum);
            userMoneyDetails.setType(2);
            // ✅
            userMoneyDetails.setClassify(4);
            userMoneyDetails.setMoney(new BigDecimal(moneySum));
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            userMoneyDetails.setCreateTime(sdf.format(new Date()));
            userMoneyDetails.setMoneyType(1);
            userMoneyDetailsService.save(userMoneyDetails);
            CashOut cashOut = new CashOut();
            cashOut.setState(0);
            cashOut.setZhifubao(sysUserEntity.getZhiFuBao());
            cashOut.setZhifubaoName(sysUserEntity.getZhiFuBaoName());
            cashOut.setMoney(money.toString());
            cashOut.setCreateAt(sdf.format(new Date()));
            cashOut.setUserId(sysUserEntity.getUserId());
            cashOut.setRate(mul);
            cashOut.setOrderNumber(String.valueOf(System.currentTimeMillis()));
            cashOut.setSysUserId(userId);
            cashOut.setUserType(2);
            baseMapper.insert(cashOut);
//            inviteMoneyDao.updateInviteMoneyCashOut(1,money,userId);
            return Result.success("提现成功，将在三个工作日内到账，请耐心等待！");
        } else {
            return Result.error("金币不足，请输入正确的提现金币！");
        }
    }


    @Override
    @Transactional
    public Result withdraw(Long userId, Double money, String msg, boolean isSys) {
        if (money == null || money <= 0.00) {
            return Result.error("请不要输入小于0的数字,请输入正确的提现金额！");
        }

        String alipayAccount;
        String alipayName;

        if (isSys) {
            SysUserEntity sysUserEntity = sysUserService.getById(userId);
            Msg msg1 = msgDao.findByPhoneAndCode(sysUserEntity.getMobile(), msg);
            if (msg1 == null) {
                return Result.error("验证码不正确！");
            }
            if (StringUtils.isBlank(sysUserEntity.getZhiFuBao()) || StringUtils.isBlank(sysUserEntity.getZhiFuBaoName())) {
                return Result.error(9999, "请先绑定支付宝账号！");
            }
            alipayAccount = sysUserEntity.getZhiFuBao();
            alipayName = sysUserEntity.getZhiFuBaoName();
        } else {
            UserEntity userInfo = userService.queryByUserId(userId);
            if (userInfo.getStatus().equals(0)) {
                return Result.error(9999, "账号不存在！");
            }
            if (StringUtils.isBlank(userInfo.getZhiFuBao()) || StringUtils.isBlank(userInfo.getZhiFuBaoName())) {
                return Result.error(9999, "请先绑定支付宝账号！");
            }

            UserInfo userDetailInfo = userInfoService.getByUserId(userId);
            if (StrUtil.isBlank(userDetailInfo.getCertName())) {
                return Result.error(9991, "请先实名认证！");
            }

            if (!userInfo.getZhiFuBaoName().equals(userDetailInfo.getCertName())) {
                return Result.error(500, "支付宝和实名姓名不太无法提现！");
            }
            alipayAccount = userInfo.getZhiFuBao();
            alipayName = userInfo.getZhiFuBaoName();
        }

        // 最低提现金额
        CommonInfo one = commonInfoService.findOne(112);
        if (one != null && money < Double.parseDouble(one.getValue())) {
            return Result.error("不满足最低提现金额，请重新输入！");
        }

        CashOut cashOut = new CashOut();
        cashOut.setIsOut(false);
        cashOut.setMoney(money.toString());
        if (isSys) {
            cashOut.setSysUserId(userId);
        } else {
            cashOut.setUserId(userId);
        }
        cashOut.setZhifubao(alipayAccount);
        cashOut.setZhifubaoName(alipayName);

        cashOut.setState(0);
        cashOut.setRate(0.00);
        cashOut.setUserType(1);
        cashOut.setCreateAt(DateUtil.now());
        cashOut.setWithdrawType(WithdrawTypeEnum.MANUAL.getValue());

        String outOrderNo = AliPayOrderUtil.createOrderId();
        cashOut.setOrderNumber(outOrderNo);
        UserMoneyDetails userMoneyDetails = new UserMoneyDetails();
        userMoneyDetails.setUserId(userId);
        userMoneyDetails.setTitle("[提现]");
        userMoneyDetails.setContent("提现：" + money + "元");
        userMoneyDetails.setType(2);
        userMoneyDetails.setState(2);
        // ✅
        userMoneyDetails.setClassify(4);
        userMoneyDetails.setMoney(new BigDecimal(money));
        userMoneyDetails.setCreateTime(DateUtil.now());
        userMoneyDetails.setMoneyType(1);
        UserMoney userMoney;
        if (isSys) {
            userMoney = userMoneyService.selectSysUserMoneyByUserId(userId);
        } else {
            userMoney = userMoneyService.selectUserMoneyByUserId(userId);
        }
        //提现判断余额是否足够
        if (userMoney.getAmount().doubleValue() < money) {
            return Result.success("可提现余额不足！");
        }

        if (wuyouPay.checkCanCash(userId, WithdrawTypeEnum.MANUAL, new BigDecimal(money.toString()))) {
            cashOut.setStatus(4);
            BaseResp baseResp = wuyouPay.extractOrder(outOrderNo, cashOut.getMoney(), cashOut.getZhifubao(), cashOut.getZhifubaoName());
            if (baseResp.getStatus() != null && (baseResp.getStatus().equals(2) || baseResp.getStatus().equals(10000))) {
                userMoneyDetails.setContent("成功提现：" + money);
                cashOut.setState(1);
            }

            if (baseResp.getErrorMsg() != null) {
                return Result.error(baseResp.getErrorMsg());
            }
        } else {
            userMoneyDetails.setContent("成功提现：" + money);
            cashOut.setState(3);
        }

        userMoneyDetailsService.save(userMoneyDetails);
        baseMapper.insert(cashOut);
        if (isSys) {
            userMoneyService.updateSysAmount(2, userId, money);
        } else {
            userMoneyService.updateAmount(2, userId, money);
        }
        return Result.success("提现成功，将在三个工作日内到账，请耐心等待！");
    }

    @Override
    public PageUtils auditPage(Map<String, Object> params) {
        PageHelper.startPage(ParamPageUtils.getPageNum(params), ParamPageUtils.getPageSize(params));
        CashOut cashOut = BeanUtil.toBean(params, CashOut.class);
        List<CashOut> page = baseMapper.selectCashOutPage(cashOut, false);
        PageInfo<CashOut> pageInfo = new PageInfo<>(page);
        return PageUtils.page(pageInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void audit(CashOut cashOut) {
        long id = cashOut.getId();
        Integer isAgree = cashOut.getIsAgree();
        if (isAgree == null) {
            throw new SqxException("请选择同意或者拒绝！");
        }
        if (isAgree == 0 && StrUtil.isBlank(cashOut.getRefund())) {
            throw new SqxException("请输入拒绝原因！");
        }
        CashOut entity = baseMapper.selectById(id);
        if (entity == null) {
            throw new SqxException("提现申请不存在！");
        }
        if (entity.getState() != 3) {
            throw new SqxException("提现申请状态无效，请刷新后重试！");
        }
        if (isAgree == 1) {
            entity.setState(0);
        } else {
            entity.setState(2);
            entity.setRefund(cashOut.getRefund());
        }

        boolean isSysUser = entity.getSysUserId() != null;

        if (isSysUser) {
            SysUserEntity sysUserEntity = sysUserService.getById(entity.getSysUserId());
            if (sysUserEntity == null) {
                throw new SqxException("提现代理信息不存在！");
            }
        } else {
            UserEntity userEntity = userService.selectUserById(entity.getUserId());
            if (userEntity == null) {
                throw new SqxException("提现用户信息不存在！");
            }
        }

        if (isAgree == 0) {
            backCashAmount(entity);
            return;
        }
        entity.setState(4);
        baseMapper.updateById(entity);
        if (StrUtil.isBlank(entity.getOrderNumber())) {
            String outOrderNo = AliPayOrderUtil.createOrderId();
            entity.setOrderNumber(outOrderNo);
        }
        // 执行提现操作
        BaseResp baseResp = wuyouPay.extractOrderForAudit(entity.getOrderNumber(), entity.getMoney(), entity.getZhifubao(), entity.getZhifubaoName());
        if (baseResp.getStatus() != null && (baseResp.getStatus().equals(2) || baseResp.getStatus().equals(10000))) {
            entity.setState(1);
        } else if (StringUtils.isNotBlank(baseResp.getErrorMsg())) {
            entity.setState(2);
            if (baseResp.getErrorMsg().contains("收款人账户号出款属性不匹配")) {
                entity.setRefund("提现失败,请检查支付宝账号与收款人姓名后,重试。");
            } else {
                entity.setRefund(baseResp.getErrorMsg());
            }
            backCashAmount(entity);
        } else if (StringUtils.isNotBlank(baseResp.getMsg())) {
            entity.setState(2);
            entity.setRefund("提现失败,请检查支付宝账号与收款人姓名后,重试。");
            backCashAmount(entity);
        }
        baseMapper.updateById(entity);
    }

    private void backCashAmount(CashOut entity) {
        baseMapper.updateById(entity);
        UserMoneyDetails userMoneyDetails = new UserMoneyDetails(
                entity.getUserId(), entity.getSysUserId(), null, "[提现退款]", 4, 1, 2,
                new BigDecimal(entity.getMoney()), "提现失败，自动退款" + entity.getMoney() + "元", 1, entity.getId());
        userMoneyDetailsService.save(userMoneyDetails);
        //归还余额 钱
        userMoneyService.updateAmount(1, entity.getUserId(), Convert.toDouble(entity.getMoney()));
    }

    /**
     * 批量审核
     *
     * @param userId  用户id
     * @param isAgree 1-同意 0-拒绝
     * @param refund  拒绝愿意
     */

    @Override
    public void batchAudit(Long userId, Integer isAgree, String refund) {
        if (userId == null) {
            throw new SqxException("用户id不能为空！");
        }
        if (isAgree == null) {
            throw new SqxException("请选择同意或者拒绝！");
        }
        if (isAgree == 0 && StrUtil.isBlank(refund)) {
            throw new SqxException("请输入拒绝原因！");
        }
        List<CashOut> list = baseMapper.selectList(Wrappers.<CashOut>lambdaQuery().eq(CashOut::getUserId, userId).eq(CashOut::getState, 3).orderByAsc(CashOut::getCreateAt).orderByAsc(CashOut::getId));
        for (CashOut cashOut : list) {
            cashOut.setIsAgree(isAgree);
            cashOut.setRefund(refund);
            queueAudit(cashOut);
        }
    }

    /**
     * 排队提现审核
     *
     * @param cashOut
     */

    public synchronized void queueAudit(CashOut cashOut) {
        audit(cashOut);
    }

    @Override
    public Map<String, Object> alipayTransferSummaryQuery(String alipayAccountName) {
        if (StrUtil.isBlank(alipayAccountName)) {
            throw new SqxException("支付宝账号不能为空！");
        }
        BigDecimal sum = BigDecimal.ZERO;
        int count = 0;
        Map<String, Object> data = new HashMap<>(8);
        data.put("alipayAccountName", alipayAccountName);
        data.put("sum", sum);
        data.put("count", count);
        List<Map<String, Object>> list = new ArrayList<>();
        data.put("list", list);
        List<UserEntity> userList = userDao.selectList(Wrappers.<UserEntity>lambdaQuery().eq(UserEntity::getZhiFuBaoName, alipayAccountName));
        if (CollUtil.isEmpty(userList)) {
            return data;
        }

        for (UserEntity entity : userList) {
            Map<String, Object> record = new HashMap<>();
            record.put("userId", entity.getUserId());
            record.put("userName", entity.getUserName());
            record.put("inviterCode", entity.getInviterCode());
            record.put("phone", entity.getPhone());
            record.put("zhiFuBaoName", entity.getZhiFuBaoName());
            record.put("zhiFuBao", entity.getZhiFuBao());
            // 累计提现金额
            BigDecimal subSum = baseMapper.selectSumMoney(entity.getUserId(), 1);
            record.put("subTotal", NumberUtil.null2Zero(subSum));
            // 累计提现次数
            Integer subCount = baseMapper.selectCount(Wrappers.<CashOut>lambdaQuery().eq(CashOut::getUserId, entity.getUserId()).eq(CashOut::getState, 1));
            record.put("subCount", subCount == null ? 0 : subCount);
            list.add(record);
            sum = NumberUtil.add(sum, NumberUtil.null2Zero(subSum));
            count = count + subCount;
        }
        data.put("sum", sum);
        data.put("count", count);
        data.put("list", list);
        return data;
    }

    @Override
    public Result batchCashOutOrder(Double maxMoney, Integer count) {
        if (maxMoney == null || maxMoney <= 0) {
            maxMoney = 20.00;
        }
        if (count == null || count <= 0) {
            count = 1000;
        }
        // 查询 待审核的用户 id 列表
        QueryWrapper<CashOut> userIdQuery = Wrappers.<CashOut>query().select("user_id").eq("state", 3).isNotNull("user_id").groupBy("user_id");
        List<CashOut> cashOutList = baseMapper.selectList(userIdQuery);
        if (CollUtil.isEmpty(cashOutList)) {
            return Result.error("没有待审核的提现申请！");
        }

        List<Long> userIdList = cashOutList.stream().map(CashOut::getUserId).collect(Collectors.toList());
        System.out.println("userIdList = " + userIdList);

        Double finalMaxMoney = maxMoney;
        Integer finalCount = count;
        ThreadUtil.execAsync(() -> batchSendCashMoney(userIdList, finalMaxMoney, finalCount, 30));

        return Result.success();
    }

    private void batchSendCashMoney(List<Long> userIds, Double maxMoney, Integer count, int len) {
        if (CollUtil.isEmpty(userIds)) {
            return;
        }

        List<List<Long>> partition = CollUtil.split(userIds, len);

        for (List<Long> userIdList : partition) {
            // 查询需要提现的用户已经提现的金额和笔数
            QueryWrapper<CashOut> sumQuery = new QueryWrapper<>();
            sumQuery.select("user_id", "sum(money) as money", "count(1) as total");
            sumQuery.in("user_id", userIdList);
            sumQuery.eq("state", 1);
            sumQuery.groupBy("user_id");
            List<Map<String, Object>> sumList = baseMapper.selectMaps(sumQuery);

            for (Map<String, Object> objectMap : sumList) {
                Double totalMoney = Convert.toDouble(objectMap.get("money"));
                Integer total = Convert.toInt(objectMap.get("total"));

                if (totalMoney >= maxMoney || total >= count) {
                    continue;
                }

                Long userId = Convert.toLong(objectMap.get("user_id"));

                try {
                    // 查询用户待审核的列表
                    BigDecimal cashTotal = BigDecimal.ZERO;
                    List<CashOut> cashOutList = baseMapper.selectList(Wrappers.<CashOut>lambdaQuery().eq(CashOut::getUserId, userId).eq(CashOut::getState, 3));
                    for (CashOut cashOut : cashOutList) {
                        cashOut.setIsAgree(1);
                        cashOut.setRefund("");
                        queueAudit(cashOut);
                        cashTotal = cashTotal.add(new BigDecimal(cashOut.getMoney()));
                    }

                    log.info("用户 {} 提现成功！ {}笔, 金额{}元", userId, cashOutList.size(), cashTotal);
                    TimeUnit.MILLISECONDS.sleep(500);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }
    }
}
