package com.om.interceptor;


import com.alibaba.fastjson.JSON;
import com.om.constant.RedisConstant;
import com.om.exception.CustomerAuthenticationException;
import com.om.utils.AdminContext;
import com.om.utils.JwtUtils;
import com.om.utils.Result;

import com.om.utils.ResultCode;
import lombok.extern.slf4j.Slf4j;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;


import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * jwt令牌校验的拦截器
 */
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {

    @Resource
    private JwtUtils jwtUtils;

    @Resource
    private RedisTemplate redisTemplate;

    /**
     * 校验jwt
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //判断当前拦截到的是Controller的方法还是其他资源
        if (!(handler instanceof HandlerMethod)) {
            //当前拦截到的不是动态方法，直接放行
            return true;
        }

        //2、校验令牌
        try {
             this.validateToken(request);
        } catch (CustomerAuthenticationException ex) {

            response.setContentType("application/json;charset=UTF-8");  // 设置字符集为 UTF-8
            String message = ex.getMessage();
            response.setStatus(ResultCode.NO_AUTH);
            response.getWriter().write(JSON.toJSONString(Result.error().message(message).result(401)));
            return false;
        }

        return true;
    }


    /**
     * 验证token信息
     */
    private void validateToken(HttpServletRequest request) {

        //从headers头部获取token信息
        String token = request.getHeader("token");

        //如果请求头部中没有携带token  则从请求的参数中中获取token
        if (StringUtils.isEmpty(token)) {
            token = request.getParameter("token");        //从参数中获取

        }

        //如果请求参数中也没有携带token信息  则抛出异常
        if (StringUtils.isEmpty(token)) {
            throw new CustomerAuthenticationException("token不存在");
        }


        //从token中获取管理员id
        Integer aId = jwtUtils.getAdminIdFromToken(token);
        //判断 管理员id 是否为空
        if (StringUtils.isEmpty(aId)) {
            throw new CustomerAuthenticationException("token解析失败");
        }

        //判断redis中是否存在token信息

        String tokenKey = RedisConstant.ADMIN_TOKEN_PREFIX +aId;
        String redisToken = (String) redisTemplate.opsForValue().get(tokenKey);

        //判断redis中是否存在token信息  如果为空 则表示token已经失效、
        if (StringUtils.isEmpty(redisToken)) {
            throw new CustomerAuthenticationException("token已过期");

        }

        //如果token和redis中的token不一致 则验证失败
        if (!token.equals(redisToken)) {
            throw new CustomerAuthenticationException("token验证失败");
        }
        //获取管理员id
        AdminContext.setAdminId(aId);
    }
}

