package com.cm.manager.sms.manager;

import com.cm.common.exception.ParamsException;
import com.cm.manager.sms.pojo.VerificationCode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: VerificationCodeManager
 * @Description: 验证码管理
 * @Author: WangGeng
 * @Date: 2020/3/4 5:34 下午
 * @Version: 1.0
 **/
public class VerificationCodeManager {

    private static final Logger LOG = LoggerFactory.getLogger(VerificationCodeManager.class);
    private static final VerificationCodeManager verificationCodeManager = VerificationCodeManagerBuilder.verificationCodeManager;
    private Map<String, VerificationCode> verificationCodeMap = new ConcurrentHashMap<>();
    /**
     * 有效时间60s
     */
    public static final long EXPIRE_TIME = 120000L;

    private VerificationCodeManager() {
    }

    public static VerificationCodeManager getInstance() {
        return verificationCodeManager;
    }

    /**
     * 设置验证码
     *
     * @param key
     * @param code
     */
    public void setVerificationCode(String key, String code) {
        VerificationCode verificationCode = new VerificationCode();
        verificationCode.setCode(code);
        verificationCode.setTime(System.currentTimeMillis());
        verificationCodeMap.put(key, verificationCode);
    }

    /**
     * 获取验证码
     *
     * @param key
     * @return
     */
    public String getVerificationCode(String key) {
        VerificationCode verificationCode = verificationCodeMap.get(key);
        if (verificationCode != null && (System.currentTimeMillis() - verificationCode.getTime() < EXPIRE_TIME)) {
            return verificationCode.getCode();
        }
        return null;
    }

    /**
     * 是否有有效的验证码
     *
     * @param key
     * @return
     */
    public long effectiveVerificationCodeTimeRemaining(String key) {
        VerificationCode verificationCode = verificationCodeMap.get(key);
        if (verificationCode == null) {
            return 0;
        }
        long timeRemaining = System.currentTimeMillis() - verificationCode.getTime();
        if (timeRemaining >= EXPIRE_TIME) {
            return 0;
        }
        return EXPIRE_TIME - timeRemaining;
    }

    /**
     * 清理使用后的验证码
     *
     * @param key
     */
    public void clearUsedVerificationCode(String key) {
        verificationCodeMap.remove(key);
    }

    /**
     * 校验验证码
     *
     * @param key
     * @param code
     */
    public void checkVerificationCode(String key, String code) {
        String verificationCode = getVerificationCode(key);
        if (StringUtils.isBlank(verificationCode)) {
            throw new ParamsException("验证码无效");
        }
        if (!StringUtils.equals(code, verificationCode)) {
            throw new ParamsException("验证码不匹配");
        }
        clearUsedVerificationCode(key);
    }

    /**
     * 删除过期验证码
     */
    public void clearExpireTimeCode() {
        int size = 0;
        long currentTime = System.currentTimeMillis();
        for (Map.Entry<String, VerificationCode> kv : verificationCodeMap.entrySet()) {
            VerificationCode verificationCode = kv.getValue();
            if (currentTime - verificationCode.getTime() > EXPIRE_TIME) {
                verificationCodeMap.remove(kv.getKey());
                size++;
            }
        }
        LOG.debug("本次清除超时验证码:{}个", size);
    }

    private static class VerificationCodeManagerBuilder {
        public static VerificationCodeManager verificationCodeManager = new VerificationCodeManager();
    }

}
