package cn.quantgroup.xyqb.controller.external.sms;

import cn.quantgroup.sms.MsgParams;
import cn.quantgroup.tech.util.TechEnvironment;
import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.aspect.captcha.CaptchaNewValidator;
import cn.quantgroup.xyqb.controller.IBaseController;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.sms.SmsMerchant;
import cn.quantgroup.xyqb.service.sms.ISmsService;
import cn.quantgroup.xyqb.util.DateUtils;
import cn.quantgroup.xyqb.util.IpUtil;
import cn.quantgroup.xyqb.util.ValidationUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * Created by FrankChow on 15/7/6.
 */
@Slf4j
@RestController
@RequestMapping("/api/sms")
public class SmsController implements IBaseController {

    private final static String RANDOM_CHARS = "0123456789";
    private static final long EXPIRE_MINUTES = 10;
    @Autowired
    private ISmsService smsService;
    @Autowired
    @Qualifier("stringRedisTemplate")
    private RedisTemplate<String, String> redisTemplate;
    @Value("${sms.is.debug}")
    private boolean smsIsDebug;
    private static final String IMAGE_IP_COUNT = "image:ip";
    private static final String IMAGE_PHONE_COUNT = "image:phone";
    private static final String IMAGE_DEVICEID_COUNT = "image:deviceId:";
    /** ip上限 */
    private static final Long IP_MAX_PER_DAY = 5000L;
    /** 手机号短信上限 */
    private static final Long PHONE_MAX_PER_DAY = 20L;
    /** 手机号语音上限 */
    private static final Long PHONE_VOICE_MAX_PER_DAY = 5L;
    /** 设备每天上限 */
    private static final Long DEVICE_MAX_PER_DAY = 20L;
    /** 手机号语音上限-KEY-4 */
    private static final String PHONE_VOICE_MAX_PER_DAY_KEY_4 = "4";
    /** 手机号语音上限-KEY-5 */
    private static final String PHONE_VOICE_MAX_PER_DAY_KEY_5 = "5";
    /** 手机号语音上限-KEY-6 */
    private static final String PHONE_VOICE_MAX_PER_DAY_KEY_6 = "6";

    /**
     * 短信验证码: for H5
     * 使用 @FPLock 注解并加入自定义限制参数, 做针对手机号的发送次数限制
     *
     * @param phoneNo      - 手机号
     * @param registerFrom -
     * @param appName      -
     * @param smsMerchant  - 短信模板/类型
     */
    @CaptchaNewValidator
    @RequestMapping("/send_sms_verification_code")
    public JsonResult verifyPhoneNoH5(@RequestParam String phoneNo,
                                      @RequestParam(required = false) String registerFrom,
                                      @RequestParam(required = false, defaultValue = "") String appName,
                                      @RequestParam(required = false) String smsMerchant) {
        log.info("注册-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_4);
        return sendVerificationCode2(phoneNo, randomCode, appName, smsMerchant);
    }

    /**
     * 短信验证码 ： 重置密码
     *
     * @param phoneNo      - 手机号
     * @param registerFrom -
     * @param appName      -
     * @param smsMerchant  - 短信模板/类型
     * @return
     */
    @CaptchaNewValidator
    @RequestMapping("/send_reset_code")
    public JsonResult resetPasswordH5(@RequestParam String phoneNo,
                                      @RequestParam(required = false) String registerFrom,
                                      @RequestParam(required = false, defaultValue = "") String appName,
                                      @RequestParam(required = false) String smsMerchant) {
        log.info("重置密码-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_4);
        return sendVerificationCode2(phoneNo, randomCode, appName, smsMerchant);
    }

    /**
     * 短信验证码: for H5
     * 使用 @FPLock 注解并加入自定义限制参数, 做针对手机号的发送次数限制
     */
    @CaptchaNewValidator
    @RequestMapping("/send_sms_verification_code_voice")
    public JsonResult verifyPhoneNoH5New(@RequestParam String phoneNo, @RequestParam(required = false) String registerFrom,
                                         String usage) {
        if (!Objects.equals(PHONE_VOICE_MAX_PER_DAY_KEY_4, usage)) {
            log.error("参数校验失败,用户注册语音验证码usage参数为{}", usage);
            return JsonResult.buildErrorStateResult("参数校验失败.", null);
        }
        log.info("注册-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_4);
        return sendVerificationCode2Voice(phoneNo, randomCode, usage);
    }

    @CaptchaNewValidator
    @RequestMapping("/send_reset_code_voice")
    public JsonResult resetPasswordH5New(@RequestParam String phoneNo, @RequestParam(required = false) String registerFrom,
                                         String usage) {
        if (!Objects.equals(PHONE_VOICE_MAX_PER_DAY_KEY_5, usage)) {
            log.error("参数校验失败,重置密码语音验证码usage参数为{}", usage);
            return JsonResult.buildErrorStateResult("参数校验失败.", null);
        }
        log.info("重置密码-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_4);
        return sendVerificationCode2Voice(phoneNo, randomCode, usage);
    }

    /**
     * 快速登陆发送验证码
     */
    @CaptchaNewValidator
    @RequestMapping("/send_login_code_voice")
    public JsonResult sendLoginCodeNew(@RequestParam String phoneNo, @RequestParam(required = false) String registerFrom,
                                       String usage) {
        if (!Objects.equals(PHONE_VOICE_MAX_PER_DAY_KEY_6, usage)) {
            log.error("参数校验失败,用户登录语音验证码usage参数为{}", usage);
            return JsonResult.buildErrorStateResult("参数校验失败.", null);
        }
        log.info("快速登陆-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_4);
        return sendVerificationCode2Voice(phoneNo, randomCode, usage);
    }

    /**
     * 快速登陆发送验证码
     *
     * @param phoneNo     - 手机号
     * @param appName     -
     * @param smsMerchant - 短信模板/类型
     */
    @CaptchaNewValidator
    @RequestMapping("/send_login_code")
    public JsonResult sendLoginCode(@RequestParam String phoneNo,
                                    @RequestParam(required = false) String registerFrom,
                                    @RequestParam(required = false, defaultValue = "") String appName,
                                    @RequestParam(required = false) String smsMerchant) {
        log.info("快速登陆-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_6);
        return sendVerificationCode2(phoneNo, randomCode, appName, smsMerchant);
    }

    /**
     * 快速注册发送验证码
     *
     * @param phoneNo     - 手机号
     * @param appName     -
     * @param smsMerchant - 短信模板/类型
     */
    @CaptchaNewValidator
    @RequestMapping("/send_regist_code")
    public JsonResult sendRegistCode(@RequestParam String phoneNo,
                                     @RequestParam(required = false) String registerFrom,
                                     @RequestParam(required = false, defaultValue = "") String appName,
                                     @RequestParam(required = false) String smsMerchant) {
        log.info("快速注册-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_4);
        return sendVerificationCode2(phoneNo, randomCode, appName, smsMerchant);
    }

    /**
     * 短信验证码
     *
     * @param phoneNo     - 手机号
     * @param appName     -
     * @param smsMerchant - 短信模板/类型
     * @return
     */
    private JsonResult sendVerificationCode2(String phoneNo, String randomCode, String appName, String smsMerchant) {
        if (!ValidationUtil.validatePhoneNo(phoneNo)) {
            return JsonResult.buildErrorStateResult("手机号格式有误", null);
        }

        String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo;
        long expire = redisTemplate.getExpire(key, TimeUnit.MINUTES);
        if (expire >= EXPIRE_MINUTES - 1) {
            return JsonResult.buildErrorStateResult("1分钟内不能重复获取验证码", null);
        }
        String uniqueId = phoneNo + UUID.randomUUID().toString().replaceAll("-", "");
        List<String> newList = new ArrayList<>();
        newList.add(randomCode);
        /*ConfirmableMsg confirmableMsg = new ConfirmableMsg(
                uniqueId, newList, "1", "1", phoneNo
        );*/
        MsgParams message = new MsgParams.Builder()
                .typeList(Collections.singletonList(2))
                .phoneNo(phoneNo)
                .merchantId(SmsMerchant.of(smsMerchant).getMerchantId())
                .contentId(SmsMerchant.of(smsMerchant).getContentId())
                .uniqueId(uniqueId)
                .contentArgs(Collections.singletonList(randomCode))
                .channel(appName)
                .build();
        try {
            //smsService.getSmsSender().sendConfirmableMessage(confirmableMsg);
            smsService.getSmsSender().sendMsg(message);
            redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES);
            deleteRetSendCode(phoneNo);//删除用户重置密码，多次错误逻辑
            return JsonResult.buildSuccessResult("发送成功", uniqueId);
        } catch (Exception e) {
            log.error("发送短信验证码失败");
            return JsonResult.buildErrorStateResult("发送失败", null);
        }
    }

    private JsonResult sendVerificationCode2Voice(String phoneNo, String randomCode, String usage) {
        String verificationCountKey = Constants.REDIS_VOICE_CODE_COUNT + phoneNo;
        Long getVerificationCount = redisTemplate.opsForHash().increment(verificationCountKey, usage, 1);
        redisTemplate.expire(verificationCountKey, DateUtils.getSeconds(), TimeUnit.SECONDS);
        if (getVerificationCount > PHONE_VOICE_MAX_PER_DAY) {
            return JsonResult.buildErrorStateResult("今天已获取5次语音验证码，请使用短信验证码或明天再试", null);
        }

        if (!ValidationUtil.validatePhoneNo(phoneNo)) {
            return JsonResult.buildErrorStateResult("手机号格式有误", null);
        }
        String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo;
        long expire = redisTemplate.getExpire(key, TimeUnit.MINUTES);
        if (expire >= EXPIRE_MINUTES - 1) {
            return JsonResult.buildErrorStateResult("1分钟内不能重复获取验证码", null);
        }
        String uniqueId = phoneNo + UUID.randomUUID().toString().replaceAll("-", "");
        MsgParams message = new MsgParams(Collections.singletonList(4), phoneNo, "1", "4", Collections.singletonList(randomCode), uniqueId);
        try {
            smsService.getSmsSender().sendMsg(message);
            redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES);
            deleteRetSendCode(phoneNo);//删除用户重置密码，多次错误逻辑
            return JsonResult.buildSuccessResult("发送成功", uniqueId);
        } catch (Exception e) {
            log.error("发送语音短信验证码失败");
            return JsonResult.buildErrorStateResult("发送失败", null);
        }
    }

    /**
     * 快速登陆发送验证码新版
     */
    @CaptchaNewValidator
    @RequestMapping("/send_login_code_voice_new")
    public JsonResult sendLoginCodeVoiceNew(@RequestParam String phoneNo, @RequestParam(required = false) String registerFrom,
                                            String usage, @RequestParam(required = false) String deviceId) {
        if (!Objects.equals(PHONE_VOICE_MAX_PER_DAY_KEY_6, usage)) {
            log.error("参数校验失败,用户登录语音验证码usage参数为{}", usage);
            return JsonResult.buildErrorStateResult("参数校验失败.", null);
        }
        log.info("快速登陆-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_4);
        return sendVerificationCode2VoiceNew(phoneNo, randomCode, usage, deviceId);
    }

    /**
     * 快速登陆发送短信验证码
     *
     * @param phoneNo      - 手机号
     * @param registerFrom -
     * @param deviceId     -
     * @param appName      -
     * @param smsMerchant  - 短信模板/类型
     */
    @CaptchaNewValidator
    @RequestMapping("/send_login_code_new")
    public JsonResult sendLoginSmsCodeNew(@RequestParam String phoneNo,
                                          @RequestParam(required = false) String registerFrom,
                                          @RequestParam(required = false) String deviceId,
                                          @RequestParam(required = false, defaultValue = "") String appName,
                                          @RequestParam(required = false) String smsMerchant) {
        log.info("快速登陆-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_6);
        return sendVerificationCode2New(phoneNo, randomCode, deviceId, true, appName, smsMerchant);
    }

    /**
     * 快速登陆发送短信验证码
     *
     * @param phoneNo      - 手机号
     * @param registerFrom -
     * @param deviceId     -
     * @param appName      -
     * @param smsMerchant  - 短信模板/类型
     */
    @CaptchaNewValidator
    @RequestMapping("/send_login_code_new_forH5")
    public JsonResult sendLoginSmsCodeNewForH5(@RequestParam String phoneNo,
                                               @RequestParam(required = false) String registerFrom,
                                               @RequestParam(required = false) String deviceId,
                                               @RequestParam(required = false, defaultValue = "") String appName,
                                               @RequestParam(required = false) String smsMerchant) {
        log.info("快速登陆-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_6);
        return sendVerificationCode2New(phoneNo, randomCode, deviceId, false, appName, smsMerchant);
    }

    /**
     * VCC通用 - 发送短信验证码
     *
     * @param phoneNo      - 手机号
     * @param registerFrom -
     * @param deviceId     -
     * @param appName      -
     * @param smsMerchant  - 短信模板/类型
     */
    @CaptchaNewValidator
    @RequestMapping("/send_vcc_sms_code")
    public JsonResult sendVccSmsCode(@RequestParam String phoneNo,
                                          @RequestParam(required = false) String registerFrom,
                                          @RequestParam(required = false) String deviceId,
                                          @RequestParam(required = false, defaultValue = "") String appName,
                                          @RequestParam(required = false) String smsMerchant) {
        log.info("VCC-发送验证码, phoneNo:{}, registerFrom:{}", phoneNo, registerFrom);
        String randomCode = getRandomCode(Constants.SMS_CODE_LEN_6);
        return sendVerificationCode2New(phoneNo, randomCode, deviceId, true, appName, smsMerchant);
    }

    public String getRandomCode(int count) {
        if(TechEnvironment.isPro()) {
            return RandomStringUtils.random(count, RANDOM_CHARS);
        }
        switch (count){
            case 6:
                return "000000";
            default:
                return Constants.SUCCESS_CODE;
        }
    }

    /**
     * 新版本短信验证码
     *
     * @param phoneNo     - 手机号
     * @param deviceId    - 设备id
     * @param isApp       -
     * @param appName     -
     * @param smsMerchant - 短信模板/类型
     * @return
     */
    public JsonResult sendVerificationCode2New(String phoneNo, String randomCode, String deviceId, boolean isApp, String appName, String smsMerchant) {
        if (!ValidationUtil.validatePhoneNo(phoneNo)) {
            return JsonResult.buildErrorStateResult("手机号格式有误", null);
        }
        String clientIp = getIp();
        log.info("请求短信新版本接口:phoneNo:{},deviceId:{},IP:{}", phoneNo, deviceId, clientIp);
        // 手机号计数器
        Long getPhoneVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_SMS_CODE_COUNT, phoneNo, 1);
        redisTemplate.expire(Constants.REDIS_SMS_CODE_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
        // 设备号计数器
        Long getDeviceVerificationCount = 0L;
        if (StringUtils.isNotBlank(deviceId)) {
            getDeviceVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_SMS_DEVICE_COUNT, deviceId, 1);
            redisTemplate.expire(Constants.REDIS_SMS_DEVICE_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
        }
        // IP计数器
        Long getIPVerificationCount = 0L;
        if (StringUtils.isNotBlank(clientIp)) {
            getIPVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_SMS_IP_COUNT, clientIp, 1);
            redisTemplate.expire(Constants.REDIS_SMS_IP_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
        }
        // 手机号上限检查
        if (getPhoneVerificationCount > PHONE_MAX_PER_DAY) {
            log.info("您手机号已经达到获取今天短信验证码上限:phoneNo:{},count:{}", phoneNo, getPhoneVerificationCount);
            return JsonResult.buildErrorStateResult("今天已获取20次短信验证码，请使用语音验证码或明天再试", null);
        }
        // 设备号上限检查
        if (getDeviceVerificationCount > DEVICE_MAX_PER_DAY) {
            log.info("您设备已经达到获取今天验证码上限:deviceId:{},count:{}", deviceId, getDeviceVerificationCount);
            return JsonResult.buildErrorStateResult("您设备已经达到获取今天验证码上限", null);
        }
        // IP上限检查
        if (!IpUtil.whiteOf(clientIp) && getIPVerificationCount > IP_MAX_PER_DAY) {
            log.info("您当前ip已经达到获取今天短信验证码上限:ip:{},count:{}", clientIp, getIPVerificationCount);
            return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天短信验证码上限", null);
        }

        String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo;
        long expire = redisTemplate.getExpire(key, TimeUnit.MINUTES);
        if (expire >= EXPIRE_MINUTES - 1) {
            log.info("sendVerificationCode2New1分钟内不能重复获取验证码:phoneNo:{},deviceId:{},ip:{}", phoneNo, deviceId, clientIp);
            return JsonResult.buildErrorStateResult("1分钟内不能重复获取验证码", null);
        }
        String uniqueId = phoneNo + UUID.randomUUID().toString().replaceAll("-", "");
        List<String> newList = new ArrayList<>();
        newList.add(randomCode);
        MsgParams message = new MsgParams.Builder()
                .typeList(Collections.singletonList(2))
                .phoneNo(phoneNo)
                .merchantId(SmsMerchant.of(smsMerchant).getMerchantId())
                .contentId(SmsMerchant.of(smsMerchant).getContentId())
                .uniqueId(uniqueId)
                .contentArgs(Collections.singletonList(randomCode))
                .channel(appName)
                .build();

        try {
            smsService.getSmsSender().sendMsg(message);
            redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES);
            //删除用户重置密码，多次错误逻辑
            deleteRetSendCode(phoneNo);
            if (isApp && needImageVlidate(clientIp, deviceId, phoneNo)) {
                return JsonResult.buildSuccessResult("发送成功", uniqueId, 3L);
            }
            log.info("sendVerificationCode2New获取短信成功:phone:{},deviceId:{},ip:{}", phoneNo, deviceId, clientIp);
            return JsonResult.buildSuccessResult("发送成功", uniqueId);
        } catch (Exception e) {
            log.error("发送短信验证码失败:phone:{},deviceId:{},ip:{}", phoneNo, deviceId, clientIp);
            return JsonResult.buildErrorStateResult("发送失败", null);
        }
    }

    /**
     * 新版本语音验证码
     */
    private JsonResult sendVerificationCode2VoiceNew(String phoneNo, String randomCode, String usage, String deviceId) {
        if (!ValidationUtil.validatePhoneNo(phoneNo)) {
            return JsonResult.buildErrorStateResult("手机号格式有误", null);
        }
        if (StringUtils.isBlank(usage)) {
            return JsonResult.buildErrorStateResult("usage参数无效", null);
        }
        String clientIp = getIp();
        log.info("请求短信新版本接口:phoneNo:{},deviceId:{},usage:{},IP:{}", phoneNo, deviceId, usage, clientIp);
        // 手机号计数器
        String verificationCountKey = Constants.REDIS_VOICE_CODE_COUNT + usage;
        Long getPhoneVerificationCount = redisTemplate.opsForHash().increment(verificationCountKey, phoneNo, 1);
        redisTemplate.expire(verificationCountKey, DateUtils.getSeconds(), TimeUnit.SECONDS);
        // 设备号计数器
        Long getDeviceVerificationCount = 0L;
        if (StringUtils.isNotBlank(deviceId)) {
            String verificationDeviceCountKey = Constants.REDIS_VOICE_DEVICE_COUNT + deviceId;
            getDeviceVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_VOICE_DEVICE_COUNT, verificationDeviceCountKey, 1);
            redisTemplate.expire(Constants.REDIS_VOICE_DEVICE_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
        }
        // IP计数器
        Long getIPVerificationCount = 0L;
        if (StringUtils.isNotBlank(clientIp)) {
            String verificationIPCountKey = Constants.REDIS_VOICE_IP_COUNT + clientIp;
            getIPVerificationCount = redisTemplate.opsForHash().increment(Constants.REDIS_VOICE_IP_COUNT, verificationIPCountKey, 1);
            redisTemplate.expire(Constants.REDIS_VOICE_IP_COUNT, DateUtils.getSeconds(), TimeUnit.SECONDS);
        }
        // 手机号上限检查
        if (getPhoneVerificationCount > PHONE_VOICE_MAX_PER_DAY) {
            log.info("您手机号已经达到获取今天语音验证码上限，请使用短信验证码或明天再试:phoneNo:{},count:{}", phoneNo, getPhoneVerificationCount);
            return JsonResult.buildErrorStateResult("今天已获取5次语音验证码，请使用短信验证码或明天再试", null);
        }
        // 设备号上限检查
        if (getDeviceVerificationCount > DEVICE_MAX_PER_DAY) {
            log.info("您设备已经达到获取今天语音验证码上限:deviceId:{},count:{}", deviceId, getDeviceVerificationCount);
            return JsonResult.buildErrorStateResult("您设备已经达到获取今天语音验证码上限", null);
        }
        // IP上限检查
        if (!IpUtil.whiteOf(clientIp) && getIPVerificationCount > IP_MAX_PER_DAY) {
            log.info("您当前ip已经达到获取今天短信验证码上限:ip:{},count:{}", clientIp, getIPVerificationCount);
            return JsonResult.buildErrorStateResult("您当前ip已经达到获取今天语音验证码上限", null);
        }

        String key = Constants.REDIS_PREFIX_VERIFICATION_CODE + phoneNo;
        long expire = redisTemplate.getExpire(key, TimeUnit.MINUTES);
        if (expire >= EXPIRE_MINUTES - 1) {
            return JsonResult.buildErrorStateResult("1分钟内不能重复获取验证码", null);
        }
        String uniqueId = phoneNo + UUID.randomUUID().toString().replaceAll("-", "");
        MsgParams message = new MsgParams(Collections.singletonList(4), phoneNo, "1", "4", Collections.singletonList(randomCode), uniqueId);
        try {
            smsService.getSmsSender().sendMsg(message);
            redisTemplate.opsForValue().set(key, uniqueId + ":" + randomCode, EXPIRE_MINUTES, TimeUnit.MINUTES);
            //删除用户重置密码，多次错误逻辑
            deleteRetSendCode(phoneNo);
            if (needImageVlidate(clientIp, deviceId, phoneNo)) {

                return JsonResult.buildSuccessResult("发送成功", uniqueId, 3L);
            }
            return JsonResult.buildSuccessResult("发送成功", uniqueId);
        } catch (Exception e) {
            log.error("发送语音短信验证码失败");
            return JsonResult.buildErrorStateResult("发送失败", null);
        }
    }

    /**
     * 判断下次是否提示图形验证码
     *
     * @param clientIp
     * @param deviceId
     * @param phoneNo
     * @return
     */
    private boolean needImageVlidate(String clientIp, String deviceId, String phoneNo) {
        boolean need = false;
        String countIP = redisTemplate.opsForValue().get(IMAGE_IP_COUNT + clientIp);
        String countDeviceId = redisTemplate.opsForValue().get(IMAGE_DEVICEID_COUNT + deviceId);
        String countPhoneNo = redisTemplate.opsForValue().get(IMAGE_PHONE_COUNT + phoneNo);
        Long ip = StringUtils.isBlank(countIP) ? 1L : Long.valueOf(countIP);
        Long devId = StringUtils.isBlank(countDeviceId) ? 1L : Long.valueOf(countDeviceId);
        Long phNo = StringUtils.isBlank(countPhoneNo) ? 1L : Long.valueOf(countPhoneNo);
        if (ip >= Constants.Image_Need_Count || devId >= Constants.Image_Need_Count || phNo >= Constants.Image_Need_Count) {
            need = true;
        }
        return need;
    }

    /**
     * 删除用户重置密码时短信验证错误
     *
     * @param phoneNo
     */
    private void deleteRetSendCode(String phoneNo) {
        String verificationCountKey = Constants.REDIS_VERIFICATION_COUNT + phoneNo;
        redisTemplate.opsForHash().delete(verificationCountKey, Constants.REDIS_VERIFICATION_COUNT);
    }

}
