// 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.api.client.util.Strings;
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.DatabaseNotFoundException;
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");
      String database = System.getenv("SPANNER_DATABASE");
      if (Strings.isNullOrEmpty(database)) {
        INSTANCE = new RealSpannerRefDb(keyPath, instance);
      } else {
        INSTANCE = new RealSpannerRefDb(keyPath, instance, database);
      }
    }
    return INSTANCE;
  }

  private final String keyPath;
  private final String instance;
  private final String dbName;
  private final boolean dropDbOnShutdown;

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

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

  private RealSpannerRefDb(String keyPath, String instance, String dbName) {
    this(keyPath, instance, dbName, false);
  }

  private RealSpannerRefDb(
      String keyPath, String instance, String dbName, boolean dropDbOnShutdown) {
    this.keyPath = keyPath;
    this.instance = instance;
    this.dbName = dbName;
    this.dropDbOnShutdown = dropDbOnShutdown;
  }

  @Override
  public void reset() throws Exception {
    if (!dbInitialized) {
      initialize();
      dbInitialized = true;
    }
    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();

    Database database;
    try {
      database = dbAdminClient.getDatabase(dbId.getInstanceId().getInstance(), dbId.getDatabase());
    } catch (DatabaseNotFoundException e) {
      // create new database and schema
      database =
          dbAdminClient
              .createDatabase(dbId.getInstanceId().getInstance(), dbId.getDatabase(), List.of())
              .get();
      DatabaseSchemaCreator databaseSchemaCreator = new DatabaseSchemaCreator(dbAdminClient, dbId);
      databaseSchemaCreator.start();
    }

    if (dropDbOnShutdown) {
      Database toBeDropped = database;
      Runtime.getRuntime()
          .addShutdownHook(
              new Thread(
                  () -> {
                    toBeDropped.drop();
                  }));
    }

    dbClient = options.getService().getDatabaseClient(dbId);

    heartbeatExecutor = createHeartbeatExecutor();

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

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

  private ScheduledThreadPoolExecutor createHeartbeatExecutor() {
    ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
    Runtime.getRuntime()
        .addShutdownHook(
            new Thread(
                () -> {
                  heartbeatExecutor.shutdownNow();
                  try {
                    heartbeatExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
                  } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                  }
                }));
    return executor;
  }
}
