package com.skr.mdm.filter;

import com.skr.mdm.authentication.admin.AdminAuthenticationEntryPoint;
import com.skr.mdm.authentication.admin.VerifyCodeException;
import com.skr.mdm.enums.ResultCodeEnum;
import com.skr.mdm.util.RedisGetKeyUtil;
import com.skr.mdm.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 验证码校验过滤器
 *
 * @author nfq
 * @date 2021/4/12 15:58
 */
@Component
@Slf4j
public class VerificationCodeFilter extends OncePerRequestFilter {

    private static final String LOGIN_URI = "/login";
    public static final String VERIFY_CODE_PARAMETER = "verifyCode";
    public static final String UUID_PARAMETER = "uuid";

    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private AdminAuthenticationEntryPoint authenticationEntryPoint;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //校验验证码
        String method = request.getMethod();
        if (StringUtils.equals(LOGIN_URI, request.getRequestURI()) && StringUtils.equalsIgnoreCase(HttpMethod.POST.name(), method.toLowerCase())) {
            ServletWebRequest servletWebRequest = new ServletWebRequest(request);
            String verifyCode = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), VERIFY_CODE_PARAMETER);
            String uuid = ServletRequestUtils.getStringParameter(servletWebRequest.getRequest(), UUID_PARAMETER);
            try {
                checkVerifyCode(verifyCode, uuid);
            } catch (VerifyCodeException e) {
                authenticationEntryPoint.commence(request, response, e);
                return;
            }
        }
        filterChain.doFilter(request, response);
    }

    private void checkVerifyCode(String verifyCode, String uuid) {
        if (StringUtils.isBlank(verifyCode)) {
            throw new VerifyCodeException(ResultCodeEnum.VERIFY_CODE_EMPTY.getCode(), ResultCodeEnum.VERIFY_CODE_EMPTY.getMsg());
        }
        if (redisUtils.get(RedisGetKeyUtil.getVerifyCodeKey(uuid)) == null) {
            throw new VerifyCodeException(ResultCodeEnum.VERIFY_CODE_EXPIRE.getCode(), ResultCodeEnum.VERIFY_CODE_EXPIRE.getMsg());
        }
        String verifyCodeRedis = redisUtils.get(RedisGetKeyUtil.getVerifyCodeKey(uuid)).toString();
        if (!StringUtils.equals(verifyCode.toLowerCase(), verifyCodeRedis.toLowerCase())) {
            throw new VerifyCodeException(ResultCodeEnum.VERIFY_CODE_ERROR.getCode(), ResultCodeEnum.VERIFY_CODE_ERROR.getMsg());
        }
        redisUtils.del(RedisGetKeyUtil.getVerifyCodeKey(uuid));
    }
}
