package com.zhangmeng.admin.manager.service.impl;


import com.wf.captcha.SpecCaptcha;
import com.zhangmeng.admin.manager.config.verificationCode.VerificationCodeConfig;
import com.zhangmeng.admin.manager.service.VerificationCodeService;
import com.zhangmeng.admin.manager.utils.RedisTemplateUtil;
import com.zhangmeng.model.base.baseService.impl.AbstractBaseServiceImpl;
import com.zhangmeng.model.base.baseUtil.CommonUtil;
import com.zhangmeng.model.entity.VerificationCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example;

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

/**
 * @author zhangmeng
 * @version 1.0
 * @date 2021/4/1 21:33
 */
@Service
public class VerificationCodeServiceImpl extends AbstractBaseServiceImpl<VerificationCode> implements VerificationCodeService {

    private final static String VERIFICATION_CODE_KEY = "VerificationCodeKey";

    @Autowired
    private VerificationCodeConfig verificationCodeConfig;

    @Autowired
    private RedisTemplate<String, List<String>> redisTemplate;

    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    @Override
    public void mysql_save(SpecCaptcha specCaptcha) {
        String text = specCaptcha.text();
        VerificationCode verificationCode = new VerificationCode();
        verificationCode.setDeleteStatus(false);
        verificationCode.setAddTime(new Date());
        verificationCode.setUpdateTime(new Date());
        verificationCode.setCode(text.toLowerCase());
        verificationCode.setStatus(VerificationCode.Status.login);
        verificationCode.setType(VerificationCode.Type.pc);
        this.save(verificationCode);
    }

    /**
     * mysql 验证码校验
     *
     * @param code 验证码
     * @return boolean
     */
    @Override
    public boolean mysql_verify(String code) {
        boolean flag = false;
        long expirationTime = new Date().getTime() + this.verificationCodeConfig.getExpirationTime() * 1000; //毫秒
        Date date = new Date(expirationTime);
        Condition condition = new Condition(VerificationCode.class);
        Example.Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("code", code);
        criteria.andLessThan("addTime", CommonUtil.data_format(date, CommonUtil.Format.YYYY_MM_DD_HH_MM_SS));
        List<VerificationCode> verificationCodes = this.findByCondition(condition);
        if (verificationCodes.size() > 0) {
            flag = true;
        }
        return flag;
    }

    @Override
    public void redis_save(SpecCaptcha specCaptcha) {
        String code = specCaptcha.text();
        Map<String, Object> map = new HashMap<>();
        map.put(String.valueOf(new Date().getTime()), code);
        this.redisTemplateUtil.set_verification_code_map(map);
    }

    /**
     * 缓存
     *
     * @param generatorVerificationCode 验证码
     */
    public void cacheVerificationCode(String generatorVerificationCode) {
        //转小写
        generatorVerificationCode = generatorVerificationCode.toLowerCase();
        VerificationCodeConfig.Type type = this.verificationCodeConfig.getType();
        cacheVerificationCode2Redis(generatorVerificationCode);
    }


    /**
     * 缓存验证码
     *
     * @param generatorVerificationCode 验证码
     */
    private void cacheVerificationCode2Redis(String generatorVerificationCode) {
        //判断Redis 里面是否存在
        List<String> verificationCodeList = this.redisTemplate.opsForValue().get("VERIFICATION_CODE_KEY");
        if (verificationCodeList != null && verificationCodeList.size() > 0) {
            if (!verificationCodeList.contains(generatorVerificationCode)) {
                verificationCodeList.add(generatorVerificationCode);
            }
        } else {
            verificationCodeList = new ArrayList<>();
            verificationCodeList.add(generatorVerificationCode);
        }
        this.redisTemplate.boundValueOps(VERIFICATION_CODE_KEY).set(verificationCodeList, verificationCodeConfig.getExpirationTime(), TimeUnit.SECONDS);
    }
}
