package io.delphiplatform.api.integration.client;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.openapitools.jackson.nullable.JsonNullableModule;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.util.DefaultUriBuilderFactory;

@Lazy //needed for @LocalServerPort
@Component
public class TestAPIClient {

    @LocalServerPort
    private int port;

    private final String serverAddress = "http://localhost";

    private TestRestTemplate restTemplate;
    private HttpHeaders defaultHeaders = new HttpHeaders();

    public TestAPIClient() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.findAndRegisterModules();
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        objectMapper.registerModule(new JsonNullableModule());

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper);

        DefaultUriBuilderFactory defaultUriBuilderFactory = new DefaultUriBuilderFactory();
        defaultUriBuilderFactory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE);

        restTemplate = new TestRestTemplate();
        restTemplate.setUriTemplateHandler(defaultUriBuilderFactory);
        restTemplate.getRestTemplate().getMessageConverters().add(0, converter);
    }

    private String createURL(String uri) {
        return serverAddress + ":" + port + "/" + uri;
    }

    public <T> ResponseEntity<T> sendAPIRequest(String endpointWithParams, Class<T> responseClass) {
        return restTemplate.exchange(createURL(endpointWithParams),
            HttpMethod.GET, new HttpEntity<>(null, defaultHeaders), responseClass);
    }
}
