// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
// Code generated by Microsoft (R) AutoRest Code Generator.

package com.azure.security.confidentialledger;

import com.azure.core.credential.AccessToken;
import com.azure.core.http.HttpClient;
import com.azure.core.http.netty.NettyAsyncHttpClientBuilder;
import com.azure.core.http.policy.HttpLogDetailLevel;
import com.azure.core.http.policy.HttpLogOptions;
import com.azure.core.http.rest.Response;
import com.azure.core.test.TestBase;
import com.azure.core.test.TestMode;
import com.azure.core.util.BinaryData;
import com.azure.core.util.Configuration;
import com.azure.identity.DefaultAzureCredentialBuilder;
import com.azure.security.confidentialledger.certificate.ConfidentialLedgerCertificateClient;
import com.azure.security.confidentialledger.certificate.ConfidentialLedgerCertificateClientBuilder;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import reactor.core.publisher.Mono;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;

import javax.net.ssl.SSLException;

import org.junit.jupiter.api.Assertions;

class ConfidentialLedgerClientTestBase extends TestBase {
    protected ConfidentialLedgerClient confidentialLedgerClient;
    protected ConfidentialLedgerClientBuilder confidentialLedgerClientBuilder;
    protected ConfidentialLedgerCertificateClient confidentialLedgerCertificateClient;

    @Override
    protected void beforeTest() {
        ConfidentialLedgerCertificateClientBuilder confidentialLedgerCertificateClientBuilder = new ConfidentialLedgerCertificateClientBuilder()
            .certificateEndpoint("https://identity.confidential-ledger.core.azure.com")
            .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BASIC));

        if (getTestMode() == TestMode.PLAYBACK) {
            confidentialLedgerCertificateClientBuilder
                .httpClient(interceptorManager.getPlaybackClient())
                .credential(request -> Mono.just(new AccessToken("this_is_a_token", OffsetDateTime.MAX)));
        } else if (getTestMode() == TestMode.RECORD) {
            confidentialLedgerCertificateClientBuilder
                .addPolicy(interceptorManager.getRecordPolicy())
                .credential(new DefaultAzureCredentialBuilder().build());
        } else if (getTestMode() == TestMode.LIVE) {
            confidentialLedgerCertificateClientBuilder.credential(new DefaultAzureCredentialBuilder().build());
        }

        confidentialLedgerCertificateClient = confidentialLedgerCertificateClientBuilder.buildClient();

        String ledgerName = Configuration.getGlobalConfiguration().get("LEDGER_NAME", "java-sdk-live-tests-ledger");

        Response<BinaryData> ledgerIdentityWithResponse = confidentialLedgerCertificateClient
            .getLedgerIdentityWithResponse(ledgerName, null);
        BinaryData identityResponse = ledgerIdentityWithResponse.getValue();
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode = null;
        try {
            jsonNode = mapper.readTree(identityResponse.toBytes());
        } catch (IOException ex) {
            System.out.println("Caught IO exception " + ex);
            Assertions.fail();
        }

        String ledgerTlsCertificate = jsonNode.get("ledgerTlsCertificate").asText();

        reactor.netty.http.client.HttpClient reactorClient = null;

        try {
            SslContext sslContext = SslContextBuilder.forClient()
                .trustManager(new ByteArrayInputStream(
                    ledgerTlsCertificate.getBytes(StandardCharsets.UTF_8)))
                .build();
            reactorClient = reactor.netty.http.client.HttpClient.create()
                .secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
        } catch (SSLException ex) {
            System.out.println("Caught SSL exception " + ex);
            Assertions.fail();
        }

        HttpClient httpClient = new NettyAsyncHttpClientBuilder(reactorClient).wiretap(true).build();

        confidentialLedgerClientBuilder = new ConfidentialLedgerClientBuilder()
            .ledgerEndpoint(Configuration.getGlobalConfiguration().get("LEDGER_URI", "https://java-sdk-live-tests-ledger.confidential-ledger.azure.com"))
            .httpLogOptions(new HttpLogOptions().setLogLevel(HttpLogDetailLevel.BASIC));

        if (getTestMode() == TestMode.PLAYBACK) {
            confidentialLedgerClientBuilder
                .httpClient(interceptorManager.getPlaybackClient())
                .credential(request -> Mono.just(new AccessToken("this_is_a_token", OffsetDateTime.MAX)));
        } else if (getTestMode() == TestMode.RECORD) {
            confidentialLedgerClientBuilder
                .addPolicy(interceptorManager.getRecordPolicy())
                .httpClient(httpClient)
                .credential(new DefaultAzureCredentialBuilder().build());
        } else if (getTestMode() == TestMode.LIVE) {
            confidentialLedgerClientBuilder
                .credential(new DefaultAzureCredentialBuilder().build())
                .httpClient(httpClient);
        }
        confidentialLedgerClient = confidentialLedgerClientBuilder.buildClient();
    }

}
