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

import com.eactive.eai.rms.common.util.IpUtil;
import com.eactive.eai.rms.onl.apim.common.BaseRestController;
import com.eactive.eai.rms.onl.apim.service.IpAuthenticationService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * IP 화이트리스트 인증 인터셉터
 *
 * <p>BaseRestController를 상속받은 컨트롤러에 대해 IP 인증을 수행합니다.</p>
 *
 * <p>동작 흐름:</p>
 * <ol>
 *   <li>핸들러가 BaseRestController 인스턴스인지 확인</li>
 *   <li>클라이언트 IP 추출 (프록시 헤더 지원)</li>
 *   <li>IP 화이트리스트 대비 검증</li>
 *   <li>검증 실패 시 HTTP 403 Forbidden 반환</li>
 * </ol>
 *
 * <p>보안:</p>
 * <ul>
 *   <li>차단된 요청은 모두 로그에 기록됩니다</li>
 *   <li>IP 화이트리스트는 kjb.api.allow_ip_list 속성에서 관리됩니다</li>
 * </ul>
 *
 * @see BaseRestController
 * @see IpAuthenticationService
 */
@Component
@Slf4j
public class IpWhitelistInterceptor implements HandlerInterceptor {

    @Autowired
    private IpAuthenticationService ipAuthenticationService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // BaseRestController를 상속받은 컨트롤러만 IP 인증 적용
        if (!isBaseRestController(handler)) {
            return true;
        }

        String clientIp = IpUtil.getClientIp(request);
        String requestUri = request.getRequestURI();

        if (ipAuthenticationService.isIpAllowed(clientIp)) {
            if (log.isDebugEnabled()) {
                log.debug("IP authentication success - IP: {}, URI: {}", clientIp, requestUri);
            }
            return true;
        }

        // IP 인증 실패
        log.warn("IP authentication failed - IP: {}, URI: {}", clientIp, requestUri);
        sendErrorResponse(response, HttpServletResponse.SC_FORBIDDEN, "Access denied: IP address not in whitelist");
        return false;
    }

    /**
     * 핸들러가 BaseRestController 인스턴스인지 확인
     *
     * @param handler 핸들러 객체
     * @return BaseRestController 인스턴스이면 true
     */
    private boolean isBaseRestController(Object handler) {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Object controller = handlerMethod.getBean();
            return controller instanceof BaseRestController;
        }
        return false;
    }

    /**
     * 에러 응답 전송
     *
     * @param response HttpServletResponse
     * @param status HTTP 상태 코드
     * @param message 에러 메시지
     * @throws IOException I/O 오류 발생 시
     */
    private void sendErrorResponse(HttpServletResponse response, int status, String message) throws IOException {
        response.setStatus(status);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(String.format("{\"error\": \"%s\"}", message));
    }
}
