package kr.gmtc.tss.util;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.ExchangeStrategies;
import org.springframework.web.reactive.function.client.WebClient;

import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;

@Configuration
public class WebClientConfig {
	private final Logger log = LoggerFactory.getLogger(getClass());
	
	@Bean
    public WebClient webClient() {
		// 기본 설정으로 생성
        HttpClient httpClient = HttpClient.create();
        
        httpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000);
        httpClient.doOnConnected(connection -> {
        			connection.addHandlerLast(new ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS));
        		    connection.addHandlerLast(new WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS));
        });
        
        //Memory 조정: 2M (default 256KB)
        ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
            .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(2*1024*1024)) 
            .build();

        return WebClient.builder()
        		.baseUrl("")
        		.defaultHeader("Access-Control-Allow-Origin", "*")
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .exchangeStrategies(exchangeStrategies)
                .filter(
                    (req, next) -> next.exchange(
                        ClientRequest.from(req).header("from", "webclient").build()
                    )
                )
                .filter(
                    ExchangeFilterFunction.ofRequestProcessor(
                        clientRequest -> {
                            log.info(">>>>>>>>>> REQUEST <<<<<<<<<<");
                            log.info("Request: {} {}", clientRequest.method(), clientRequest.url());
                            clientRequest.headers().forEach(
                                (name, values) -> values.forEach(value -> log.info("{} : {}", name, value))
                            );
                            return Mono.just(clientRequest);
                        }
                    )
                )
                .filter(
                    ExchangeFilterFunction.ofResponseProcessor(
                        clientResponse -> {
                            log.info(">>>>>>>>>> RESPONSE <<<<<<<<<<");
                            clientResponse.headers().asHttpHeaders().forEach((name, values) -> values.forEach(value -> log.info("{} : {}", name, value)));
                            return Mono.just(clientResponse);
                        }
                    )
                )
                .build();
    }
}
