package com.philisense.www.api.repository.impl;

import com.philisense.www.api.repository.VcodeRepository;
import com.philisense.www.consts.ErrorConst;
import com.philisense.www.consts.VcodeKeys;
import com.philisense.www.enums.VcodeType;
import com.philisense.www.exception.UtilsException;
import com.philisense.www.properties.VcodeProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.ServletWebRequest;

import javax.annotation.Resource;
import java.time.LocalDateTime;

import static org.springframework.web.context.request.RequestAttributes.SCOPE_SESSION;

public class SessionVcodeRepository implements VcodeRepository {
    private static final Logger log = LoggerFactory.getLogger(SessionVcodeRepository.class);

    @Resource
    private VcodeProperties vcodeProperties;

    @Override
    public String save(ServletWebRequest request, Object vcodeValue, VcodeType type) {

        String dataKey = String.format(VcodeKeys.VCODE_DATA_TEMPLATE, type.getName());
        log.info("put vcode sessionid: {}", request.getSessionId());
        request.setAttribute(dataKey, vcodeValue, SCOPE_SESSION);

        LocalDateTime expireTime = LocalDateTime.now().plusSeconds(vcodeProperties.getCodeExpiration()); // 设置过期时间
        // 保存过期时间
        String expireKey = String.format(VcodeKeys.VCODE_EXPIRE_KEY_TEMPLATE, type.getName());
        request.setAttribute(expireKey, expireTime, SCOPE_SESSION);
        return dataKey;
    }

    @Override
    public Object get(ServletWebRequest request, VcodeType type) {
        String expireKey = String.format(VcodeKeys.VCODE_EXPIRE_KEY_TEMPLATE, type.getName());
        String dataKey = String.format(VcodeKeys.VCODE_DATA_TEMPLATE, type.getName());

        // 从session获取验证码信息
        Object dataObj = null;
        log.info("get vcode sessionid: {}", request.getSessionId());
        if ((dataObj = request.getAttribute(dataKey, SCOPE_SESSION)) == null) {
            throw new UtilsException(type.getDesc() + "不存在", ErrorConst.ERR_CODE);
        }
        // 验证码和过期时间会一同存在或者不存在
        LocalDateTime expireTime = (LocalDateTime)request.getAttribute(expireKey, SCOPE_SESSION);
        // 判断过期
        if (LocalDateTime.now().isAfter(expireTime)) {
            log.warn(type.getDesc() + "已过期");
            // 发现过期就做清理
            request.removeAttribute(expireKey, SCOPE_SESSION);
            request.removeAttribute(dataKey, SCOPE_SESSION);
            throw new UtilsException(type.getDesc() + "已过期", ErrorConst.ERR_CODE);
        }

        return dataObj;
    }

    @Override
    public void remove(ServletWebRequest request, VcodeType type) {
        String expireKey = String.format(VcodeKeys.VCODE_EXPIRE_KEY_TEMPLATE, type.getName());
        String dataKey = String.format(VcodeKeys.VCODE_DATA_TEMPLATE, type.getName());
        request.removeAttribute(expireKey, SCOPE_SESSION);
        request.removeAttribute(dataKey, SCOPE_SESSION);
    }
}
