package incheon.com.config;

import org.apache.catalina.valves.ErrorReportValve;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;

/**
 * Tomcat 내장 서버 최적화 설정
 */
@Configuration
public class EgovConfigAppTomcat {

    /**
     * Tomcat JAR 스캔 최적화 및 Multipart 설정
     */
    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() {
        return factory -> {
            // Context 커스터마이저: JAR 스캔 최적화
            factory.addContextCustomizers(context -> {
                if (context.getJarScanner() instanceof StandardJarScanner) {
                    ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
                }
            });

            // Connector 커스터마이저: Multipart Part 개수 제한 설정
            factory.addConnectorCustomizers(connector -> {
                // 일반 파라미터 개수 제한
                connector.setProperty("maxParameterCount", "20000");

                // Multipart Part 개수 제한 (Tomcat 9.0.106+ 에서 지원)
                try {
                    // Connector 객체에 직접 setMaxPartCount 호출 시도
                    connector.setMaxPartCount(20000);
                } catch (NoSuchMethodError e) {
                    // 메서드가 없는 경우 property로 설정 시도
                    connector.setProperty("maxPartCount", "20000");
                }

                // POST 크기 제한
                connector.setMaxPostSize(10485760); // 10MB
            });

            // Tomcat 레벨 에러 페이지 설정 (Request header is too large 등 파싱 에러 대응)
            factory.addErrorPages(
                new ErrorPage(HttpStatus.BAD_REQUEST, "/error")
            );

            // Tomcat 기본 에러 리포트 비활성화 (스택 트레이스 노출 방지)
            factory.addContextCustomizers(context -> {
                ErrorReportValve errorReportValve = new ErrorReportValve();
                errorReportValve.setShowReport(false);
                errorReportValve.setShowServerInfo(false);
                context.getParent().getPipeline().addValve(errorReportValve);
            });
        };
    }
}
