package com.ruoyi.ss.user.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.ServiceConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.core.domain.dto.BasicConfigDTO;
import com.ruoyi.common.core.domain.entity.User;
import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.core.redis.enums.RedisLockKey;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServiceUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.utils.verify.VerifyIdentityUtil;
import com.ruoyi.ss.changeBalance.domain.ChangeBalance;
import com.ruoyi.ss.changeBalance.domain.ChangeBalanceQuery;
import com.ruoyi.ss.changeBalance.service.IChangeBalanceService;
import com.ruoyi.ss.channelWithdraw.domain.ChannelWithdrawVO;
import com.ruoyi.ss.user.domain.UserQuery;
import com.ruoyi.ss.user.domain.UserVO;
import com.ruoyi.ss.user.mapper.UserMapper;
import com.ruoyi.ss.user.service.IUserService;
import com.ruoyi.ss.userWithdraw.domain.UserWithdraw;
import com.ruoyi.ss.withdraw.domain.Withdraw;
import com.ruoyi.ss.withdraw.domain.bo.WithdrawBO;
import com.ruoyi.ss.withdraw.domain.dto.MchWithdrawDTO;
import com.ruoyi.ss.withdraw.domain.dto.WithdrawApprovalDTO;
import com.ruoyi.ss.withdraw.mapper.WithdrawMapper;
import com.ruoyi.ss.withdraw.service.IWithdrawService;
import com.ruoyi.system.domain.SysUserRole;
import com.ruoyi.system.domain.enums.config.ConfigKey;
import com.ruoyi.system.domain.query.AuthenticationQuery;
import com.ruoyi.system.mapper.SysUserPostMapper;
import com.ruoyi.system.mapper.SysUserRoleMapper;
import com.ruoyi.system.service.ISysConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.validation.Validator;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static com.ruoyi.common.constant.ServiceConstants.USER_TYPE_MERCHANT;
import static com.ruoyi.common.constant.ServiceConstants.WITHDRAW_TYPE_ONLINE;
import static com.ruoyi.common.utils.SecurityUtils.getUserId;

/**
 * 用户 业务层处理
 *
 * @author ruoyi
 */
@Slf4j
@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    protected Validator validator;

    @Autowired
    private IWithdrawService rlWithdrawService;

    @Autowired
    private IChangeBalanceService rlChangeBalanceService;

    @Resource
    private SysUserRoleMapper userRoleMapper;

    @Resource
    private SysUserPostMapper userPostMapper;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private IChangeBalanceService changeBalanceService;

    @Value("${e.verifyUrl}")
    private String verifyUrl;

    @Value("${e.appcode}")
    private String appcode;

    @Autowired
    private RedisLock redisLock;

    @Autowired
    private ScheduledExecutorService scheduledExecutorService;

    @Autowired
    private ISysConfigService sysConfigService;

    @Autowired
    private IWithdrawService withdrawService;
    /**
     * 根据条件分页查询用户列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(userAlias = "u")
    public List<UserVO> selectUserList(UserQuery user)
    {
        /** 获取设备绑定数量*/
        return userMapper.selectUserList(user);
    }

    /**
     * 获取app用户列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    public List<UserVO> selectAppUserList(UserQuery user) {
        return userMapper.selectAppUserList(user);
    }

    /**
     * 根据条件分页查询已分配用户角色列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(userAlias = "u")
    public List<User> selectAllocatedList(User user)
    {
        return userMapper.selectAllocatedList(user);
    }

    /**
     * 获取分账用户列表
     *
     * @param merchantId 商户id
     * @return 用户信息集合信息
     */
    @Override
    public List<User> selectDividendUserList(Long merchantId) {
        return userMapper.selectDividendUserList(merchantId);
    }

    /**
     * 根据条件分页查询未分配用户角色列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
//    @DataScope(deptAlias = "d", userAlias = "u")
    public List<User> selectUnallocatedList(User user)
    {
        return userMapper.selectUnallocatedList(user);
    }

    /**
     * 通过用户名查询用户
     *
     * @param userName 用户名
     * @return 用户对象信息
     */
    @Override
    public UserVO selectUserByUserName(String userName)
    {
        return userMapper.selectUserByUserName(userName);
    }

    /**
     * 通过手机号查询用户
     *
     * @param phone 手机号
     * @return 用户对象信息
     */
    @Override
    public UserVO selectUserByPhone(String phone)
    {
        return userMapper.selectUserByPhone(phone);
    }

    /**
     * 通过用户ID查询用户（带角色信息等）
     *
     * @param userId 用户ID
     * @return 用户对象信息
     */
    @Override
    public UserVO selectUserById(Long userId)
    {
        return userMapper.selectUserById(userId);
    }

    /**
     * 通过用户ID查询用户（带角色信息等）
     *
     * @param userId 用户ID
     * @return 用户对象信息
     */
    @Override
    public UserVO selectAppUserById(Long userId)
    {
        return userMapper.selectAppUserById(userId);
    }

    /**
     * 获取用户可提现金额
     */
    @Override
    public BigDecimal getWithdrawAbleAmount(UserVO user) {
        BigDecimal todayOrderAmount = selectTodayOrderAmount(user.getUserId()); // 今日订单金额
//        BigDecimal withdrawingAmount = withdrawService.selectWithdrawingAmount(user.getUserId()); // 正在提现中金额

        // 计算可提现余额
        BigDecimal withdrawAbleAmount = user.getBalance().subtract(todayOrderAmount);

        // 判断可提现金额是否小于0，如果是，则返回0
        if (withdrawAbleAmount.compareTo(BigDecimal.ZERO) < 0) {
            return BigDecimal.ZERO;
        } else {
            return withdrawAbleAmount;
        }
    }

    /**
     *  更新成为商户
     */
    @Override
    public int becomeMch(Long userId) {
        User user = new User();
        user.setUserId(userId);
        user.setUserType(USER_TYPE_MERCHANT);
        return userMapper.updateUser(user);
    }

    /**
     *  根据店铺id获取保洁人员
     */
    @Override
    public List<UserVO> getClearUserByStoreId(Long storeId) {
        return userMapper.getClearUserByStoreId(storeId);
    }

    /**
     *  保存基础配置
     */
    @Override
    public int basicConfig(BasicConfigDTO dto) {
        User user = new User();
        user.setUserId(SecurityUtils.getUserId());
        user.setCleanDuration(dto.getCleanDuration());
        user.setCleanNotice(dto.getCleanNotice());
        user.setAgoCancel(dto.getAgoCancel());
        user.setPenalty(dto.getPenalty());
        user.setBeforeTime(dto.getBeforeTime());
        return userMapper.updateUser(user);
    }

    /**
     *  根据条件统计用户数量
     */
    @Override
    public int selectCount(UserQuery userQuery) {
        return userMapper.selectCount(userQuery);
    }

    @Override
    public BigDecimal selectAllBalance() {
        return userMapper.selectAllBalance();
    }

    /**
     * 通过用户ID查询账户
     *
     * @param userId 用户ID
     * @return 用户对象信息
     */
    @Override
    public UserVO myAccountInfoByUserId(Long userId)
    {
        UserVO users = userMapper.myAccountInfoByUserId(userId);
        /** 累计提现*/
        BigDecimal totalWithdrawAmount = rlWithdrawService.cumulativeWithdrawalAmount(userId);
        if(ObjectUtil.isNull(totalWithdrawAmount)){
            totalWithdrawAmount = BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        }
        users.setTotalWithdrawAmount(totalWithdrawAmount);
        /** 可提现金额   等于余额-今日订单金额 */
        BigDecimal withdrawableAmount = getWithdrawAbleAmount(users);
        users.setWithdrawalAmount(withdrawableAmount);
        /** 最后账变描述*/
        ChangeBalance changeBalance = changeBalanceService.lastChangeBalance(userId);
        // 根据类型获取描述
        if(ObjectUtil.isNotNull(changeBalance)){
            String desc= getDesc(changeBalance);
            users.setLastChangeBalanceDesc(desc);
        }
        return users;
    }

    @Override
    public BigDecimal selectTodayOrderAmount(Long userId){
        return userMapper.selectTodayOrderAmount(userId);
    }


    private String getDesc(ChangeBalance changeBalance) {
        StringBuilder desc = new StringBuilder();

        // 获取变动金额
        BigDecimal amount = changeBalance.getAmount();
        String amountStr = amount != null ? amount.toString() : "0.00";
        // 获取收支类型
        String type = changeBalance.getType();
        String typeDesc = "未知";
        if ("1".equals(type)) {
            typeDesc = "收入";
        } else if ("2".equals(type)) {
            typeDesc = "支出";
        }
        // 获取业务类型
        String busType = changeBalance.getBusType();
        String busDesc = "未知";
        switch (busType) {
            case "1":
                busDesc = "订单";
                break;
            case "2":
                busDesc = "续单订单";
                break;
            case "4":
                busDesc = "订单退款";
                break;
            case "5":
                busDesc = "提现";
                break;
            case "6":
                busDesc = "提现失败";
                break;
            case "8":
                busDesc = "短信扣费";
                break;
            default:
                break;
        }
        // 拼接收支和业务类型
        desc.append(busDesc).append(typeDesc).append(amountStr).append("元");
        // 计算时间差
        Date createTime = changeBalance.getCreateTime();
        if (createTime != null) {
            long diffInMillis = new Date().getTime() - createTime.getTime();
            long diffInDays = TimeUnit.DAYS.convert(diffInMillis, TimeUnit.MILLISECONDS);
            desc.append("·").append(diffInDays).append("天前");
        } else {
            desc.append(" 时间未知");
        }
        return desc.toString();
    }


//    /**
//     * 校验用户名称是否唯一
//     *
//     * @param user 用户信息
//     * @return 结果
//     */
//    @Override
//    public boolean checkUserNameUnique(EUser user)
//    {
//        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
//        EUser info = EUserMapper.checkUserNameUnique(user.getUserName());
//        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
//        {
//            return UserConstants.NOT_UNIQUE;
//        }
//        return UserConstants.UNIQUE;
//    }
//
//    /**
//     * 校验手机号码是否唯一
//     *
//     * @param user 用户信息
//     * @return
//     */
//    @Override
//    public boolean checkPhoneUnique(EUser user)
//    {
//        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
//        EUser info = EUserMapper.checkPhoneUnique(user.getPhonenumber());
//        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
//        {
//            return UserConstants.NOT_UNIQUE;
//        }
//        return UserConstants.UNIQUE;
//    }
//
//    /**
//     * 校验email是否唯一
//     *
//     * @param user 用户信息
//     * @return
//     */
//    @Override
//    public boolean checkEmailUnique(EUser user)
//    {
//        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
//        EUser info = EUserMapper.checkEmailUnique(user.getEmail());
//        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
//        {
//            return UserConstants.NOT_UNIQUE;
//        }
//        return UserConstants.UNIQUE;
//    }
//
//
    /**
     * 新增保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional
    public int insertUser(User user)
    {
        return userMapper.insertUser(user);
    }
//
//    /**
//     * 注册用户信息
//     *
//     * @param user 用户信息
//     * @return 结果
//     */
//    @Override
//    public boolean registerUser(EUser user)
//    {
//        return EUserMapper.insertUser(user) > 0;
//    }
//
    /**
     * 修改保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional
    public int updateUser(User user)
    {
        // 删除用户与角色关联
        if (StringUtils.isNotEmpty(user.getRoleIds())){
            userRoleMapper.deleteUserRoleByUserId(user.getUserId());
            // 新增用户与角色管理
            insertUserRole(user.getUserId(),user.getRoleIds());
        }
        return userMapper.updateUser(user);
    }

    /**
     * 根据电话修改用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int updateUserByPhone(User user)
    {
        return userMapper.updateUserByPhone(user);
    }




    /**
     * 修改用户状态
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int updateUserStatus(User user)
    {
        return userMapper.updateUser(user);
    }

    /**
     * 修改用户基本信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public int updateUserProfile(User user)
    {
        return userMapper.updateUser(user);
    }
//
//    /**
//     * 修改用户头像
//     *
//     * @param userName 用户名
//     * @param avatar 头像地址
//     * @return 结果
//     */
//    @Override
//    public boolean updateUserAvatar(String userName, String avatar)
//    {
//        return EUserMapper.updateUserAvatar(userName, avatar) > 0;
//    }
//
//    /**
//     * 重置用户密码
//     *
//     * @param user 用户信息
//     * @return 结果
//     */
//    @Override
//    public int resetPwd(EUser user)
//    {
//        return EUserMapper.updateUser(user);
//    }
//
//    /**
//     * 重置用户密码
//     *
//     * @param userName 用户名
//     * @param password 密码
//     * @return 结果
//     */
//    @Override
//    public int resetUserPwd(String userName, String password)
//    {
//        return EUserMapper.resetUserPwd(userName, password);
//    }
//
//
//    /**
//     * 通过用户ID删除用户
//     *
//     * @param userId 用户ID
//     * @return 结果
//     */
//    @Override
//    @Transactional
//    public int deleteUserById(Long userId)
//    {
//        return EUserMapper.deleteUserById(userId);
//    }
//
//    /**
//     * 批量删除用户信息
//     *
//     * @param userIds 需要删除的用户ID
//     * @return 结果
//     */
//    @Override
//    @Transactional
//    public int deleteUserByIds(Long[] userIds)
//    {
//        return EUserMapper.deleteUserByIds(userIds);
//    }
//
//    /**
//     * 导入用户数据
//     *
//     * @param userList 用户数据列表
//     * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
//     * @param operName 操作用户
//     * @return 结果
//     */
//    @Override
//    public String importUser(List<EUser> userList, Boolean isUpdateSupport, String operName)
//    {
//        if (StringUtils.isNull(userList) || userList.size() == 0)
//        {
//            throw new ServiceException("导入用户数据不能为空！");
//        }
//        int successNum = 0;
//        int failureNum = 0;
//        StringBuilder successMsg = new StringBuilder();
//        StringBuilder failureMsg = new StringBuilder();
//        String password = configService.selectConfigByKey("sys.user.initPassword");
//        for (EUser user : userList)
//        {
//            try
//            {
//                // 验证是否存在这个用户
//                EUser u = EUserMapper.selectUserByUserName(user.getUserName());
//                if (StringUtils.isNull(u))
//                {
//                    BeanValidators.validateWithException(validator, user);
//                    user.setPassword(SecurityUtils.encryptPassword(password));
//                    user.setCreateBy(operName);
//                    EUserMapper.insertUser(user);
//                    successNum++;
//                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
//                }
//                else if (isUpdateSupport)
//                {
//                    BeanValidators.validateWithException(validator, user);
//                    user.setUserId(u.getUserId());
//                    user.setUpdateBy(operName);
//                    EUserMapper.updateUser(user);
//                    successNum++;
//                    successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
//                }
//                else
//                {
//                    failureNum++;
//                    failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
//                }
//            }
//            catch (Exception e)
//            {
//                failureNum++;
//                String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败：";
//                failureMsg.append(msg + e.getMessage());
//                log.error(msg, e);
//            }
//        }
//        if (failureNum > 0)
//        {
//            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
//            throw new ServiceException(failureMsg.toString());
//        }
//        else
//        {
//            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
//        }
//        return successMsg.toString();
//    }
//
//    /**
//     * 通过手机号查询用户
//     *
//     * @param phone 手机号
//     * @return 用户对象信息
//     */
//    @Override
//    public EUser selectUserByPhone(String phone) {
//        return EUserMapper.selectUserByPhone(phone);
//    }

    /**
     * 通过用户手机号和appid查询用户
     *
     * @param phone 手机号
     * @return 用户对象信息
     */
    @Override
    public User selectUserByPhoneAndAppId(String phone) {
        return userMapper.selectUserByPhoneAndAppId(phone);
    }

    /**
     * 通过openid查询用户
     *
     * @param openid 手机号
     * @return 用户对象信息
     */
    @Override
    public UserVO selectUserByWxopenid(String openid) {
        return userMapper.selectUserByWxopenid(openid);
    }

//    /**
//     * 检测用户是否有充值过押金
//     * @param userId
//     */
//    @Override
//    public Boolean checkIsDeposit(Long userId) {
//        EUser eUser = EUserMapper.selectUserById(userId);
//        BigDecimal balance = asUser.getBalance();
////        EtOperatingArea area = etOperatingAreaService.selectEtOperatingAreaByAreaId(asUser.getAreaId());
////        BigDecimal deposit = new BigDecimal(area.getDeposit());
//        if(ObjectUtil.isNull(balance)){
//            log.info("用户【{}】余额为空",userId);
//            return false;
//        }
//        if(balance.compareTo(BigDecimal.ZERO)==0){//余额为0
//            log.info("用户【{}】余额为0",userId);
//            return false;
//        }
//        // 判断是否有押金充值记录
//        EtOrder etOrder = new EtOrder();
//        etOrder.setType(ServiceConstants.ORDER_TYPE_DEPOSIT);
//        etOrder.setUserId(userId);
//        etOrder.setPaid("1");
//        if(etOrderMapper.selectEtOrderList(etOrder).size()<1){//没有充值押金记录
//            log.info("用户【{}】没有充值押金记录",userId);
//            return false;
//        }
//        return true;
//    }

//    /**
//     * 新增用户
//     */
//    @Override
//    public String getNewUser(String powerStart, String powerEnd,String areaId) {
//        if(StringUtils.isNotEmpty(powerStart) && StringUtils.isNotEmpty(powerEnd)){
//            return EUserMapper.getNewUser(powerStart,powerEnd,areaId);
//        }
//        return null;
//    }
//
//    /**
//     * 总用户
//     */
//    @Override
//    public String getTotalUser(String areaId) {
//        return EUserMapper.getTotalUser(areaId);
//    }
//
//    /**
//     * 租赁用户
//     */
//    @Override
//    public String getLeaseUser(String powerStart, String powerEnd,String areaId) {
//        if(StringUtils.isNotEmpty(powerStart) && StringUtils.isNotEmpty(powerEnd)){
//            return EUserMapper.getLeaseUser(powerStart,powerEnd,areaId);
//        }
//        return null;
//    }
//
//    /**
//     * 绑定系统用户
//     */
//    @Transactional
//    @Override
//    public int bandSystemUser(EUser user) {
//        // 删除用户缓存
//        Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.APP_LOGIN_TOKEN_KEY + "*");
//        redisCache.deleteObject(keys);
//        return EUserMapper.updateUser(user);
//    }
//
    /**
     * 实名认证
     */
    @Override
    public Object authentication(AuthenticationQuery authenticationQuery) {
        String idCard = authenticationQuery.getIdCard();
        String realName = authenticationQuery.getRealName();
        return VerifyIdentityUtil.verifyIdentity(verifyUrl, appcode, idCard, realName);
    }
//
//    /**
//     * 检测是否实名认证
//     */
//    @Override
//    public boolean checkIsAuthentication(Long userId) {
//        if(EUserMapper.selectUserById(userId).getIsAuthentication().equals("1")){
//            return true;
//        }
//        return false;
//    }
//
//    /**
//     * 根据手机号快速搜索用户列表
//     */
//    @Override
//    public List<LabelVo> fastSearch(String phonenumber) {
//        /** 获取设备绑定数量*/
//        List<LabelVo> users = EUserMapper.fastSearch(phonenumber);
//        return users;
//    }

    /**
     * 更新用户密码
     */
    @Override
    public int updateUserPwd(Long userId, String newPassword) {
        return userMapper.updateUserPwd(userId, newPassword);
    }

    @Override
    public void checkUserDataScope(Long userId) {
        if (!User.isAdmin(getUserId()))
        {
            UserQuery user = new UserQuery();
            user.setUserId(userId);
            List<UserVO> users = SpringUtils.getAopProxy(this).selectUserList(user);
            if (StringUtils.isEmpty(users))
            {
                throw new ServiceException("没有权限访问用户数据！");
            }
        }
    }

    @Override
    public String importUser(List<User> userList, Boolean isUpdateSupport, String operName) {
        return null;
    }

    @Override
    public boolean checkUserNameUnique(User user) {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        User info = userMapper.checkUserNameUnique(user.getUserName());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public boolean registerUser(User user) {
        return userMapper.insertUser(user) > 0;
    }

    @Override
    public boolean checkPhoneUnique(User user) {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        User info = userMapper.checkPhoneUnique(user.getPhonenumber());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public boolean checkEmailUnique(User user) {
        Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
        User info = userMapper.checkEmailUnique(user.getEmail());
        if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
        {
            return UserConstants.NOT_UNIQUE;
        }
        return UserConstants.UNIQUE;
    }

    @Override
    public String selectUserRoleGroup(String userName) {
        return null;
    }

    @Override
    public String selectUserPostGroup(String userName) {
        return null;
    }

    @Override
    public boolean updateUserAvatar(String userName, String avatar) {
        return false;
    }

    @Override
    public int resetUserPwd(String userName, String password) {
        return userMapper.resetUserPwd(userName, password);
    }

    @Override
    public void checkUserAllowed(User user) {
        if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin())
        {
            throw new ServiceException("不允许操作超级管理员用户");
        }
    }

    @Override
    public int deleteUserByIds(Long[] userIds) {
        for (Long userId : userIds)
        {
            checkUserAllowed(new User(userId));
            checkUserDataScope(userId);
        }
        // 删除用户与角色关联
        userRoleMapper.deleteUserRole(userIds);
        // 删除用户与岗位关联
        userPostMapper.deleteUserPost(userIds);
        return userMapper.deleteUserByIds(userIds);
    }

    @Override
    public int resetPwd(User user) {
        return userMapper.updateUser(user);
    }

    /**
     * 用户授权角色
     *
     * @param userId 用户ID
     * @param roleIds 角色组
     */
    @Override
    @Transactional
    public void insertUserAuth(Long userId, Long[] roleIds)
    {
        userRoleMapper.deleteUserRoleByUserId(userId);
        insertUserRole(userId, roleIds);
    }

    /**
     * 获取用户余额
     *
     * @param userId 用户id
     * @return 结果
     */
    @Override
    public BigDecimal selectUserBalanceById(Long userId) {
        return userMapper.selectUserBalanceById(userId);
    }

    /**
     * 账变记录
     */
    @Override
    public List<ChangeBalance> myChangeBalanceList(ChangeBalanceQuery query, Long userId) {
        /** 账变明细*/
        return rlChangeBalanceService.selectRlChangeBalanceListByUserId(query,userId);
    }

    /**
     * 商户提现
     * 1. 获取当前用户
     * 2. 根据用户提现渠道判断是否是自动提现
     *      2.1 发起自动提现
     *              新建转账批次
     *              新建转账明细
     *              提交转账
     *
     *              定时查询  提现状态
     *      2.2 发起人工审核提现
     *
     * 2. 记录提现记录
     * 3. 计算服务费
     * 3. 扣余额,记录账变
     * 4. 发起提现（如果是自动api提现）
     */
    @Override
    public int mchWithdraw(WithdrawBO bo) {
        String withdrawNo = IdUtils.getOrderNo("tx");
        Long userId = getUserId();
        MchWithdrawDTO dto = bo.getDto();
        UserWithdraw userWithdraw = bo.getUserWithdraw();
        ChannelWithdrawVO channelWithdraw = bo.getChannelWithdraw();
        UserVO user = bo.getUser();
        // 加锁
        ServiceUtil.assertion(!redisLock.lock(RedisLockKey.ADD_WITHDRAW, userId), "请勿频繁操作提现");
        try {
            Boolean execute = transactionTemplate.execute(e -> {
                /** 2. 记录提现记录*/
                withdrawalRecord(dto.getAmount(),userWithdraw,channelWithdraw, withdrawNo, user);
                /** 3. 扣余额,记录账变  */
                int i = changeBalanceService.generateChangeBalance(withdrawNo, null, ServiceConstants.FLOW_TYPE_DISBURSE,
                        ServiceConstants.WITHDRAWAL, dto.getAmount(), user.getUserId(), user.getUserName(), user.getPhonenumber(),user.getUserType());
                if(i<=0)throw new ServiceException("【提现】记录账变失败");
                // 发短信通知转账人
//            asynchronousMsg(user.getUserName());
                return Boolean.TRUE;
            });
            if(Boolean.FALSE.equals(execute))throw new ServiceException("【提现】失败");

            // 异步操作：当提现申请金额免审核且为线上打款时，直接通过
            try {
                String noverifyAmountStr = sysConfigService.selectConfigByKey(ConfigKey.NOVERIFY_WITHDRAW_SINGLE.getKey());
                if (StringUtils.hasText(noverifyAmountStr)) {
                    BigDecimal noverifyAmount = new BigDecimal(noverifyAmountStr);
                    if(userWithdraw.getType().equals(WITHDRAW_TYPE_ONLINE) && userWithdraw.getIsAuto() && dto.getAmount().compareTo(noverifyAmount) <= 0){
                        scheduledExecutorService.schedule(() -> {
                            WithdrawApprovalDTO passDto = new WithdrawApprovalDTO();
                            passDto.setWithdrawNo(withdrawNo);
                            withdrawService.passWithdraw(passDto);
                        }, 0, TimeUnit.SECONDS);
                    }
                }
            } catch (Exception e) {
                log.error(e.getMessage());
                throw new ServiceException("【提现】异步操作失败");
            }
            return 1;
        } finally {
            redisLock.unlock(RedisLockKey.ADD_WITHDRAW, userId);
        }
    }

    /**
     * 更新用户余额
     */
    @Override
    public int changeBalance(BigDecimal changeAmount, Long userId) {
        return userMapper.changeBalance(changeAmount, userId);
    }

    /**
     *  根据运营商查商户列表
     */
    @Override
    public List<UserVO> getMerchantList(UserQuery userQuery) {
        return userMapper.selectUserList(userQuery);
    }

    private void withdrawalRecord(BigDecimal amount, UserWithdraw userWithdraw, ChannelWithdrawVO channelWithdraw, String withdrawNo, UserVO user) {
        Withdraw withdraw = new Withdraw();
        withdraw.setWithdrawNo(withdrawNo);
        withdraw.setCreateTime(DateUtils.getNowDate());
        withdraw.setAmount(amount);
        withdraw.setStatus(ServiceConstants.WITHDRAW_STATUS_APPLY);
        withdraw.setOwnerId(user.getUserId());
        withdraw.setOwnerName(user.getUserName());
        withdraw.setOwnerPhone(user.getPhonenumber());
        withdraw.setOwnerType(user.getUserType());
        withdraw.setWxOpenid(user.getWxopenid());
        withdraw.setAfterBalance(user.getBalance().subtract(amount));
        withdraw.setCost(getCost(amount, channelWithdraw));
        withdraw.setWithdrawChannelId(channelWithdraw.getChannelId());
        withdraw.setUserWithdrawChannelId(userWithdraw.getUserChannelId());
        BigDecimal serveCharge = getHandlingCharge(amount, userWithdraw);
        withdraw.setHandlingCharge(serveCharge);
        withdraw.setHandlingChargeType(userWithdraw.getHandlingChargeType());
        BigDecimal subtract = amount.subtract(serveCharge);
        ServiceUtil.assertion(subtract.compareTo(BigDecimal.ZERO) < 0, "提现金额不能小于手续费");
        withdraw.setReceivedAmount(subtract);
        withdraw.setType(userWithdraw.getType());
        withdraw.setIsAuto(userWithdraw.getIsAuto());
        withdraw.setWithdrawHandlingCharge(userWithdraw.getWithdrawHandlingCharge());
        int i = rlWithdrawService.insertRlWithdraw(withdraw);
        ServiceUtil.assertion(i == 0, "新增提现记录失败");
    }

    //提现服务费
    private static BigDecimal getHandlingCharge(BigDecimal amount, UserWithdraw userWithdraw) {
        BigDecimal handlingCharge;
        if(userWithdraw.getHandlingChargeType().equals(ServiceConstants.HANDLING_CHARGE_TYPE_PERCENT)){
            BigDecimal handlingCharge1 = userWithdraw.getWithdrawHandlingCharge();// 5.4
            BigDecimal bigDecimal = handlingCharge1.divide(new BigDecimal(10), 6, RoundingMode.HALF_UP);// 0.0054
            handlingCharge = bigDecimal.multiply(amount).setScale(2, RoundingMode.HALF_UP);// 0.0054 * 1000 = 0.54
        }else{
            handlingCharge = userWithdraw.getWithdrawHandlingCharge();
        }
        return handlingCharge;
    }

    // 渠道成本
    private BigDecimal getCost(BigDecimal amount, ChannelWithdrawVO channelWithdraw) {
        BigDecimal cost;
        if(channelWithdraw.getHandlingChargeType().equals(ServiceConstants.HANDLING_CHARGE_TYPE_PERCENT)){
            cost = channelWithdraw.getCostRate().divide(new BigDecimal(100)).multiply(amount).setScale(2, RoundingMode.HALF_UP);
        }else{
            cost = channelWithdraw.getWithdrawHandlingCharge();
        }
        return cost;
    }

//    private void asynchronousMsg(String userName) {
//        scheduledExecutorService.schedule(() -> {
//            /** 提现申请发送一个短信给审核人*/
//            JSONObject jsonObject = new JSONObject();
//            jsonObject.put("name", userName);
//
//            SendSmsVo sendSmsVo = new SendSmsVo();
//            sendSmsVo.setMobile(phone);
//            sendSmsVo.setTemplateCode(templateCode3);
//            sendSmsVo.setParam(jsonObject.toJSONString());
//            sendSmsVo.setSignName(signName);
//            SendSmsResponse response = null;
//            log.info("【提现申请】向阿里云发送短信，请求,----------【{}】", JSON.toJSONString(sendSmsVo));
//            try {
//                response = SendAliSmsUtil.sendVerifyCode(accessKeyId,accessKeySecret,sendSmsVo);
//            } catch (ClientException e) {
//                e.printStackTrace();
//            }
//            log.info("【提现申请】发送阿里云短信成功,返回----------【{}】",JSON.toJSONString(response));
//
//            // 短信日志
//            EMsgLog etMsgLog = new EMsgLog();
//            etMsgLog.setPhone(phone);
//            etMsgLog.setContent("用户【"+userName+"】，发起押金提现申请，请尽快审核！");
//            etMsgLog.setType("2");
//            etMsgLog.setSignName(signName);
//            etMsgLog.setTemplateCode(templateCode3);
//            int i = msgLogService.insertEtMsgLog(etMsgLog);
//            if(i>0){
//                log.info("【提现申请】短信日志记录成功");
//            }else{
//                log.info("【提现申请】短信日志记录失败");
//            }
//        }, 0 , TimeUnit.HOURS);
//    }

//    /**
//     * 新增用户岗位信息
//     *
//     * @param user 用户对象
//     */
//    public void insertUserPost(EUser user)
//    {
//        Long[] posts = user.getPostIds();
//        if (StringUtils.isNotEmpty(posts))
//        {
//            // 新增用户与岗位管理
//            List<SysUserPost> list = new ArrayList<SysUserPost>(posts.length);
//            for (Long postId : posts)
//            {
//                SysUserPost up = new SysUserPost();
//                up.setUserId(user.getUserId());
//                up.setPostId(postId);
//                list.add(up);
//            }
//            userPostMapper.batchUserPost(list);
//        }
//    }

    /**
     * 新增用户角色信息
     *
     * @param userId 用户ID
     * @param roleIds 角色组
     */
    public void insertUserRole(Long userId, Long[] roleIds)
    {
        if (StringUtils.isNotEmpty(roleIds))
        {
            // 新增用户与角色管理
            List<SysUserRole> list = new ArrayList<SysUserRole>(roleIds.length);
            for (Long roleId : roleIds)
            {
                SysUserRole ur = new SysUserRole();
                ur.setUserId(userId);
                ur.setRoleId(roleId);
                list.add(ur);
            }
            userRoleMapper.batchUserRole(list);
        }
    }

}
