// Copyright (C) 2023 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.spannerrefdb;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;

import com.gerritforge.gerrit.globalrefdb.GlobalRefDbLockException;
import com.google.cloud.Timestamp;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.Key;
import com.google.cloud.spanner.Mutation;
import com.google.cloud.spanner.Struct;
import com.google.gerrit.entities.Project;
import java.util.Arrays;
import java.util.Collections;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class LockTest implements RefFixture {
  private SpannerTestSystem testSystem;
  private SpannerRefDatabase refDb;
  private DatabaseClient dbClient;

  private String TOKEN = "token";
  private String HEARTBEAT = "heartbeat";

  @Before
  public void setUp() throws Exception {
    testSystem = SpannerTestSystem.create();
    refDb = testSystem.database();
    dbClient = testSystem.dbClient();
  }

  @After
  public void tearDown() {
    testSystem.cleanup();
  }

  @Test
  public void lockUnlockedRef_Success() throws Exception {
    try (AutoCloseable refLock = refDb.lockRef(PROJECT_NAME_KEY, REF_NAME)) {
      assertThat(getLockTimestamp(PROJECT_NAME_KEY, REF_NAME, TOKEN)).isNotNull();

      Timestamp heartbeat = getLockTimestamp(PROJECT_NAME_KEY, REF_NAME, HEARTBEAT);
      try {
        Thread.sleep(4_000);
      } catch (InterruptedException ie) {
        Thread.currentThread().interrupt();
      }
      assertThat(getLockTimestamp(PROJECT_NAME_KEY, REF_NAME, HEARTBEAT).compareTo(heartbeat))
          .isGreaterThan(0);
    }

    assertThat(getLockRow(PROJECT_NAME_KEY, REF_NAME)).isNull();
  }

  @Test
  public void lockAlreadyLockedRef_Rejected() throws Exception {
    try (AutoCloseable refLock = refDb.lockRef(PROJECT_NAME_KEY, REF_NAME)) {
      GlobalRefDbLockException e =
          assertThrows(
              GlobalRefDbLockException.class, () -> refDb.lockRef(PROJECT_NAME_KEY, REF_NAME));
      assertThat(e)
          .hasMessageThat()
          .contains(
              String.format("Unable to lock ref %s on project %s", REF_NAME, PROJECT_NAME_KEY));
    }
  }

  @Test
  public void lockReleasedRef_Success() throws Exception {
    Timestamp lockToken;
    try (AutoCloseable refLock = refDb.lockRef(PROJECT_NAME_KEY, REF_NAME)) {
      lockToken = getLockTimestamp(PROJECT_NAME_KEY, REF_NAME, TOKEN);
    }

    try (AutoCloseable refLock = refDb.lockRef(PROJECT_NAME_KEY, REF_NAME)) {
      Timestamp newLockToken = getLockTimestamp(PROJECT_NAME_KEY, REF_NAME, TOKEN);
      assertThat(lockToken).isNotEqualTo(newLockToken);
    }
  }

  @Test
  public void reclaimStaleLockedRef_Success() throws Exception {
    Timestamp staleTimestamp = Timestamp.ofTimeSecondsAndNanos(0, 0);
    insertLockRow(staleTimestamp);
    try (AutoCloseable refLock = refDb.lockRef(PROJECT_NAME_KEY, REF_NAME)) {
      Timestamp newLockToken = getLockTimestamp(PROJECT_NAME_KEY, REF_NAME, TOKEN);
      assertThat(newLockToken).isNotNull();
      assertThat(staleTimestamp.compareTo(newLockToken)).isLessThan(0);
    }
  }

  @Test
  public void reclaimFreshLockedRef_Rejected() throws Exception {
    Timestamp freshTimestamp = Timestamp.now();
    insertLockRow(freshTimestamp);
    GlobalRefDbLockException e =
        assertThrows(
            GlobalRefDbLockException.class, () -> refDb.lockRef(PROJECT_NAME_KEY, REF_NAME));
    assertThat(e)
        .hasMessageThat()
        .contains(String.format("Unable to lock ref %s on project %s", REF_NAME, PROJECT_NAME_KEY));
  }

  private Timestamp getLockTimestamp(Project.NameKey project, String refName, String column) {
    Struct row = getLockRow(project, refName);
    return row != null ? row.getTimestamp(column) : null;
  }

  private Struct getLockRow(Project.NameKey project, String refName) {
    return dbClient
        .singleUse()
        .readRow("locks", Key.of(project.get(), refName), Arrays.asList(TOKEN, HEARTBEAT));
  }

  private void insertLockRow(Timestamp timestamp) {
    Mutation staleLock =
        Mutation.newInsertBuilder("locks")
            .set("project")
            .to(PROJECT_NAME_KEY.get())
            .set("ref")
            .to(REF_NAME)
            .set("heartbeat")
            .to(timestamp)
            .set("token")
            .to(timestamp)
            .set("owner")
            .to("")
            .build();
    dbClient.write(Collections.singletonList(staleLock));
  }
}
