// 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.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.util.Collections;
import java.util.concurrent.ExecutionException;
import org.eclipse.jgit.lib.Config;
import org.junit.Ignore;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;

@Ignore
public class SpannerEmulatorContainer {
  public static class Container extends GenericContainer<Container> {
    public static String EMULATOR_VERSION = "1.5.7";

    public Container() {
      super("gcr.io/cloud-spanner-emulator/emulator:" + EMULATOR_VERSION);
    }
  }

  public static final String PROJECT_ID = "test";
  public static final String SPANNER_INSTANCE_ID = "instance";
  public static final String SPANNER_DATABASE_ID = "refdb";
  private static final int GRPC_PORT = 9010;
  private static final int REST_PORT = 9020;
  private static final String pluginName = "spanner-refdb";

  private final Container container;
  private final Integer grpcPort;
  private final Integer restPort;

  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
  @SuppressWarnings("resource")
  public SpannerEmulatorContainer() throws Exception {
    container =
        new Container().withExposedPorts(GRPC_PORT, REST_PORT).waitingFor(Wait.forListeningPort());
    container.start();
    grpcPort = container.getMappedPort(GRPC_PORT);
    restPort = container.getMappedPort(REST_PORT);
    System.out.println(
        "Spanner emulator container started and is listening on ports "
            + grpcPort
            + ", "
            + restPort);

    spanner = getEmulatorOptions().getService();
    instanceAdminClient = spanner.getInstanceAdminClient();
    spannerInstance = createSpannerInstance();
    spannerDatabase =
        spannerInstance.createDatabase(SPANNER_DATABASE_ID, Collections.emptyList()).get();
    pluginConfig = createEmulatorConfiguration();
    createSchema();
    databaseClient = createDatabaseClient();
    spannerRefDb = new SpannerRefDatabase(databaseClient);
  }

  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 Container getContainer() {
    return container;
  }

  public Integer getGrpcPort() {
    return grpcPort;
  }

  public Integer getRestPort() {
    return restPort;
  }

  public Database getSpannerDatabase() {
    return spannerDatabase;
  }

  public SpannerRefDatabase getSpannerRefDatabase() {
    return spannerRefDb;
  }

  private SpannerOptions getEmulatorOptions() {
    return SpannerOptions.newBuilder()
        .setEmulatorHost("localhost:" + getGrpcPort())
        .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() {
    Config refDbConfig = new Config();
    refDbConfig.setString(SECTION, SUBSECTION, INSTANCE_KEY, SPANNER_INSTANCE_ID);
    refDbConfig.setString(SECTION, SUBSECTION, DATABASE_KEY, SPANNER_DATABASE_ID);

    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());
  }
}
