// 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.ScheduledThreadPoolExecutor;
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 ScheduledThreadPoolExecutor heartbeatExecutor;

  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
  ScheduledThreadPoolExecutor heartbeatExecutor() {
    return heartbeatExecutor;
  }

  @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);
    heartbeatExecutor = new ScheduledThreadPoolExecutor(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);
  }
}
