package com.smyhub.infogenie.infogeniebackendjava.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.smyhub.infogenie.infogeniebackendjava.config.AppProperties;
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.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Map;

/**
 * Intercepts every request and, if a Bearer token is present in the Authorization header,
 * forwards it to the external auth-center for verification.
 *
 * On success the resulting AuthCenterUser is stored as a request attribute.
 * On failure the attribute is simply absent — controllers decide how to react
 * (401 for required-auth, ignored for optional-auth endpoints).
 *
 * Mirrors Go's OptionalJWTAuth / JWTAuth middleware pair.
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {

    private final AppProperties appProperties;
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

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

        String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7);
            AuthCenterUser user = verifyToken(token);
            if (user != null) {
                request.setAttribute(AuthCenterUser.AUTH_USER_ATTR, user);
            }
        }
        filterChain.doFilter(request, response);
    }

    private AuthCenterUser verifyToken(String token) {
        try {
            String url = appProperties.getAuthCenterUrl() + "/api/auth/verify";

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("X-Auth-Client", "infogenie");
            headers.set("X-Auth-Client-Name", "万象口袋");

            Map<String, String> body = Map.of("token", token);
            HttpEntity<Map<String, String>> entity = new HttpEntity<>(body, headers);

            ResponseEntity<Map> responseEntity =
                    restTemplate.postForEntity(url, entity, Map.class);

            if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) {
                Map<?, ?> responseBody = responseEntity.getBody();
                Object userObj = responseBody.get("user");
                if (userObj != null) {
                    String userJson = objectMapper.writeValueAsString(userObj);
                    return objectMapper.readValue(userJson, AuthCenterUser.class);
                }
            }
        } catch (Exception e) {
            log.debug("Auth-center token verification failed: {}", e.getMessage());
        }
        return null;
    }
}
