package com.mvc.interceptor;

import com.alibaba.fastjson.JSON;
import com.mvc.constant.QueryUserType;
import com.mvc.model.ResultGeekerModel;
import com.mvc.utils.JwtUtil;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * Jwt拦截器(处理Token)
 */
public class JwtInterceptor implements HandlerInterceptor {
    //记录用户退出前的Token(做软件测评时,特殊处理的)
    // static List<String> expiredTokenList = new ArrayList<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //如果不是映射到方法直接通过
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        //从 http 请求头中取出 token
        String token = request.getHeader("Authorization");

        //****测评临时处理****(对第三方开放的接口,仍要校验/api/v1.. 2023-12-23 guozhao)
        if (org.apache.commons.lang3.StringUtils.isEmpty(token)
                &&!request.getRequestURI().contains("/api/v1")
        ) {
            return true;
        }

        if (org.apache.commons.lang3.StringUtils.isEmpty(token)) {
            handleInvalidToken(response);
            return false;

            //throw new RuntimeException("无 token ，请重新登陆");
        }

        if (StringUtils.hasLength(token) && token.indexOf("Bearer") >= 0) {
            token = token.substring("Bearer ".length() - 1).trim();
        } else {
            handleInvalidToken(response);
            //throw new RuntimeException("Token错误");
            return false;
        }

        //****测评临时处理****
        /*String tokenInfo = JwtUtil.getUserId(token);
        if (!userId.equals(tokenInfo)) {//不是指定用户跳过验证
            return true;
        } else {
            if (expiredTokenList.indexOf(token) > -1) {
                response.setCharacterEncoding("UTF-8");
                response.setContentType("application/json; charset=utf-8");
                response.sendError(1500);//用户退出,使用了旧的Token
                return true;
            }
            if (request.getRequestURI().contains("loginOut")) {//登出接口
                expiredTokenList.add(token);
                if (expiredTokenList.size() > 50) {
                    expiredTokenList.remove(0);
                }
            }
        }*/

        //验证 token
        boolean flag = JwtUtil.checkSign(token);

        /*if (expiredTokenList.indexOf(token) > -1) {//用户退出了
            flag = false;
        }*/

        if (!flag) {
            handleInvalidToken(response);
            return false;
        }

        //验证通过后， 这里测试取出JWT中存放的数据
        //获取 token 中的 userId
        JwtUtil.getUserId(token);
        //System.out.println("id : " + userId);

        //获取 token 中的其他数据
        //JwtUtil.getInfo(token);
        //info.forEach((k, v) -> System.out.println(k + ":" + v));
        return true;
    }

    private void handleInvalidToken(HttpServletResponse response) {
        // 返回一个错误响应，例如401 Unauthorized状态码和一个错误消息
        try{
            response.setCharacterEncoding("UTF-8");
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json");
            //response.sendError(1501);
            ResultGeekerModel model=new ResultGeekerModel("token invalid");
            String json = JSON.toJSONString(model);

            byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
            response.getOutputStream().write(bytes);
            /*//response.getWriter().write(json);
            //使用getWriter()会有此异常:nested exception is java.lang.IllegalStateException: getWriter() has already been called for this response
            //无法同时使用getWriter()和getOutputStream(),怀疑SpringBoot默认已经使用了使用getWriter */
        }catch (Exception ex){

        }
    }

    /**
     * 根据request获取userId
     * @param request
     * @return
     */
    public static String getUserIdByRequest(HttpServletRequest request){
        return JwtUtil.getUserId(getTokenByRequest(request));
    }

    public static Map<String, Object> getInfoByRequest(HttpServletRequest request){
        String token = getTokenByRequest(request);
        return JwtUtil.getInfo(token);
    }

    /**
     * 根据request获取用户类型
     * @param request
     * @return
     */
    public static QueryUserType getQueryUserTypeByRequest(HttpServletRequest request){
        String token = getTokenByRequest(request);
        Map<String, Object> info = JwtUtil.getInfo(token);
        if (info != null && info.containsKey("queryUserType")) {
            return QueryUserType.findDataViewTypeByflag(info.get("queryUserType").toString());
        }
        return null;
    }

    /**
     * 从请求中获取token
     * @param request
     * @return
     */
    private static String getTokenByRequest(HttpServletRequest request){
        //从 http 请求头中取出 token
        String token = request.getHeader("Authorization");

        if (StringUtils.hasLength(token) && token.indexOf("Bearer") >= 0) {
            token = token.substring("Bearer ".length() - 1).trim();
        }
        return token;
    }
}
