package com.bonus.auth.service;

import com.bonus.common.core.constant.CacheConstants;
import com.bonus.common.core.constant.Constants;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.CaptchaException;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.VerificationCodeUtils;
import com.bonus.common.core.utils.sms.SmsUtils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.redis.service.RedisService;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.system.api.RemoteConfigService;
import com.bonus.system.api.domain.SysUser;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * 登录密码方法
 *
 * @author bonus
 */
@Component
public class SysPasswordService {
    @Autowired
    private RedisService redisService;

    private int maxRetryCount = CacheConstants.PASSWORD_MAX_RETRY_COUNT;

    private Long lockTime = CacheConstants.PASSWORD_LOCK_TIME;

    @Autowired
    private SysRecordLogService recordLogService;

    @Resource
    private RemoteConfigService configService;

    /**
     * 登录账户密码错误次数缓存键名
     *
     * @param username 用户名
     * @return 缓存键key
     */
    private String getCacheKey(String username) {
        return CacheConstants.REDIS_KEY + username;
    }

    public void validate(SysUser user, String password, long startTime) {
        String username = user.getUserName();
        Integer retryCount = redisService.getCacheObject(getCacheKey(username));
        Integer times = 5;
        Integer lockTime = 20;
        AjaxResult timesAjaxResult = configService.getConfigKey("sys.login.failed.times");
        AjaxResult lockTimeAjaxResult = configService.getConfigKey("sys.login.failed.locktime");
        if (timesAjaxResult.isSuccess()){
            times = Integer.parseInt(timesAjaxResult.get("msg").toString());
        }
        if (lockTimeAjaxResult.isSuccess()){
            lockTime = Integer.parseInt(lockTimeAjaxResult.get("msg").toString());
        }

        if (ObjectUtils.isEmpty(retryCount)){
            retryCount = 0;
        }
        if (retryCount >= times) {
            long time = redisService.getExpire(getCacheKey(username));
            String errMsg = String.format("密码输入错误%s次，帐户锁定,请%s分钟后重试", maxRetryCount, time / 60 + 1);
            recordLogService.saveErrorLogs( user.getUserName(), startTime,"", "连续登录失败，锁定账号" );
            throw new ServiceException(errMsg);
        }
        if (!matches(user, password)) {
            retryCount = retryCount + 1;
            recordLogService.saveLogs(username, startTime, "密码输入错误", "用户不存在/密码错误", null, null);
            redisService.setCacheObject(getCacheKey(username), retryCount, (long)lockTime, TimeUnit.MINUTES);
            throw new ServiceException("用户不存在/密码错误");
        } else {
            clearLoginRecordCache(username);
        }
    }
    public boolean matches(SysUser user, String rawPassword) {
        return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
    }

    public void clearLoginRecordCache(String loginName) {
        if (redisService.hasKey(getCacheKey(loginName))) {
            redisService.deleteObject(getCacheKey(loginName));
        }
    }

    /**
     * 生成手机验证码
     *
     * @return AjaxResult
     * @throws IOException      输入输出异常
     * @throws CaptchaException 自定义captcha 异常
     */
    public R createPhoneCaptcha(String phone) {
        if (StringUtils.isEmpty(phone)) {
            throw new CaptchaException("手机号不能为空");
        }
        String code = VerificationCodeUtils.generateVerificationCode(VerificationCodeUtils.CodeType.NUMERIC);
        String str = "您的验证码为" + code + "，尊敬的客户，以上验证码3分钟有效，微服务平台提醒您：转发可能导致账号被盗，请勿将验证码泄露于他人";
        String verifyKey = CacheConstants.VERIFICATION_CODE + phone;
        String s = SmsUtils.smsToken(phone, str, "");
        if (StringUtils.isNotEmpty(s)) {
            if (s.contains("ok")) {
                redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
            } else {
                throw new CaptchaException("获取短信失败");
            }
        } else {
            throw new CaptchaException("获取短信失败");
        }

        return R.ok();
    }
}
