// 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.http.rest.PagedIterable;
import com.azure.core.http.rest.RequestOptions;
import com.azure.core.http.rest.Response;
import com.azure.core.util.BinaryData;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

@Isolated("There is an assumption in post ledger entries that checks it is latest entry.")
public final class LedgerEntriesTest extends ConfidentialLedgerClientTestBase {
    @Test
    public void testPostLedgerEntryTests() throws Exception {
        // Arrange
        RequestOptions requestOptions = new RequestOptions();
        String transactionId = postLedgerEntry();

        Response<BinaryData> transactionResponse = confidentialLedgerClient.getTransactionStatusWithResponse(transactionId, requestOptions);

        JsonNode transactionResponseBodyJson = OBJECT_MAPPER.readTree(transactionResponse.getValue().toBytes());

        assertEquals(transactionResponseBodyJson.get(TRANSACTION_ID).asText(), transactionId);

        int statusCode = transactionResponse.getStatusCode();
        assertTrue(200 == statusCode || 406 == statusCode, "Expected 200, or 206. Actual: " + statusCode);

        // Act
        Response<BinaryData> currentResponse = confidentialLedgerClient.getCurrentLedgerEntryWithResponse(requestOptions);

        // Assert
        JsonNode currentResponseBodyJson = OBJECT_MAPPER.readTree(currentResponse.getValue().toBytes());

        assertTrue(200 == currentResponse.getStatusCode() || 406 == currentResponse.getStatusCode());

        if (200 == currentResponse.getStatusCode()) {
            // we assume no one has created an entry since we created this entry.
            assertTrue(currentResponseBodyJson.get(TRANSACTION_ID).asDouble() <= Double.parseDouble(transactionId));
        }
    }

    @Test
    public void testGetCollectionIdsTests() throws Exception {
        postLedgerEntry();

        RequestOptions requestOptions = new RequestOptions();
        PagedIterable<BinaryData> pagedIterableResponse = confidentialLedgerClient.listCollections(requestOptions);

        List<String> collectionKeys = new ArrayList<>();

        pagedIterableResponse.streamByPage().forEach(resp -> {
            assertEquals(200, resp.getStatusCode());
            resp.getValue().forEach(item -> {
                ObjectMapper objectMapper = new ObjectMapper();
                JsonNode responseBodyJson = null;

                try {
                    responseBodyJson = objectMapper.readTree(item.toBytes());
                } catch (IOException e) {
                    e.printStackTrace();
                    assertTrue(false);
                }

                Assertions.assertNotNull(responseBodyJson.get(COLLECTION_ID));
                collectionKeys.add(responseBodyJson.get(COLLECTION_ID).asText());
            });

            boolean exists = collectionKeys.stream().anyMatch((item) -> item.contains("subledger:0"));
            assertTrue(exists, "Did not find matching collection.");
        });
    }
}

