// Path: src/main/java/com/webfluxclient/LogLevel.java
// public enum LogLevel {
//     /** No logs. */
//     NONE,
// 
//     /**
//      * Logs request and response lines.
//      *
//      * <p>Example:
//      * <pre>{@code
//      * --> POST /hello
//      * Content-Type: application/json
//      *
//      * <-- 200 OK POST /hello (22ms)
//      * }</pre>
//      */
//     BASIC,
// 
//     /**
//      * Logs request and response lines and their respective headers.
//      *
//      * <p>Example:
//      * <pre>{@code
//      * --> POST /hello
//      * Content-Type: plain/text
//      * Headers:
//      * - Accept-Language: en
//      * - Accept-Charset: UTF-8
//      * --> END POST
//      *
//      * <-- 200 OK POST /hello (22ms)
//      * Headers:
//      * - Content-Type: plain/text
//      * <-- END HTTP
//      * }</pre>
//      */
//     HEADERS
// }
// 
// Path: src/main/java/com/webfluxclient/Logger.java
// public interface Logger {
//     void log(Supplier<String> messageSupplier);
//     void log(String message);
// }
// 
// Path: src/main/java/com/webfluxclient/RequestProcessor.java
// @FunctionalInterface
// public interface RequestProcessor {
// 
//     ClientRequest process(ClientRequest request);
// 
//     default RequestProcessor andThen(RequestProcessor after) {
//         Assert.notNull(after, "");
//         return request -> after.process(process(request));
//     }
// }
// 
// Path: src/main/java/com/webfluxclient/ResponseProcessor.java
// @FunctionalInterface
// public interface ResponseProcessor {
// 
//     ClientResponse process(ClientResponse clientResponse);
// 
//     default ResponseProcessor andThen(ResponseProcessor after) {
//         Assert.notNull(after, "");
//         return request -> after.process(process(request));
//     }
// }
// 
// Path: src/main/java/com/webfluxclient/client/ExchangeFilterFunctions.java
// static ExchangeFilterFunction requestProcessorFilter(RequestProcessor requestProcessor) {
//     return ofRequestProcessor(clientRequest -> Mono.just(requestProcessor.process(clientRequest)));
// }
// 
// Path: src/main/java/com/webfluxclient/client/ExchangeFilterFunctions.java
// static ExchangeFilterFunction responseInterceptorFilter(ResponseProcessor responseProcessor) {
//     return ofResponseProcessor(clientResponse -> Mono.just(responseProcessor.process(clientResponse)));
// }


import com.webfluxclient.LogLevel;
import com.webfluxclient.Logger;
import com.webfluxclient.RequestProcessor;
import com.webfluxclient.ResponseProcessor;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import java.util.List;
import static com.webfluxclient.client.ExchangeFilterFunctions.requestProcessorFilter;
import static com.webfluxclient.client.ExchangeFilterFunctions.responseInterceptorFilter;
package com.webfluxclient.client;




public class DefaultExchangeFilterFunctionFactory implements ExchangeFilterFunctionFactory {

    @Override
    public ExchangeFilterFunction build(List<RequestProcessor> requestProcessors, List<ResponseProcessor> responseProcessors, Logger logger, LogLevel logLevel) {
        ExchangeFilterFunction exchangeFilterFunction = null;
        if (!requestProcessors.isEmpty()) {
            RequestProcessor requestProcessor = requestProcessors.stream()
                    .reduce(RequestProcessor::andThen)
                    .orElseGet(() -> clientRequest -> clientRequest);

            exchangeFilterFunction = requestProcessorFilter(requestProcessor);
        }

        if (logger != null && logLevel != null) {
            ExchangeFilterFunction loggingExchangeFilterFunction = ExchangeFilterFunctions.loggingFilter(logger, logLevel);
            exchangeFilterFunction = exchangeFilterFunction == null?
                    loggingExchangeFilterFunction :
                    exchangeFilterFunction.andThen(loggingExchangeFilterFunction);
        }

        if (!responseProcessors.isEmpty()) {
            ResponseProcessor responseProcessor = responseProcessors.stream()
                    .reduce(ResponseProcessor::andThen)
                    .orElseGet(() -> clientResponse -> clientResponse);

// Path: src/main/java/com/webfluxclient/LogLevel.java
// public enum LogLevel {
//     /** No logs. */
//     NONE,
// 
//     /**
//      * Logs request and response lines.
//      *
//      * <p>Example:
//      * <pre>{@code
//      * --> POST /hello
//      * Content-Type: application/json
//      *
//      * <-- 200 OK POST /hello (22ms)
//      * }</pre>
//      */
//     BASIC,
// 
//     /**
//      * Logs request and response lines and their respective headers.
//      *
//      * <p>Example:
//      * <pre>{@code
//      * --> POST /hello
//      * Content-Type: plain/text
//      * Headers:
//      * - Accept-Language: en
//      * - Accept-Charset: UTF-8
//      * --> END POST
//      *
//      * <-- 200 OK POST /hello (22ms)
//      * Headers:
//      * - Content-Type: plain/text
//      * <-- END HTTP
//      * }</pre>
//      */
//     HEADERS
// }
// 
// Path: src/main/java/com/webfluxclient/Logger.java
// public interface Logger {
//     void log(Supplier<String> messageSupplier);
//     void log(String message);
// }
// 
// Path: src/main/java/com/webfluxclient/RequestProcessor.java
// @FunctionalInterface
// public interface RequestProcessor {
// 
//     ClientRequest process(ClientRequest request);
// 
//     default RequestProcessor andThen(RequestProcessor after) {
//         Assert.notNull(after, "");
//         return request -> after.process(process(request));
//     }
// }
// 
// Path: src/main/java/com/webfluxclient/ResponseProcessor.java
// @FunctionalInterface
// public interface ResponseProcessor {
// 
//     ClientResponse process(ClientResponse clientResponse);
// 
//     default ResponseProcessor andThen(ResponseProcessor after) {
//         Assert.notNull(after, "");
//         return request -> after.process(process(request));
//     }
// }
// 
// Path: src/main/java/com/webfluxclient/client/ExchangeFilterFunctions.java
// static ExchangeFilterFunction requestProcessorFilter(RequestProcessor requestProcessor) {
//     return ofRequestProcessor(clientRequest -> Mono.just(requestProcessor.process(clientRequest)));
// }
// 
// Path: src/main/java/com/webfluxclient/client/ExchangeFilterFunctions.java
// static ExchangeFilterFunction responseInterceptorFilter(ResponseProcessor responseProcessor) {
//     return ofResponseProcessor(clientResponse -> Mono.just(responseProcessor.process(clientResponse)));
// }


// Path: src/main/java/com/webfluxclient/client/DefaultExchangeFilterFunctionFactory.java
import com.webfluxclient.LogLevel;
import com.webfluxclient.Logger;
import com.webfluxclient.RequestProcessor;
import com.webfluxclient.ResponseProcessor;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import java.util.List;
import static com.webfluxclient.client.ExchangeFilterFunctions.requestProcessorFilter;
import static com.webfluxclient.client.ExchangeFilterFunctions.responseInterceptorFilter;

package com.webfluxclient.client;




public class DefaultExchangeFilterFunctionFactory implements ExchangeFilterFunctionFactory {

    @Override
    public ExchangeFilterFunction build(List<RequestProcessor> requestProcessors, List<ResponseProcessor> responseProcessors, Logger logger, LogLevel logLevel) {
        ExchangeFilterFunction exchangeFilterFunction = null;
        if (!requestProcessors.isEmpty()) {
            RequestProcessor requestProcessor = requestProcessors.stream()
                    .reduce(RequestProcessor::andThen)
                    .orElseGet(() -> clientRequest -> clientRequest);

            exchangeFilterFunction = requestProcessorFilter(requestProcessor);
        }

        if (logger != null && logLevel != null) {
            ExchangeFilterFunction loggingExchangeFilterFunction = ExchangeFilterFunctions.loggingFilter(logger, logLevel);
            exchangeFilterFunction = exchangeFilterFunction == null?
                    loggingExchangeFilterFunction :
                    exchangeFilterFunction.andThen(loggingExchangeFilterFunction);
        }

        if (!responseProcessors.isEmpty()) {
            ResponseProcessor responseProcessor = responseProcessors.stream()
                    .reduce(ResponseProcessor::andThen)
                    .orElseGet(() -> clientResponse -> clientResponse);

            ExchangeFilterFunction responseInterceptorFilter = responseInterceptorFilter(responseProcessor);