package com.template.core;

import com.auth0.jwt.interfaces.Claim;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.template.annotation.PassToken;
import com.template.common.exception.MyCustomException;
import com.template.common.result.ResponseStatusEnum;
import com.template.common.utils.JWTUtil;
import org.springframework.boot.configurationprocessor.json.JSONObject;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Map;

public class JwtAuthenticationInterceptor implements HandlerInterceptor {

    /**
     * preHandle:进入到控制器方法之前执行的内容
     *     boolean：
     *         true：可以继续执行控制器方法
     *         false：拦截
     * posthandler：执行控制器方法之后执行的内容
     * afterCompletion：响应结束之前执行的内容
     *///说明
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //region 检查是否有passtoken注释，有则跳过认证
        //PassToken注解用在方法上面
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.requeired()) {
                return true;
            }
        }
        //endregion

        //除了登录和注册接口不需要user_head和token请求头外其他时候基本都要请求头
//        if(request.getHeader("user_head") == null){
//            //region 自定义返回响应的json格式
//            //加上这个可以让浏览器那里得到浏览器的401：response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
//            response.setCharacterEncoding("UTF-8");
//            response.setContentType("application/json; charset=utf-8");
//            JSONObject res = new JSONObject();
//            res.put("code", ResponseStatusEnum.MISSING_REQUEST_HEADER.getStatus());
//            res.put("message",  ResponseStatusEnum.MISSING_REQUEST_HEADER.getMsg());
//            res.put("success", false);
//            PrintWriter out = null;
//            out = response.getWriter();
//            out.write(res.toString());
//            out.flush();
//            out.close();
//            //endregion
//            return false;
//        }

        //region 获取url传递的参数 Query string传递的参数
        //获取url参数 getParameter方法里的参数名和定义的参数名一致
        String token = request.getHeader("token");
        // 验证userToken
        if (!StringUtils.hasText(token)) {
            throw new MyCustomException(ResponseStatusEnum.SYSTEM_TOKEN_ERROR);
        }

        // 解析token
        Map<String, Claim> stringClaimMap = JWTUtil.verifyToken(token);
        if (ObjectUtils.isNotEmpty(stringClaimMap)) { // 登录
            //String userId = stringClaimMap.get("identifierId").asString();
            //Integer userIds = stringClaimMap.get("userId").asInt();

            request.setAttribute("userId", stringClaimMap.get("userId").asInt());
            return true;
        }
        //endregion

        //region 自定义返回响应的json格式
        //加上这个可以让浏览器那里得到浏览器的401：response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        JSONObject res = new JSONObject();
        res.put("code", ResponseStatusEnum.NO_PERMISSION.getStatus());
        res.put("message", ResponseStatusEnum.NO_PERMISSION.getMsg());
        res.put("success", false);
        PrintWriter out = null;
        out = response.getWriter();
        out.write(res.toString());
        out.flush();
        out.close();
        //endregion

        //region 默认的响应提示信息
        //上面的提示信息返回格式和下面的只能开启一个，否则应用日志系统会导致Idean抛出异常：
        //java.lang.IllegalStateException: getWriter() has already been called for this response
        //response.sendError(401, "无权限");
        //endregion

        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
