// 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.googlesource.gerrit.plugins.spannerrefdb.Configuration.DATABASE_KEY;
import static com.googlesource.gerrit.plugins.spannerrefdb.Configuration.EMULATOR_KEY;
import static com.googlesource.gerrit.plugins.spannerrefdb.Configuration.INSTANCE_KEY;
import static com.googlesource.gerrit.plugins.spannerrefdb.Configuration.SECTION;
import static com.googlesource.gerrit.plugins.spannerrefdb.Configuration.SUBSECTION;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.cloud.NoCredentials;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.DatabaseAdminClient;
import com.google.cloud.spanner.DatabaseClient;
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 com.google.gerrit.server.config.PluginConfigFactory;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.Collections;
import java.util.concurrent.ExecutionException;
import org.eclipse.jgit.lib.Config;
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 static final String pluginName = "spanner-refdb";

  private final SpannerEmulatorContainer container;

  private final Spanner spanner;
  private final InstanceAdminClient instanceAdminClient;
  private final Instance spannerInstance;
  private final Database spannerDatabase;
  private final DatabaseClient databaseClient;
  private final SpannerRefDatabase spannerRefDb;
  private final Configuration pluginConfig;

  @Inject
  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()));

    spanner = getEmulatorOptions().getService();
    instanceAdminClient = spanner.getInstanceAdminClient();
    spannerInstance = createSpannerInstance();
    spannerDatabase =
        spannerInstance.createDatabase(SPANNER_DATABASE_ID, Collections.emptyList()).get();
    pluginConfig = createEmulatorConfiguration();
    createSchema();
    databaseClient = createDatabaseClient();
    Lock.LockFactory lockFactory =
        new Lock.LockFactory() {
          @Override
          public Lock create(String projectName, String refName) {
            return new Lock(databaseClient, "", projectName, refName);
          }
        };
    spannerRefDb = new SpannerRefDatabase(databaseClient, lockFactory);
  }

  private void createSchema() {
    DatabaseAdminClient dbAdminClient = spanner.getDatabaseAdminClient();
    SpannerLifeCycleManager lcm = new SpannerLifeCycleManager(pluginConfig, dbAdminClient);
    lcm.start();
  }

  public void cleanup() {
    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 createDatabaseClient(pluginConfig);
  }

  private Configuration createEmulatorConfiguration() throws IOException {
    Config refDbConfig = new Config();
    refDbConfig.setString(SECTION, SUBSECTION, INSTANCE_KEY, SPANNER_INSTANCE_ID);
    refDbConfig.setString(SECTION, SUBSECTION, DATABASE_KEY, SPANNER_DATABASE_ID);
    refDbConfig.setBoolean(SECTION, SUBSECTION, EMULATOR_KEY, true);

    PluginConfigFactory cfgFactory = mock(PluginConfigFactory.class);
    when(cfgFactory.getGlobalPluginConfig(pluginName)).thenReturn(refDbConfig);
    Configuration spannerConfig = new Configuration(cfgFactory, pluginName);
    spannerConfig.setOptions(getEmulatorOptions());
    return spannerConfig;
  }

  private DatabaseClient createDatabaseClient(Configuration configuration) {
    return configuration.getOptions().getService().getDatabaseClient(configuration.getDatabaseId());
  }
}
