package at.procon.dip.clustering.client;

import at.procon.dip.clustering.config.ClusteringPhaseBProperties;
import at.procon.dip.clustering.dto.PythonClusteringRequest;
import at.procon.dip.clustering.dto.PythonClusteringResponse;
import at.procon.dip.clustering.dto.PythonRunExecutionRequest;
import java.net.http.HttpClient;
import java.time.Duration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.MediaType;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClient;
import org.springframework.web.server.ResponseStatusException;

@Component
@ConditionalOnProperty(prefix = "dip.clustering.python", name = "enabled", havingValue = "true")
public class RestPythonClusteringClient implements PythonClusteringClient {

    private static final Duration DEFAULT_CONNECT_TIMEOUT = Duration.ofSeconds(30);
    private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofMinutes(30);

    private final ClusteringPhaseBProperties properties;
    private final RestClient restClient;

    public RestPythonClusteringClient(ClusteringPhaseBProperties properties) {
        this.properties = properties;

        Duration connectTimeout = properties.connectTimeout() != null
                ? properties.connectTimeout()
                : DEFAULT_CONNECT_TIMEOUT;
        Duration readTimeout = properties.readTimeout() != null
                ? properties.readTimeout()
                : DEFAULT_READ_TIMEOUT;

        HttpClient httpClient = HttpClient.newBuilder()
                .connectTimeout(connectTimeout)
                .version(HttpClient.Version.HTTP_1_1)
                .build();

        JdkClientHttpRequestFactory requestFactory = new JdkClientHttpRequestFactory(httpClient);
        requestFactory.setReadTimeout(readTimeout);

        this.restClient = RestClient.builder()
                .requestFactory(requestFactory)
                .build();
    }

    @Override
    public PythonClusteringResponse cluster(PythonClusteringRequest request) {
        String url = properties.resolvedClusterUrl();
        if (url == null || url.isBlank()) {
            throw new ResponseStatusException(org.springframework.http.HttpStatus.BAD_REQUEST,
                    "Python clustering is enabled but no baseUrl/clusterPath is configured");
        }

        try {
            return restClient.post()
                    .uri(url)
                    .contentType(MediaType.APPLICATION_JSON)
                    .accept(MediaType.APPLICATION_JSON)
                    .body(request)
                    .retrieve()
                    .body(PythonClusteringResponse.class);
        } catch (Exception ex) {
            throw new ResponseStatusException(
                    org.springframework.http.HttpStatus.BAD_GATEWAY,
                    "Python cluster request failed: " + ex.getMessage(),
                    ex);
        }
    }

    @Override
    public PythonClusteringResponse clusterRun(PythonRunExecutionRequest request) {
        String url = properties.resolvedClusterRunUrl();
        if (url == null || url.isBlank()) {
            throw new ResponseStatusException(org.springframework.http.HttpStatus.BAD_REQUEST,
                    "Python clustering is enabled but no baseUrl/clusterRunPath is configured");
        }

        try {
            return restClient.post()
                    .uri(url)
                    .contentType(MediaType.APPLICATION_JSON)
                    .accept(MediaType.APPLICATION_JSON)
                    .body(request)
                    .retrieve()
                    .body(PythonClusteringResponse.class);
        } catch (Exception ex) {
            throw new ResponseStatusException(
                    org.springframework.http.HttpStatus.BAD_GATEWAY,
                    "Python cluster-run request failed: " + ex.getMessage(),
                    ex);
        }
    }
}
