package cn.wise.sc.energy.power.plant.business.security;

import cn.wise.sc.energy.power.plant.business.config.MyApplicationContextAware;
import cn.wise.sc.energy.power.plant.common.core.bean.BaseResponse;
import com.alibaba.fastjson.JSON;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Header;
import io.jsonwebtoken.Jwts;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

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

import static cn.wise.sc.energy.power.plant.business.security.SecurityConstants.AUTHORIZATION_HEADER;
import static cn.wise.sc.energy.power.plant.business.security.SecurityConstants.SOCKET_TOKEN;
import static cn.wise.sc.energy.power.plant.business.security.SecurityConstants.TOKEN_PREFIX;

public class JWTFilter extends BasicAuthenticationFilter {

    private final UserDetailsService userDetailsService;
    RedissonClient redissonClient  = (RedissonClient) MyApplicationContextAware.getApplicationContext().getBean("redissonSingle");
    public JWTFilter(final AuthenticationManager authenticationManager,
                     final UserDetailsService userDetailsService) {
        super(authenticationManager);
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void doFilterInternal(final HttpServletRequest request,
                                    final HttpServletResponse response, final FilterChain filterChain)
            throws ServletException, IOException {
        final String token = this.getToken(request);
        //设置websocket 子协议头
        response.setHeader("Sec-WebSocket-Protocol",request.getHeader("Sec-WebSocket-Protocol"));
        /*if(true){
            filterChain.doFilter(request, response);
            return;
        }*/
        if(request.getServletPath().contains("/login")||request.getServletPath().contains("/plantInfo/allPlantInfo")){
            filterChain.doFilter(request, response);
            return;
        }
        if (!StringUtils.hasText(token)) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(BaseResponse.errorMsg("没有token权限")));
            return;
        }
        Claims claims;
        try {
            claims = Jwts.parserBuilder()
                    .setSigningKey(JWTKeyHolder.RISEN_KEY)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();

        } catch (Exception e) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(BaseResponse.errorMsg("无权限用户")));
            return;
        }

        final UserDetails userDetails = this.userDetailsService
                .loadUserByUsername(claims.getSubject());
        RBucket<String> cacheToken = redissonClient.getBucket("token:" + userDetails.getUsername());
        if (!token.equals(cacheToken.get())) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write(JSON.toJSONString(BaseResponse.errorMsg("toke已过期")));
            return;
        }
        SecurityContextHolder.getContext()
                .setAuthentication(new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities()
                ));
        filterChain.doFilter(request, response);
    }

    private String getToken(final HttpServletRequest request) {
        final String web_header = request.getHeader(AUTHORIZATION_HEADER);
        //socket token
        final String socket_header = request.getHeader(SOCKET_TOKEN);
        String header = socket_header!=null?TOKEN_PREFIX+socket_header:web_header;
        if (header != null  && header.startsWith(TOKEN_PREFIX)) {
            return header.substring(TOKEN_PREFIX.length());
        }
        return null;
    }
}
