/**
 * JWT 认证过滤器。
 *
 * <p>从请求头 Authorization: Bearer token 中解析 JWT，并将认证信息写入 SecurityContext。</p>
 */
package com.hertz.security;

import com.hertz.modules.system.service.AuthzService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.stream.Collectors;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

@Component
public class JwtAuthFilter extends OncePerRequestFilter {
  private final JwtService jwtService;
  private final AuthzService authzService;

  public JwtAuthFilter(JwtService jwtService, AuthzService authzService) {
    this.jwtService = jwtService;
    this.authzService = authzService;
  }

  @Override
  protected void doFilterInternal(
      @NonNull HttpServletRequest request,
      @NonNull HttpServletResponse response,
      @NonNull FilterChain filterChain
  ) throws ServletException, IOException {
    var header = request.getHeader(HttpHeaders.AUTHORIZATION);
    if (header == null || !header.startsWith("Bearer ")) {
      filterChain.doFilter(request, response);
      return;
    }

    var token = header.substring("Bearer ".length()).trim();
    try {
      var claims = jwtService.parse(token);
      var userId = claims.get("uid", Number.class).longValue();
      var username = claims.getSubject();
      var authorities = authzService.loadAuthorities(userId).stream()
          .map(SimpleGrantedAuthority::new)
          .collect(Collectors.toSet());
      var auth = new UsernamePasswordAuthenticationToken(username, null, authorities);
      auth.setDetails(userId);
      SecurityContextHolder.getContext().setAuthentication(auth);
      // System.out.println("DEBUG: JWT Auth Success for user: " + username);
    } catch (Exception e) {
      System.err.println("DEBUG: JWT Auth Failed: " + e.getMessage());
      e.printStackTrace();
      logger.error("JWT Authentication failed: " + e.getMessage(), e);
      SecurityContextHolder.clearContext();
    }

    filterChain.doFilter(request, response);
  }
}

