package ru.yandex.canvas;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

import javax.annotation.Nonnull;
import javax.annotation.ParametersAreNonnullByDefault;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.util.FileCopyUtils;

@ParametersAreNonnullByDefault
public class RestTemplateLoggerInterceptor implements ClientHttpRequestInterceptor {
    public static final String LOGGER_NAME = "CANVAS_OUTGOING_REQUESTS.log";
    private final Logger logger = LoggerFactory.getLogger(LOGGER_NAME);

    public Logger getLogger() {
        return logger;
    }

    /*
     * при логировании ответ отдельрно от запроса, может не получится сматчить одно с другим
     * логирование бинариков в body
     * не логируется multiform body (в body только разделитель полей формы), заголовки могут содержать токены
     * запросы тоже могут содержать секреты, в итоге решили что правильнее логику логирования вынести на вызывающую
     * сторону. Этот класс оставить для дебага
     */
    @Override
    @Nonnull
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
            throws IOException
    {
        logRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        logResponse(response);
        return response;
    }

    private void logRequest(HttpRequest request, byte[] body) {
        if (logger.isDebugEnabled()) {
            String bodyString = new String(body, StandardCharsets.UTF_8);
            logger.debug("Request Headers: {}, Uri: {}, Method: {}, Body: {}",
                    request.getHeaders(),
                    request.getURI(),
                    request.getMethod(),
                    bodyString);
        }
    }

    /**
     *  уровень логирования ответа - debug, т.к. логировать все ответы может быть рассточительно, а в случае
     *  ошибки запроса ответ будет залогирован в DefaultResponseErrorHandler
     *  см. определение бина в {@link ru.yandex.canvas.configs.ServiceConfig}
     *  В случае если важно логировать все ответы сервиса это надо делать в коде по месту использования RestTemplate
     *
     * @param response запрос
     * @throws IOException если падает получение статуса
     */
    private void logResponse(ClientHttpResponse response) throws IOException {
        if (logger.isDebugEnabled()) {
            String responseBody = FileCopyUtils.copyToString(new InputStreamReader(response.getBody()));
            logger.debug("Response status={} body={}", HttpStatus.resolve(response.getRawStatusCode()), responseBody);
        }
    }
}
