package com.patzn.lims.sys.service.impl;

import com.baomidou.kisso.common.IpHelper;
import com.baomidou.kisso.common.util.RandomUtil;
import com.patzn.lims.core.api.PtAssert;
import com.patzn.lims.core.web.Account;
import com.patzn.lims.sys.enums.VerificationCodeEnum;
import com.patzn.lims.sys.service.ISmsService;
import com.patzn.lims.sys.service.ISysUserService;
import com.patzn.lims.sys.service.RedisCountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 短信验证码表 服务实现类
 * </p>
 *
 * @author patzn
 * @since 2018-03-31
 */
@Service
public class SmsServiceImpl implements ISmsService {

    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private RedisCountService redisCountService;


    @Override
    public boolean sendValidCode(HttpServletRequest request, Account account, String module, String mobile) {
        PtAssert.fail("暂不支持发送短信");
        // 模块判断
        VerificationCodeEnum vce = VerificationCodeEnum.fromPrefix(module);
        PtAssert.fail(null == vce, "指定模块不存在，请不要尝试谢谢");

        // 手机号码登录
        PtAssert.fail(VerificationCodeEnum.LOGIN == vce && !sysUserService.isVerify(mobile), "该手机号码未激活，请注册后发送");

        // 手机号码绑定
        if (VerificationCodeEnum.BIND_MOBILE == vce || VerificationCodeEnum.BIND_CHANGE_MOBILE == vce) {
            PtAssert.fail(sysUserService.isVerify(mobile), "该手机号码已激活，请使用其它号码发送");
        }

        // 手机号码注册
        PtAssert.fail(VerificationCodeEnum.REGISTER == vce && sysUserService.isVerify(mobile), "该手机号码已注册，请更换其他手机号码");

        // 同模块同一个 IP 一天允许 20 次请求验证码
        String ip = IpHelper.getIpAddr(request);
        int ipCount = redisCountService.get(vce.getKey(ip));
        PtAssert.fail(ipCount >= 20, "当前 IP 发送次数超过限制，请勿恶意发送谢谢。");

        // 同模块一个手机号码只允许发送 3 次验证码
        int mobileCount = redisCountService.get(vce.getKey(mobile));
        PtAssert.fail(mobileCount >= 3, "该手机号码验证码已发送，未收到 2 小时后重试。");

        // 短信验证码
        String code = RandomUtil.getNumber(6);

        // 记录2小时内该模块手机发送次数
        redisCountService.set(vce.getKey(mobile), ipCount, 2);

        // 验证码内容30分钟有效
        if (vce == VerificationCodeEnum.BIND_MOBILE || vce == VerificationCodeEnum.BIND_CHANGE_MOBILE) {
            PtAssert.fail(null == account, "未登录无法绑定指定用户");
            redisTemplate.opsForValue().set(vce.getKey(account.getUserIdStr(), code), mobile,
                    30, TimeUnit.MINUTES);
        } else {
            redisTemplate.opsForValue().set(vce.getKey(mobile, code), code, 30, TimeUnit.MINUTES);
        }

        // 记录24小时 IP 发送次数
        redisCountService.set(vce.getKey(ip), ipCount, 24);

        // 调用短信接口发送短信
        return false;
    }


    @Override
    public boolean bindByCode(VerificationCodeEnum verificationCodeEnum, Account account, String vailCode) {
        if (null == verificationCodeEnum || null == account || null == vailCode) {
            return false;
        }
        // 绑定激活手机号
        String mobile = redisTemplate.opsForValue().get(verificationCodeEnum.getKey(account.getUserIdStr(), vailCode));
        PtAssert.fail(null == mobile, "该验证码无效，请重新输入");
        return sysUserService.bindMobileById(account.getUserId(), mobile);
    }
}
