package com.qnfhq.modules.user.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.map.MapUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.qnfhq.common.exception.RenException;
import com.qnfhq.common.redis.RedisUtils;
import com.qnfhq.common.utils.DateUtils;
import com.qnfhq.common.utils.IpUtils;
import com.qnfhq.common.utils.MessageUtils;
import com.qnfhq.common.utils.Result;
import com.qnfhq.constant.ApiConstant;
import com.qnfhq.modules.user.dao.AppUserDao;
import com.qnfhq.modules.user.dto.*;
import com.qnfhq.modules.user.dto.setting.AssetSymbolSetting;
import com.qnfhq.modules.user.entity.AppAssetEntity;
import com.qnfhq.modules.user.entity.AppUserDetailEntity;
import com.qnfhq.modules.user.entity.AppUserEntity;
import com.qnfhq.modules.user.entity.SettingEntity;
import com.qnfhq.modules.user.enums.*;
import com.qnfhq.modules.user.service.*;
import com.qnfhq.utils.EmailUtils;
import com.qnfhq.utils.EmailValidUtils;
import com.qnfhq.utils.OrderUtils;
import com.qnfhq.utils.password.PasswordStrengthValidator;
import com.qnfhq.utils.password.PasswordUtils;
import com.qnfhq.utils.sms.SmsSenderUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.qnfhq.common.service.impl.BaseServiceImpl;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

/**
 * 玩家用户表
 *
 * @author yelz 30262728@qq.com
 * @since 1.0.0 2025-11-11
 */
@Slf4j
@Service
@AllArgsConstructor
public class AppUserServiceImpl extends BaseServiceImpl<AppUserDao, AppUserEntity> implements AppUserService {

    @Resource
    RedisUtils redisUtils;

    @Resource
    private SettingService settingService;

    @Resource
    private AppUserDetailService detailService;

    @Resource
    private AppAssetService assetService;

    @Resource
    AppuserLoginLogService appuserLoginLogService;

    @Resource
    private SmsSendService smsSendService;

    @Resource
    private CaptchaService captchaService;

    @Override
    public AppUserEntity getUserByEmail(String email) {
        return baseDao.selectOne(new LambdaQueryWrapper<AppUserEntity>()
                .eq(AppUserEntity::getEmail, email)
                .eq(AppUserEntity::getStatus, UserStatus.OK.getCode())
                .last(" limit 1")
        );
    }

    @Override
    public AppUserEntity getUserByMobile(String mobile,String zone) {
        return baseDao.selectOne(new LambdaQueryWrapper<AppUserEntity>()
                .eq(AppUserEntity::getPhone, mobile)
                .eq(AppUserEntity::getZone, zone)
                .eq(AppUserEntity::getStatus, UserStatus.OK.getCode())
                .last(" limit 1")
        );
    }

    @Override
    public AppUserEntity getUserByUserId(Long userId) {
        return baseDao.selectById(userId);
    }

    @Override
    public AppUserEntity getUserByActiveCode(String activeCode) {
        return baseDao.selectOne(new LambdaQueryWrapper<AppUserEntity>()
                .eq(AppUserEntity::getActiveCode, activeCode)
                .eq(AppUserEntity::getStatus, UserStatus.OK.getCode())
                .last(" limit 1")
        );
    }

    public AppUserEntity getUserByLoginName(String loginName,String zone) {
        if(Validator.isEmail(loginName)) {
            return getUserByEmail(loginName);
        } else {
            return getUserByMobile(loginName,zone);
        }
    }

    /**
     * 注册
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result register(AppRegisterDTO registerDto, HttpServletRequest request) {
        AppUserEntity fUser = null;
        //判断推荐码是否存在
        if(StringUtils.isNotEmpty(registerDto.getActiveCode())) {
            fUser  = getUserByActiveCode(registerDto.getActiveCode());
            if(null == fUser) {
                throw new RenException(MessageUtils.message("user.register.activecode.notexisit"));//推荐码不存在
            }
        }

        AppUserEntity appUserEntity = new AppUserEntity();
        //临时邮箱检测
        EmailValidUtils.validateEmail(registerDto.getEmail());
        //密码强度检测
        PasswordStrengthValidator.validatePasswordStrength(registerDto.getLoginPassword());


        //验证码校验
        String codeType = registerDto.getCodeType();
        final String phoneCodeResultKey = String.format("%s%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),registerDto.getZone(),registerDto.getPhone(),":result");
        verifyResult(phoneCodeResultKey);
        final String emailCodeResultKey = String.format("%s%s%s%s", CachePrefix.EMAIL_CODE.getPrefix(), UserCodeTypeEnum.valueOf(codeType).name(), registerDto.getEmail(),":result");
        verifyResult(emailCodeResultKey);

        AppUserEntity appUser = getUserByEmail(registerDto.getEmail());
        if(Objects.nonNull(appUser)){
            throw new RenException(MessageUtils.message("user.register.email.exisit"));//邮箱已存在
        }
        appUser = getUserByMobile(registerDto.getPhone(),registerDto.getZone());
        if(Objects.nonNull(appUser)){
            throw new RenException(MessageUtils.message("user.register.phone.exisit"));//手机号已存在
        }


        appUserEntity.setCountry(registerDto.getCountry());
        appUserEntity.setLoginName(registerDto.getEmail().toLowerCase().trim());
        String host = request.getServerName();
        appUserEntity.setHost(host);
        appUserEntity.setRegisterIp(IpUtils.getIpAddr(request));
        appUserEntity.setEmail(registerDto.getEmail().toLowerCase().trim());
        appUserEntity.setZone(registerDto.getZone());
        appUserEntity.setPhone(registerDto.getPhone());
        appUserEntity.setStatus(UserStatus.OK.getCode());
        appUserEntity.setIsTest(0);
        appUserEntity.setIsBlack(UserBlackEnum.NORMAL.getCode());
        appUserEntity.setLoginPassword(PasswordUtils.encode(registerDto.getLoginPassword().trim()));

        //设置6位随机邀请码
        String activeCodeKey = "register_active_code";
        Long activeCode = redisUtils.increment(activeCodeKey, 1L, -1L);
        String registerActiveCode = activeCode.toString();
        if(activeCode<100000L) {
            registerActiveCode=OrderUtils.generateActiveCode(6,activeCode);
        }
        appUserEntity.setActiveCode(registerActiveCode);

        //设置推荐人
        if (null != fUser) {
            String appParentIds = fUser.getAppParentIds();
            String userId = fUser.getId() + "";
            if (StringUtils.isNotBlank(appParentIds)) {
                String[] split = appParentIds.split(",");
                if (split.length >= 3) {
                    for (int i = 0; i < split.length - 1; i++) {
                        userId += "," + split[i];
                    }
                    appUserEntity.setAppParentIds(userId);
                } else {
                    appUserEntity.setAppParentIds(userId + "," + appParentIds);
                }
            } else {
                appUserEntity.setAppParentIds(fUser.getId() + "");
            }
            //存代理关系
            appUserEntity.setAdminParentIds(fUser.getAdminParentIds());
            appUserEntity.setParentId(fUser.getId());
        }
        //设置昵称
        appUserEntity.setNickname(OrderUtils.generateNickname("QN",12));
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        //用户唯一标识
        appUserEntity.setUid(uuid);
        appUserEntity.setCreateTime(new Date());
        appUserEntity.setUpdateTime(new Date());
        if(baseDao.insert(appUserEntity)<=0) {
            throw new RenException(MessageUtils.message("user.register.fail"));//注册失败
        }

        //初始化玩家详情表
        initAppUserDetail(appUserEntity);
        //初始化玩家用户钱包-平台资产、理财、合约
        initAppUserAsset(appUserEntity);

        appUserEntity.setLoginPassword(null);
        Result result = new Result();
        result.setMsg(MessageUtils.message("user.register.success"));//注册成功
        result.setData(appUserEntity);
        return result;
    }


    /**
     * 登陆
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Result login(AppLoginDTO dto, HttpServletRequest request)
    {
        //图形验证码 要改滑动码
        //if(!captchaService.validate(dto.getUuid(), dto.getCode())) {
        //    throw new RenException(MessageUtils.message("appUser.login.code.err"));//验证码错误
        //}

        //账号密码失败重试次数
        checkPwdErrTryTimes(dto.getLoginName());

        AppUserEntity appUser = getUserByLoginName(dto.getLoginName(),dto.getZone());
        if(appUser==null) {
            throw new RenException(MessageUtils.message("appUser.loginName.or.password.err"));//账号或密码错误
        }
        if(!PasswordUtils.matches(dto.getLoginPassword(),appUser.getLoginPassword())){
            long pwdFailTimes = setPwdErrTryTimes(dto.getLoginName());
            checkPwdErrTryTimes(dto.getLoginName());
            throw new RenException(MessageUtils.message("appUser.loginName.or.password.err.limit.chance",ApiConstant.PASSWORD_FAIL_HOUR_TIMES-pwdFailTimes));//账号或密码错误，您还有4次机会
        }
        //手机验证校验
        String codeType = UserCodeTypeEnum.LOGIN.name();
        final String phoneCodeResultKey = String.format("%s%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),appUser.getZone(),appUser.getPhone(),":result");
        verifyResult(phoneCodeResultKey);

        //是否黑名单
        if(Objects.nonNull(appUser.getIsBlack()) && appUser.getIsBlack() == UserBlackEnum.BLOCK.getCode()){
            throw new RenException(MessageUtils.message("user_is_black"));//您的账号已被列入黑名单，无法登录。
        }


        StpUtil.login(appUser.getId());
        appuserLoginLogService.insertAppActionLog(appUser, "用户登录", "0", request);

        Result result = new Result();
        result.setMsg(MessageUtils.message("appUser.login.success"));//登陆成功
        result.setData(MapUtil.of(StpUtil.getTokenName(), StpUtil.getTokenValue()));
        return result;
    }


    @Override
    public void initAppUserDetail(AppUserEntity user) {
        //添加玩家详情表
        AppUserDetailEntity tAppUserDetail = new AppUserDetailEntity();
        tAppUserDetail.setUserId(user.getId());
        //信用设置
        Integer credits = 100;
        SettingEntity setting1 = settingService.getSetting(SettingEnum.LOGIN_REGIS_SETTING.name());
        if (Objects.nonNull(setting1)) {
            JSONObject loginRegisSetting = JSONUtil.parseObj(setting1.getSettingValue());
            credits=loginRegisSetting.getInt("credits");
        }
        tAppUserDetail.setCredits(credits);
        tAppUserDetail.setCreateTime(new Date());
        tAppUserDetail.setUpdateTime(new Date());
        detailService.insert(tAppUserDetail);
    }



    @Override
    public void initAppUserAsset(AppUserEntity user) {
        SettingEntity setting = settingService.getSetting(SettingEnum.ASSET_COIN.name());
        List<AssetSymbolSetting> currencyList = JSONUtil.toList(JSONUtil.parseArray(setting.getSettingValue()), AssetSymbolSetting.class);
        if (!CollectionUtils.isEmpty(currencyList)) {
            Map<String, List<AssetSymbolSetting>> symbolGroup = currencyList.stream().collect(Collectors.groupingBy(AssetSymbolSetting::getSymbol));
            symbolGroup.forEach((symbol, assetList) -> {
                AppAssetEntity tAppAsset = new AppAssetEntity();
                tAppAsset.setUserId(user.getId());
                tAppAsset.setSymbol(symbol);
                tAppAsset.setTotal(BigDecimal.ZERO);
                tAppAsset.setFrozen(BigDecimal.ZERO);
                tAppAsset.setAvailable(BigDecimal.ZERO);
                tAppAsset.setType(AssetEnum.PLATFORM_ASSETS.getCode());
                tAppAsset.setCreateTime(new Date());
                tAppAsset.setUpdateTime(new Date());
                assetService.insert(tAppAsset);
            });
        }

        //初始化玩家用户钱包-理财资产
        AppAssetEntity tAppAsset = new AppAssetEntity();
        tAppAsset.setUserId(user.getId());
        tAppAsset.setSymbol("usdt");
        tAppAsset.setTotal(BigDecimal.ZERO);
        tAppAsset.setFrozen(BigDecimal.ZERO);
        tAppAsset.setAvailable(BigDecimal.ZERO);
        tAppAsset.setType(AssetEnum.FINANCIAL_ASSETS.getCode());
        tAppAsset.setCreateTime(new Date());
        tAppAsset.setUpdateTime(new Date());
        assetService.insert(tAppAsset);

        //初始化玩家用户钱包-合约账户
        tAppAsset.setType(AssetEnum.CONTRACT_ASSETS.getCode());
        tAppAsset.setId(null);
        assetService.insert(tAppAsset);
    }


    /**
     * 发送邮箱验证码
     * 校验邮箱 已存在
     * @param codeType 类型：LOGIN 登录使用
     * @param email 邮箱
     * @return
     */
    @Override
    public Result sendEmailCode(String codeType, String email) {

        if (!EmailUtils.checkEmail(email)) {
            throw new RenException(MessageUtils.message("user.register.email.format"));//邮箱格式不正确
        }

        if(codeType.toLowerCase().equals("register")) {
            EmailValidUtils.validateEmail(email);

            AppUserEntity existUser = getUserByEmail(email);
            if (Objects.nonNull(existUser)) {
                throw new RenException(MessageUtils.message("user.register.email.exisit"));//邮箱已存在
            }
        }
        email = email.trim();
        final String emailKey = String.format("%s%s%s",CachePrefix.EMAIL_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),email);
        sendCodeFrequencyLimit(ApiConstant.EMAIL_EXPIRE,emailKey);

        Result result = new Result();
        try {
            EmailUtils.formMail(email, codeType);
        } catch (Exception e) {
            log.error("EmailUtils.formMail.err:{}",e.getMessage());
            return result.error(MessageUtils.message("user.email.send.fail"));//邮箱发送失败
        }
        result.setMsg(MessageUtils.message("app.verification.email.code"));//验证码已发送到您的邮箱，请注意查收
        return result;
    }

    /**
     * 发送手机验证码
     *
     * @param codeType 类型：LOGIN 登录使用
     * @param phone 手机号
     * @param zone 区号
     * @return
     */
    @Override
    public Result sendMobileCode(String codeType, String phone, String zone) {

        if(StringUtils.isEmpty(phone)){
            throw new RenException(MessageUtils.message("phone_code_empty"));//手机号不能为空!
        }

        if(codeType.toLowerCase().equals("register")) {
            AppUserEntity appUser = getUserByMobile(phone,zone);
            if(Objects.nonNull(appUser)){
                throw new RenException(MessageUtils.message("user.register.phone.exist"));//手机号已经存在
            }
        }


        final String smsKey = String.format("%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),zone,phone);
        sendCodeFrequencyLimit(ApiConstant.SMS_EXPIRE,smsKey);

        //发送验证码
        String randomCode = String.valueOf(SmsSenderUtil.getRandomNumber(100000, 999999));
        Map<String, String> map = new HashMap<>();
        map.put("code", randomCode);
        SendPhoneDto sendPhoneDto = new SendPhoneDto();
        sendPhoneDto.setMobile(zone + phone);
        sendPhoneDto.setCode(codeType);
        sendPhoneDto.setParams(map);
        Result result = smsSendService.sendMobileCodeV2(sendPhoneDto);
        if(result.getCode() == 200){
            redisUtils.set(smsKey, randomCode, ApiConstant.SMS_EXPIRE);
            final String codeTryKey = String.format("%s%s", smsKey,"try");
            redisUtils.delete(codeTryKey);
            result.setMsg(MessageUtils.message("user.code.send"));//验证码发送成功
        }
        return result;

    }


    private void sendCodeFrequencyLimit(long expireSet,String key) {
        long expireTime = redisUtils.getExpire(key);
        if(expireSet-expireTime < 60){
            throw new RenException(MessageUtils.message("user.sendcode.frequency.limit"));//验证码请求太过频率，请60秒后再试
        }
    }


    /**
     * 重设密码
     * @param codeDTO
     * @return
     */
    @Override
    public Result resetPwdByEmail(ResetPwdByEmailDTO codeDTO) {
        Result result = new Result();

        //校验邮箱验证码
        checkEmailCode("FIND_PASSWORD",codeDTO.getEmail(),codeDTO.getCode());

        //更新密码
        AppUserEntity appUser = getUserByEmail(codeDTO.getEmail());
        if(Objects.isNull(appUser)){
            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
        }
        appUser.setLoginPassword(PasswordUtils.encode(codeDTO.getNewPwd()));
        updateById(appUser);
        return result;

    }


    @Override
    public Result resetPwdByEmail(String email,String newPwd) {
        Result result = new Result();
        String codeType = "FIND_PASSWORD";
        //校验邮箱验证码
        final String emailCodeResultKey = String.format("%s%s%s%s", CachePrefix.EMAIL_CODE.getPrefix(), UserCodeTypeEnum.valueOf(codeType).name(), email,":result");
        verifyResult(emailCodeResultKey);

        //密码强度检测
        PasswordStrengthValidator.validatePasswordStrength(newPwd);
        //更新密码
        AppUserEntity appUser = getUserByEmail(email);
        if(Objects.isNull(appUser)){
            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
        }
        final String phoneCodeResultKey = String.format("%s%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),appUser.getZone(),appUser.getPhone(),":result");
        verifyResult(phoneCodeResultKey);

        appUser.setLoginPassword(PasswordUtils.encode(newPwd));
        //提币或c2c卖出限制时间
        appUser.setTransferOutTime(DateUtils.addDays(new Date(),1));
        updateById(appUser);

        return result;

    }


    @Override
    public Result resetPwdByPhone(String zone,String phone,String newPwd) {
        Result result = new Result();
        String codeType = "FIND_PASSWORD";
        //校验手机验证码
        final String phoneCodeResultKey = String.format("%s%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),zone,phone,":result");
        verifyResult(phoneCodeResultKey);

        //密码强度检测
        PasswordStrengthValidator.validatePasswordStrength(newPwd);
        //更新密码
        AppUserEntity appUser = getUserByMobile(phone,zone);
        if(Objects.isNull(appUser)){
            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
        }

        final String emailCodeResultKey = String.format("%s%s%s%s", CachePrefix.EMAIL_CODE.getPrefix(), UserCodeTypeEnum.valueOf(codeType).name(), appUser.getEmail(),":result");
        verifyResult(emailCodeResultKey);

        appUser.setLoginPassword(PasswordUtils.encode(newPwd));
        appUser.setTransferOutTime(DateUtils.addDays(new Date(),1));
        updateById(appUser);
        return result;

    }


    private void verifyResult(String codeResultKey) {
        Object codeResult = redisUtils.get(codeResultKey);
        if(Objects.isNull(codeResult) || (int)codeResult != 1){
            throw new RenException(MessageUtils.message("system.busy.try.again.later"));//系统繁忙，请稍后再试
        }
        redisUtils.delete(codeResultKey);
    }

    /**
     * 重设密码
     * @param codeDTO
     * @return
     */
    @Override
    public Result resetPwdByPhone(ResetPwdByPhoneDTO codeDTO) {
        Result result = new Result();

        //校验手机验证码
        checkPhoneCode("FIND_PASSWORD",codeDTO.getZone(),codeDTO.getPhone(),codeDTO.getCode());

        //更新密码
        AppUserEntity appUser = getUserByMobile(codeDTO.getPhone(),codeDTO.getZone());
        if(Objects.isNull(appUser)){
            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
        }
        appUser.setLoginPassword(PasswordUtils.encode(codeDTO.getNewPwd()));
        updateById(appUser);
        return result;

    }

    /**
     *限制验证码重试次数
     */
    private void checkCodeTryTimes(String codeKey) {
        Object tryTimesObj = redisUtils.get(codeKey);
        if(Objects.nonNull(tryTimesObj)){
            long tryTimes = Long.valueOf(tryTimesObj.toString());
            if(tryTimes>4L){
                throw new RenException(MessageUtils.message("code.try.times.limit"));//重试次数过多
            }
        }
    }

    /**
     * 校验密码输错次数
     * 密码输错5次，锁住1小时
     * 累计输错10次，锁24小时
     */
    private void checkPwdErrTryTimes(String loginName) {
        final String codeKey = String.format("%s%s","pwd_fail_hour_times:", loginName);
        Object tryTimesObj = redisUtils.get(codeKey);
        if(Objects.nonNull(tryTimesObj)){
            long pwdHourFailTimes = Long.valueOf(tryTimesObj.toString());
            if(pwdHourFailTimes>=ApiConstant.PASSWORD_FAIL_HOUR_TIMES){
                long expireTime = redisUtils.getExpire(codeKey);
                if(expireTime>3600){
                    long hourL = expireTime/3600L;
                    throw new RenException(MessageUtils.message("pwd.fail.times.excess.day.lock",hourL));//账号已锁，{0}小时后解锁
                } else if(expireTime>60){
                    long minL = expireTime/60L;
                    throw new RenException(MessageUtils.message("pwd.fail.times.excess.hour.lock",minL));//账号已锁，{0}分钟后解锁
                } else {
                    throw new RenException(MessageUtils.message("pwd.fail.times.excess.second.lock",expireTime));//账号已锁，{0}秒后解锁
                }
            }
        }
    }

    /**
     * 设置密码输错次数+1
     */
    private long setPwdErrTryTimes(String loginName) {
        final String pwdErrTimsHourKey = String.format("%s%s","pwd_fail_hour_times:", loginName);
        final String pwdErrTimsDayKey = String.format("%s%s","pwd_fail_day_times:", loginName);

        long pwdErrDayTimes = redisUtils.increment(pwdErrTimsDayKey, 1L, ApiConstant.PASSWORD_FAIL_LOCK_24HOUR);
        long pwdFailTimes = 1;
        if(pwdErrDayTimes>=ApiConstant.PASSWORD_FAIL_DAY_TIMES) {
            pwdFailTimes = redisUtils.increment(pwdErrTimsHourKey, 1L, ApiConstant.PASSWORD_FAIL_LOCK_24HOUR);
        } else {
            pwdFailTimes = redisUtils.increment(pwdErrTimsHourKey, 1L, ApiConstant.PASSWORD_FAIL_LOCK_HOUR);
        }
        return pwdFailTimes;
    }


    @Override
    public Result checkCaptcha(CheckCaptchaDTO dto, HttpServletRequest request)
    {
        if(!captchaService.validate(dto.getUuid(), dto.getCode())) {
            throw new RenException(MessageUtils.message("appUser.login.code.err"));//验证码错误
        }
        Result result = new Result();
        return result;
    }

    @Override
    public Result checkPhoneCode(String codeType,String zone,String phone,String code)
    {
        //校验手机验证码
        final String phoneCodeKey = String.format("%s%s%s%s",CachePrefix.SMS_CODE.getPrefix(),UserCodeTypeEnum.valueOf(codeType).name(),zone,phone);
        checkCode(phoneCodeKey,code);

        AppUserEntity user = getUserByMobile(phone,zone);
        if(Objects.isNull(user)) {
            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
        }
        Map data = MapUtil.of("phone",user.getPhone());
        data.put("zone",user.getZone());
        data.put("email",user.getEmail());
        Result result = new Result();
        result.setData(data);
        return result;
    }


    @Override
    public Result checkEmailCode(String codeType,String email,String code)
    {
        //校验邮箱验证码
        final String emailCodeKey = String.format("%s%s%s", CachePrefix.EMAIL_CODE.getPrefix(), UserCodeTypeEnum.valueOf(codeType).name(), email);
        checkCode(emailCodeKey,code);

        AppUserEntity user = getUserByEmail(email);
        if(Objects.isNull(user)) {
            throw new RenException(MessageUtils.message("user.not.exist"));//用户不存在
        }
        Map data = MapUtil.of("phone",user.getPhone());
        data.put("zone",user.getZone());
        data.put("email",user.getEmail());
        Result result = new Result();
        result.setData(data);
        return result;
    }

    /**
     * 校验验证码
     * @param cacheKey
     * @param code
     * @return
     */
    private void checkCode(String cacheKey,String code) {
        Object checkCode = redisUtils.get(cacheKey);
        if (checkCode == null) {
            throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
        } else {
            final String codeKeyTry = String.format("%s%s", cacheKey,"try");
            checkCodeTryTimes(codeKeyTry);
            String validCode = checkCode.toString();
            if (!code.equalsIgnoreCase(validCode)) {
                redisUtils.increment(codeKeyTry, 1L, ApiConstant.CHECK_EXPIRE);
                throw new RenException(MessageUtils.message("user.register.code.err"));//验证码错误
            }
        }
        redisUtils.delete(cacheKey);
        //设置验证结果
        final String checkCodeResult = String.format("%s%s",cacheKey,":result");
        redisUtils.set(checkCodeResult,1,ApiConstant.CHECK_EXPIRE);
    }
}