// Copyright (C) 2021 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.Configuration.DEFAULT_LOCKS_TABLE_NAME;
import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.Configuration.DEFAULT_REFS_DB_TABLE_NAME;
import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.DynamoDBRefDatabase.REF_DB_PRIMARY_KEY;
import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.DynamoDBRefDatabase.REF_DB_VALUE_KEY;
import static com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.DynamoDBRefDatabase.pathFor;
import static org.testcontainers.containers.localstack.LocalStackContainer.Service.DYNAMODB;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.acceptance.WaitUtil;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Project;
import java.time.Duration;
import java.util.Optional;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.junit.Before;
import org.junit.Test;
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.utility.DockerImageName;

@TestPlugin(
    name = "aws-dynamodb-refdb",
    sysModule = "com.googlesource.gerrit.plugins.validation.dfsrefdb.dynamodb.Module")
public class DynamoDBRefDatabaseIT extends LightweightPluginDaemonTest {
  private static final Duration DYNAMODB_TABLE_CREATION_TIMEOUT = Duration.ofSeconds(10);

  private static final int LOCALSTACK_PORT = 4566;
  private static final LocalStackContainer localstack =
      new LocalStackContainer(DockerImageName.parse("localstack/localstack:0.12.8"))
          .withServices(DYNAMODB)
          .withExposedPorts(LOCALSTACK_PORT);

  @Before
  public void setUpTestPlugin() throws Exception {
    localstack.start();

    System.setProperty("endpoint", localstack.getEndpointOverride(DYNAMODB).toASCIIString());
    System.setProperty("region", localstack.getRegion());
    System.setProperty("aws.accessKeyId", localstack.getAccessKey());

    // The secret key property name has changed from aws-sdk 1.11.x and 2.x [1]
    // Export both names so that default credential provider chains work regardless
    // he underlying library version.
    // https: // docs.aws.amazon.com/sdk-for-java/latest/migration-guide/client-credential.html
    System.setProperty("aws.secretKey", localstack.getSecretKey());
    System.setProperty("aws.secretAccessKey", localstack.getSecretKey());

    super.setUpTestPlugin();
  }

  @Override
  public void tearDownTestPlugin() {
    localstack.close();

    super.tearDownTestPlugin();
  }

  @Test
  public void shouldEnsureLockTableExists() throws Exception {
    WaitUtil.waitUntil(
        () -> DynamoDBLifeCycleManager.tableExists(dynamoDBClient(), DEFAULT_LOCKS_TABLE_NAME),
        DYNAMODB_TABLE_CREATION_TIMEOUT);
  }

  @Test
  public void shouldEnsureRefsDbTableExists() throws Exception {
    WaitUtil.waitUntil(
        () -> DynamoDBLifeCycleManager.tableExists(dynamoDBClient(), DEFAULT_REFS_DB_TABLE_NAME),
        DYNAMODB_TABLE_CREATION_TIMEOUT);
  }

  @Test
  public void getShouldBeEmptyWhenRefDoesntExists() throws Exception {
    Optional<String> maybeRef = dynamoDBRefDatabase().get(project, "refs/not/in/db", String.class);

    assertThat(maybeRef).isEmpty();
  }

  @Test
  public void getShouldReturnRefValueWhenItExists() throws Exception {
    String refName = "refs/changes/01/01/meta";
    String refValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";
    createRefInDynamoDB(project, refName, refValue);

    Optional<String> maybeRef = dynamoDBRefDatabase().get(project, refName, String.class);

    assertThat(maybeRef).hasValue(refValue);
  }

  @Test
  public void existsShouldReturnFalseWhenRefIsNotStored() throws Exception {
    assertThat(dynamoDBRefDatabase().exists(project, "refs/not/in/db")).isFalse();
  }

  @Test
  public void existShouldReturnTrueWhenRefIsStored() throws Exception {
    String refName = "refs/changes/01/01/meta";
    String refValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";
    createRefInDynamoDB(project, refName, refValue);

    assertThat(dynamoDBRefDatabase().exists(project, refName)).isTrue();
  }

  @Test
  public void isUpToDateShouldReturnTrueWhenRefPointsToTheStoredRefValue() throws Exception {
    String refName = "refs/changes/01/01/meta";
    String currentRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";

    createRefInDynamoDB(project, refName, currentRefValue);

    assertThat(dynamoDBRefDatabase().isUpToDate(project, refOf(refName, currentRefValue))).isTrue();
  }

  @Test
  public void isUpToDateShouldReturnFalseWhenRefDoesNotPointToTheStoredRefValue() {
    String refName = "refs/changes/01/01/meta";
    String currentRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";
    String previousRefValue = "9f6f2963cf44505428c61b935ff1ca65372cf28c";

    createRefInDynamoDB(project, refName, previousRefValue);

    assertThat(dynamoDBRefDatabase().isUpToDate(project, refOf(refName, currentRefValue)))
        .isFalse();
  }

  @Test
  public void isUpToDateShouldBeConsideredTrueWhenNoPreviousRefExists() {
    String refName = "refs/changes/01/01/meta";
    String currentRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";

    assertThat(dynamoDBRefDatabase().isUpToDate(project, refOf(refName, currentRefValue))).isTrue();
  }

  @Test
  public void compareAndPutShouldBeSuccessfulWhenNoPreviousRefExists() {
    String refName = "refs/changes/01/01/meta";
    String newRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";

    assertThat(
            dynamoDBRefDatabase()
                .compareAndPut(project, refOf(refName, null), ObjectId.fromString(newRefValue)))
        .isTrue();
  }

  @Test
  public void compareAndPutShouldSuccessfullyUpdateRemovedRef() throws Exception {
    String refName = "refs/changes/01/01/meta";
    String currentRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";

    createRefInDynamoDB(project, refName, currentRefValue);

    assertThat(
            dynamoDBRefDatabase()
                .compareAndPut(project, refOf(refName, currentRefValue), ObjectId.zeroId()))
        .isTrue();
  }

  @Test
  public void compareAndPutShouldThrowWhenStoredRefIsNotExpected() {
    String refName = "refs/changes/01/01/meta";
    String currentRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";
    String newRefValue = "9f6f2963cf44505428c61b935ff1ca65372cf28c";
    String expectedRefValue = "875ce4b14278b64be61478f91a40cf480758bfba";
    Ref expectedRef = refOf(refName, expectedRefValue);

    createRefInDynamoDB(project, refName, currentRefValue);

    GlobalRefDbSystemError thrown =
        assertThrows(
            GlobalRefDbSystemError.class,
            () ->
                dynamoDBRefDatabase()
                    .compareAndPut(project, expectedRef, ObjectId.fromString(newRefValue)));
    assertThat(thrown)
        .hasMessageThat()
        .containsMatch(
            "Conditional Check Failure when updating refPath.*expected:.*"
                + expectedRefValue
                + " New:.*"
                + newRefValue);
  }

  @Test
  public void compareAndPutStringsShouldBeSuccessful() throws Exception {
    String refName = "refs/changes/01/01/meta";
    String currentRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";
    String newRefValue = "9f6f2963cf44505428c61b935ff1ca65372cf28c";

    createRefInDynamoDB(project, refName, currentRefValue);

    assertThat(dynamoDBRefDatabase().compareAndPut(project, refName, currentRefValue, newRefValue))
        .isTrue();
  }

  @Test
  public void compareAndPutStringsShouldBeSuccessfulWhenNoPreviousRefExists() {
    String refName = "refs/changes/01/01/meta";
    String newRefValue = "533d3ccf8a650fb26380faa732921a2c74924d5c";

    assertThat(dynamoDBRefDatabase().compareAndPut(project, refName, null, newRefValue)).isTrue();
  }

  private AmazonDynamoDB dynamoDBClient() {
    return plugin.getSysInjector().getInstance(AmazonDynamoDB.class);
  }

  private DynamoDBRefDatabase dynamoDBRefDatabase() {
    return plugin.getSysInjector().getInstance(DynamoDBRefDatabase.class);
  }

  private void createRefInDynamoDB(Project.NameKey project, String refPath, String refValue) {
    dynamoDBClient()
        .putItem(
            new PutItemRequest()
                .withTableName(DEFAULT_REFS_DB_TABLE_NAME)
                .withItem(
                    ImmutableMap.of(
                        REF_DB_PRIMARY_KEY,
                        new AttributeValue(pathFor(project, refPath)),
                        REF_DB_VALUE_KEY,
                        new AttributeValue(refValue))));
  }

  private Ref refOf(String refName, @Nullable String objectIdSha1) {
    return new ObjectIdRef.Unpeeled(
        Ref.Storage.NETWORK,
        refName,
        Optional.ofNullable(objectIdSha1).map(ObjectId::fromString).orElse(null));
  }
}
