package com.muchinfo.mtp3century.filter;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.muchinfo.mtp3common.enumtype.Constants;
import com.muchinfo.mtp3common.enumtype.MessageType;
import com.muchinfo.mtp3common.utils.JwtUtil;
import com.muchinfo.mtp3century.utils.ResponseUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

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

public class JwtAuthorizationFilter extends BasicAuthenticationFilter {

    public JwtAuthorizationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        String headerToken = "";
        // 从header中获取token
        if (StringUtils.isBlank(headerToken) && StringUtils.isNotBlank(request.getHeader(JwtUtil.TOKEN_HEADER))) {
            headerToken = request.getHeader(JwtUtil.TOKEN_HEADER);
        }

        // 从参数中获取token
        if (StringUtils.isBlank(headerToken) && StringUtils.isNotBlank(request.getParameter(JwtUtil.TOKEN_HEADER))) {
            headerToken = request.getParameter(JwtUtil.TOKEN_HEADER);
        }

        // 校验token头
        if (StringUtils.isBlank(headerToken) || !headerToken.startsWith(JwtUtil.TOKEN_PREFIX)) {
            chain.doFilter(request, response);
            return;
        }
        // 解析token
        String token = headerToken.substring(JwtUtil.TOKEN_PREFIX.length());
        Claims claims = null;
        try {
            claims = JwtUtil.parseToken(token);
            // 校验token是否过期
            if (JwtUtil.isExpiration(claims)) {
                chain.doFilter(request, response);
                return;
            }
        } catch (ExpiredJwtException e) {
            ResponseUtils.writeFiled(response, Constants.Token_failure_code, MessageType.MESSAGE_ERROR_CODE_SYSTEM001.getCode(), request.getHeader("Accept-Language"));
            return;
        }
        String username = JwtUtil.getUsername(claims);
        if (StringUtils.isBlank(username)) {
            chain.doFilter(request, response);
            return;
        }
        Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (String authority : JwtUtil.getAuthorities(claims)) {
            authorities.add(new SimpleGrantedAuthority(authority));
        }

        SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(username, null, authorities));

        refreshToken(token, response);
        super.doFilterInternal(request, response, chain);
    }

    /**
     * 刷新token
     *
     * @param token
     * @param response
     */
    private void refreshToken(String token, HttpServletResponse response) {
        token = JwtUtil.refreshToken(token);
        // 将token添加到header中
        response.setHeader("Access-Control-Expose-Headers", "Authorization");
        response.setHeader(JwtUtil.TOKEN_HEADER, JwtUtil.TOKEN_PREFIX + token);
    }
}
