package ervu_business_metrics.security.filter;

import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import ervu_business_metrics.security.model.jwt.authentication.JwtTokenDummy;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.CredentialsExpiredException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

  private final AuthenticationManager authenticationManager;

  public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
    this.authenticationManager = authenticationManager;
  }

  @Override
  protected void doFilterInternal(
      HttpServletRequest request, HttpServletResponse response, FilterChain filterChain
  ) throws ServletException, IOException {
    Authentication authentication = attemptAuthentication(request, response);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    filterChain.doFilter(request, response);
  }

  protected Authentication attemptAuthentication(
      HttpServletRequest request, HttpServletResponse response
  ) throws AuthenticationException {
    String token = extractAuthTokenFromRequest(request);

    if (token == null) {
      return null;
    }

    Authentication authentication = new JwtTokenDummy(token);
    try {
      authentication = authenticationManager.authenticate(authentication);
    }
    catch (CredentialsExpiredException e) {
      response.setStatus(401);
      //LOGGER.warn(e.getMessage());
    }
    return authentication;
  }

  private String extractAuthTokenFromRequest(HttpServletRequest request) {
    return Optional.ofNullable(request.getHeader("Authorization"))
        .map(token -> URLDecoder.decode(token, StandardCharsets.UTF_8))
        .map(token -> token.replace("Bearer", ""))
        .map(String::trim)
        .orElse(null);
  }
}
