package com.gnx.telemedicine.security;

import com.gnx.telemedicine.util.CorrelationIdUtil;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

@Component
@RequiredArgsConstructor
@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    private final JwtUtils jwtUtils;
    private final CustomUserDetailsService customUserDetailsService;

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

        String authHeader = request.getHeader("Authorization");

        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7);
            
            // Skip if token is null or empty
            if (token == null || token.isEmpty() || token.equals("null")) {
                log.debug("JWT: Empty or null token for {}", request.getRequestURI());
                filterChain.doFilter(request, response);
                return;
            }
            
            try {
                if (jwtUtils.validateToken(token)) {
                    String email = jwtUtils.getEmailFromToken(token);
                    log.debug("JWT: Token validated successfully for user: {} on {}", email, request.getRequestURI());
                    UserDetails userDetails = customUserDetailsService.loadUserByUsername(email);
                    
                    // Check if user account is still enabled (active)
                    if (!userDetails.isEnabled()) {
                        log.warn("JWT: Account is deactivated for user: {}", email);
                        response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                        response.getWriter().write("{\"message\":\"Account is deactivated\"}");
                        response.setContentType("application/json");
                        return; // Stop processing if user is deactivated
                    }
                    
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                            email,
                            null,
                            userDetails.getAuthorities()
                    );
                    authentication.setDetails(
                            new WebAuthenticationDetailsSource().buildDetails(request)
                    );
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                    
                    // Set user ID in MDC for logging
                    CorrelationIdUtil.setUserId(email);
                    
                    log.debug("JWT: Authentication set for user: {} with roles: {}", email, userDetails.getAuthorities());
                } else {
                    // Token validation failed
                    log.warn("JWT: Token validation failed for request: {}", request.getRequestURI());
                    log.debug("JWT: Token (first 20 chars): {}", token.length() > 20 ? token.substring(0, 20) + "..." : token);
                }
            } catch (Exception e) {
                // Log but don't fail - let Spring Security handle authentication failure
                // Invalid tokens will result in 401 Unauthorized
                log.error("JWT validation error for {}: {}", request.getRequestURI(), e.getMessage(), e);
            }
        } else {
            log.debug("JWT: No Authorization header found for {}", request.getRequestURI());
        }
        filterChain.doFilter(request, response);
    }
}
