// 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.auth.oauth2.GoogleCredentials;
import com.google.cloud.spanner.Database;
import com.google.cloud.spanner.DatabaseAdminClient;
import com.google.cloud.spanner.DatabaseClient;
import com.google.cloud.spanner.DatabaseId;
import com.google.cloud.spanner.KeySet;
import com.google.cloud.spanner.Mutation;
import com.google.cloud.spanner.SpannerOptions;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class RealSpannerRefDb extends SpannerTestSystem {

  private static RealSpannerRefDb INSTANCE;

  public static RealSpannerRefDb create() {
    if (INSTANCE == null) {
      String keyPath = System.getenv("GOOGLE_APPLICATION_CREDENTIALS");
      String instance = System.getenv("SPANNER_INSTANCE");
      INSTANCE = new RealSpannerRefDb(keyPath, instance);
    }
    return INSTANCE;
  }

  private final String keyPath;
  private final String instance;
  private final String dbName;

  private boolean dbInitialized;
  private SpannerRefDatabase refdb;
  private DatabaseClient dbClient;

  private RealSpannerRefDb(String keyPath, String instance) {
    this.keyPath = keyPath;
    this.instance = instance;
    this.dbName = "global-refdb-" + System.currentTimeMillis();
  }

  @Override
  public void reset() throws Exception {
    if (!dbInitialized) {
      initialize();
      dbInitialized = true;
    } else {
      deleteAllData();
    }
  }

  @Override
  SpannerRefDatabase database() {
    return refdb;
  }

  @Override
  DatabaseClient dbClient() {
    return dbClient;
  }

  @Override
  void cleanup() {
    // do nothing
  }

  private void initialize() throws Exception {
    GoogleCredentials credentials = GoogleCredentials.fromStream(new FileInputStream(keyPath));

    SpannerOptions options = SpannerOptions.newBuilder().setCredentials(credentials).build();
    DatabaseId dbId = DatabaseId.of(options.getProjectId(), instance, dbName);
    DatabaseAdminClient dbAdminClient = options.getService().getDatabaseAdminClient();

    // create empty database
    Database database =
        dbAdminClient
            .createDatabase(dbId.getInstanceId().getInstance(), dbId.getDatabase(), List.of())
            .get();

    DatabaseSchemaCreator databaseSchemaCreator = new DatabaseSchemaCreator(dbAdminClient, dbId);
    databaseSchemaCreator.start();
    dbClient = options.getService().getDatabaseClient(dbId);
    ScheduledExecutorService heartbeatExecutor = Executors.newScheduledThreadPool(2);
    Lock.Factory lockFactory =
        new Lock.Factory() {
          @Override
          public Lock create(String projectName, String refName) {
            return new Lock(dbClient, "", heartbeatExecutor, projectName, refName);
          }
        };
    refdb = new SpannerRefDatabase(dbClient, lockFactory);

    // schedule heartbeat stop and database drop when JVM gets shutdown
    Runtime.getRuntime()
        .addShutdownHook(
            new Thread(
                () -> {
                  heartbeatExecutor.shutdownNow();
                  try {
                    heartbeatExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
                  } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                  }
                  database.drop();
                }));
  }

  private void deleteAllData() {
    List<Mutation> mutations = new ArrayList<>();
    mutations.add(Mutation.delete("refs", KeySet.all()));
    mutations.add(Mutation.delete("locks", KeySet.all()));
    dbClient.write(mutations);
  }
}
