package com.bio.bio_backend.global.filter;

import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

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

@Slf4j
@Component
public class HttpLoggingFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        
        long startTime = System.currentTimeMillis();
        
        // 요청 정보 로깅 (IP 정보 제거)
        log.info("HTTP REQUEST: {} {} | Headers: {} | Body: {}", 
            request.getMethod(), request.getRequestURI(),
            getRequestHeaders(request), getRequestBody(request));
        
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
        ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
        
        try {
            filterChain.doFilter(wrappedRequest, wrappedResponse);
        } finally {
            long duration = System.currentTimeMillis() - startTime;
            
            // 응답 정보 로깅
            log.info("HTTP RESPONSE: {} {} | Status: {} | Time: {}ms | Headers: {} | Body: {}", 
                request.getMethod(), request.getRequestURI(),
                wrappedResponse.getStatus(), duration, getResponseHeaders(wrappedResponse), getResponseBody(wrappedResponse));
            
            wrappedResponse.copyBodyToResponse();
        }
    }
    
    // 민감 정보 마스킹 메서드
    private String maskSensitiveData(String body) {
        if (body == null || body.isEmpty()) return "N/A";
        
        // 비밀번호, 토큰 등 민감 정보 마스킹
        return body.replaceAll("\"password\"\\s*:\\s*\"[^\"]*\"", "\"password\":\"***\"")
                  .replaceAll("\"token\"\\s*:\\s*\"[^\"]*\"", "\"token\":\"***\"")
                  .replaceAll("\"refreshToken\"\\s*:\\s*\"[^\"]*\"", "\"refreshToken\":\"***\"");
    }
    
    private String getRequestHeaders(HttpServletRequest request) {
        // 주요 헤더만 (Content-Type, Authorization, User-Agent)
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", request.getContentType());
        headers.put("User-Agent", request.getHeader("User-Agent"));
        
        // Authorization 헤더는 마스킹
        String auth = request.getHeader("Authorization");
        if (auth != null) {
            headers.put("Authorization", auth.startsWith("Bearer ") ? "Bearer ***" : "***");
        }
        
        return headers.toString();
    }
    
    private String getRequestBody(HttpServletRequest request) {
        try {
            ContentCachingRequestWrapper wrapper = (ContentCachingRequestWrapper) request;
            String body = new String(wrapper.getContentAsByteArray());
            return maskSensitiveData(body);
        } catch (Exception e) {
            return "N/A";
        }
    }
    
    private String getResponseHeaders(HttpServletResponse response) {
        // 응답 헤더 정보
        return "Content-Type: " + response.getContentType();
    }
    
    private String getResponseBody(HttpServletResponse response) {
        try {
            ContentCachingResponseWrapper wrapper = (ContentCachingResponseWrapper) response;
            String body = new String(wrapper.getContentAsByteArray());
            return maskSensitiveData(body);
        } catch (Exception e) {
            return "N/A";
        }
    }
    
    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        String path = request.getRequestURI();
        return path.startsWith("/static/") || 
               path.startsWith("/css/") || 
               path.startsWith("/js/") || 
               path.startsWith("/images/") ||
               path.equals("/actuator/health") ||
               path.equals("/favicon.ico");
    }
}
