// 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 com.google.cloud.NoCredentials;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.Instance;
import com.google.cloud.spanner.InstanceAdminClient;
import com.google.cloud.spanner.InstanceConfigId;
import com.google.cloud.spanner.InstanceId;
import com.google.cloud.spanner.InstanceInfo;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerOptions;
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.junit.Ignore;
import org.testcontainers.containers.SpannerEmulatorContainer;
import org.testcontainers.utility.DockerImageName;

@Ignore
public class EmulatedSpannerRefDb {
  public static final String PROJECT_ID = "test";
  public static final String SPANNER_INSTANCE_ID = "spanner-instance";
  public static final String SPANNER_DATABASE_ID = "global-refdb";

  private final SpannerEmulatorContainer container;

  private final Spanner spanner;
  private final SpannerOptions spannerOptions;
  private final InstanceAdminClient instanceAdminClient;
  private final Instance spannerInstance;
  private final Database spannerDatabase;
  private final DatabaseId dbId;
  private final DatabaseClient databaseClient;
  private final ScheduledExecutorService heartbeatExecutor;
  private final SpannerRefDatabase spannerRefDb;

  public EmulatedSpannerRefDb() throws Exception {
    container =
        new SpannerEmulatorContainer(
            DockerImageName.parse("gcr.io/cloud-spanner-emulator/emulator").withTag("1.5.9"));
    container.start();
    System.out.println(
        String.format(
            "Spanner emulator container started and is listening on %s",
            container.getEmulatorGrpcEndpoint()));

    spannerOptions = getEmulatorOptions();
    spanner = spannerOptions.getService();
    instanceAdminClient = spanner.getInstanceAdminClient();
    spannerInstance = createSpannerInstance();
    dbId = DatabaseId.of(spannerOptions.getProjectId(), SPANNER_INSTANCE_ID, SPANNER_DATABASE_ID);
    spannerDatabase =
        spannerInstance.createDatabase(SPANNER_DATABASE_ID, Collections.emptyList()).get();
    createSchema();
    databaseClient = createDatabaseClient();
    heartbeatExecutor = Executors.newScheduledThreadPool(2);
    Lock.Factory lockFactory =
        new Lock.Factory() {
          @Override
          public Lock create(String projectName, String refName) {
            return new Lock(databaseClient, "", heartbeatExecutor, projectName, refName);
          }
        };
    spannerRefDb = new SpannerRefDatabase(databaseClient, lockFactory);
  }

  private void createSchema() {
    SpannerLifeCycleManager lcm = new SpannerLifeCycleManager(spannerOptions, dbId);
    lcm.start();
  }

  public void cleanup() {
    heartbeatExecutor.shutdownNow();
    try {
      heartbeatExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
      throw new RuntimeException(e);
    }
    spannerDatabase.drop();
    instanceAdminClient.deleteInstance(SPANNER_INSTANCE_ID);
    spanner.close();
    container.stop();
    container.close();
    System.out.println("Spanner emulator container was stopped");
  }

  public SpannerEmulatorContainer getContainer() {
    return container;
  }

  public Database getSpannerDatabase() {
    return spannerDatabase;
  }

  public SpannerRefDatabase getSpannerRefDatabase() {
    return spannerRefDb;
  }

  private SpannerOptions getEmulatorOptions() {
    return SpannerOptions.newBuilder()
        .setEmulatorHost(container.getEmulatorGrpcEndpoint())
        .setCredentials(NoCredentials.getInstance())
        .setProjectId(PROJECT_ID)
        .build();
  }

  private Instance createSpannerInstance() throws InterruptedException, ExecutionException {
    InstanceConfigId instanceConfig = InstanceConfigId.of(PROJECT_ID, "emulator-config");
    InstanceId instanceId = InstanceId.of(PROJECT_ID, SPANNER_INSTANCE_ID);
    InstanceInfo instanceInfo =
        InstanceInfo.newBuilder(instanceId)
            .setInstanceConfigId(instanceConfig)
            .setNodeCount(1)
            .setDisplayName("test instance")
            .build();
    return instanceAdminClient.createInstance(instanceInfo).get();
  }

  private DatabaseClient createDatabaseClient() {
    return spannerOptions.getService().getDatabaseClient(dbId);
  }
}
