package io.delphiplatform.api.bigtable;


import com.google.api.gax.retrying.RetrySettings;
import com.google.cloud.bigtable.data.v2.BigtableDataClient;
import com.google.cloud.bigtable.data.v2.BigtableDataSettings;
import com.google.cloud.bigtable.data.v2.BigtableDataSettings.Builder;
import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.threeten.bp.Duration;

import java.io.IOException;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
@ConditionalOnProperty(name="integration.tests.enable", havingValue = "false", matchIfMissing = true)
public class BigTableClientConfiguration {

    @Value("${delphi.bigtable.project-id}")
    private String projectId;
    @Value("${delphi.bigtable.instance-id}")
    private String instanceId;
    @Value("${delphi.bigtable.application-profile-id}")
    private String appProfileId;
    @Value("${delphi.bigtable.timeout}")
    private int timeoutMilliseconds;
    @Value("${delphi.bigtable.initial_rpc_timeout}")
    private int initialRpcTimeout;
    @Value("${delphi.bigtable.max_rpc_timeout}")
    private int maxRpcTimeout;
    @Value("${delphi.bigtable.rpc_timeout_multiplier}")
    private double rpcTimeoutMultiplier;

    @Bean
    public BigtableDataClient dataClient() {
        try {
            Builder settingsBuilder = BigtableDataSettings.newBuilder()
                .setAppProfileId(appProfileId)
                .setProjectId(projectId)
                .setInstanceId(instanceId);

            if (timeoutMilliseconds >= 0) {
                Duration timeout = Duration.ofMillis(timeoutMilliseconds);
                EnhancedBigtableStubSettings.Builder stubSettings = settingsBuilder.stubSettings();

                RetrySettings readRowRetrySettings = stubSettings
                    .readRowSettings()
                    .getRetrySettings()
                    .toBuilder()
                    .setTotalTimeout(timeout)
                    .setInitialRpcTimeout(Duration.ofMillis(initialRpcTimeout))
                    .setMaxRpcTimeout(Duration.ofMillis(maxRpcTimeout))
                    .setRpcTimeoutMultiplier(rpcTimeoutMultiplier)
                    .build();

                RetrySettings readRowsRetrySettings = stubSettings
                    .readRowsSettings()
                    .getRetrySettings()
                    .toBuilder().setTotalTimeout(timeout)
                    .setInitialRpcTimeout(Duration.ofMillis(initialRpcTimeout))
                    .setMaxRpcTimeout(Duration.ofMillis(maxRpcTimeout))
                    .setRpcTimeoutMultiplier(rpcTimeoutMultiplier)
                    .build();

                stubSettings.readRowsSettings().setRetrySettings(readRowRetrySettings);
                stubSettings.readRowSettings().setRetrySettings(readRowsRetrySettings);
            }

            return BigtableDataClient.create(settingsBuilder.build());
        } catch (IOException e) {
            log.error("Failed to create BigTable data client.", e);
            throw new IllegalStateException("Cannot initialize BigTable client", e);
        }
    }

}
