package com.eactive.eai.rms.common.advice;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.Map;

/**
 * .json 요청에 대해 빈 응답 본문을 {}로 변환하는 ResponseBodyAdvice.
 *
 * 웹서버를 거치면서 Content-Type이 application/json으로 설정되는데,
 * 빈 응답이면 JavaScript(jQuery)가 JSON 파싱 시 에러가 발생하는 문제를 해결합니다.
 */
@ControllerAdvice
public class EmptyJsonResponseAdviceController implements ResponseBodyAdvice<Object> {

    private static final Logger logger = LoggerFactory.getLogger(EmptyJsonResponseAdviceController.class);
    private static final Map<String, Object> EMPTY_JSON = Collections.emptyMap();
    private static final String EMPTY_JSON_STRING = "{}";

    @PostConstruct
    public void init() {
        logger.debug("========== EmptyJsonResponseAdviceController 로딩됨 ==========");
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 모든 응답에 대해 적용 (beforeBodyWrite에서 .json 요청만 필터링)
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
            Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
            ServerHttpResponse response) {

			String path = request.getURI().getPath();
			        
			// .json 요청이 아니면 원본 그대로 반환
	        if (path == null || !path.endsWith(".json")) {
	            return body;
	        }
	
	        // 정상적인 응답이 있는 경우, String 타입의 빈 응답 처리
	        if (body != null && !(body instanceof String && ((String) body).isEmpty())) {
	            return body;
	        }
	        
	        // Controller 리턴타입이 String 일 때 cannot be cast 에러 대응 
	        logger.debug("빈 응답 감지, {} 로 변환 시도. 선택된 컨버터: {}", path, selectedConverterType.getSimpleName());
	
	        if (StringHttpMessageConverter.class.isAssignableFrom(selectedConverterType)) {
	            return EMPTY_JSON_STRING; // 문자열 "{}" 반환
	        }
	
	        return EMPTY_JSON; // Map 객체 반환
    }
}
