// Copyright (C) 2021 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.google.gerrit.pgm;

import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.pgm.init.api.ConsoleUI;
import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIds;
import com.google.gerrit.server.account.externalids.storage.notedb.DisabledExternalIdCache;
import com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdCaseSensitivityMigrator;
import com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdNoteDbReadStorageModule;
import com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdNoteDbWriteStorageModule;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
import com.google.gerrit.server.schema.NoteDbSchemaVersionCheck;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import java.io.IOException;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.TextProgressMonitor;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.kohsuke.args4j.Option;

/**
 * Changes the case sensitivity of `username:` and `gerrit:` external IDs by recomputing the SHA-1
 * sums used as note names.
 */
public class ChangeExternalIdCaseSensitivity extends SiteProgram {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  @Option(name = "--batch", usage = "Don't ask for confirmation before migrating.")
  private boolean batch;

  @Option(name = "--dryrun", usage = "Do a dryrun of the migration.")
  private boolean dryrun;

  private final LifecycleManager manager = new LifecycleManager();
  private final TextProgressMonitor monitor = new TextProgressMonitor();

  private Config globalConfig;
  private boolean isUserNameCaseInsensitive;
  private ConsoleUI ui;

  @Inject private ExternalIds externalIds;
  @Inject private ExternalIdCaseSensitivityMigrator.Factory migratorFactory;

  @Override
  public int run() throws Exception {
    mustHaveValidSite();
    ui = ConsoleUI.getInstance(batch);

    Injector dbInjector = createDbInjector();
    manager.add(dbInjector, dbInjector.createChildInjector(NoteDbSchemaVersionCheck.module()));
    dbInjector
        .createChildInjector(
            new FactoryModule() {
              @Override
              protected void configure() {
                bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED);
                install(
                    new FactoryModuleBuilder()
                        .build(ExternalIdCaseSensitivityMigrator.Factory.class));
                factory(MetaDataUpdate.InternalFactory.class);
                install(new ExternalIdNoteDbReadStorageModule());
                install(new ExternalIdNoteDbWriteStorageModule());

                // The ChangeExternalIdCaseSensitivity program needs to access all external IDs only
                // once to update them. After the update they are not accessed again. Hence the
                // LocalUsernamesToLowerCase program doesn't benefit from caching external IDs and
                // the external ID cache can be disabled.
                install(DisabledExternalIdCache.module());
              }
            })
        .injectMembers(this);
    globalConfig = dbInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));

    this.isUserNameCaseInsensitive =
        globalConfig.getBoolean("auth", "userNameCaseInsensitive", false);

    String message =
        "auth.userNameCaseInsensitive is set to %b. "
            + "External IDs will be migrated to be case %ssensitive. Continue?";
    if (!ui.yesno(
        true, message, isUserNameCaseInsensitive, isUserNameCaseInsensitive ? "" : "in")) {
      return 0;
    }

    ImmutableSet<ExternalId> todo = externalIds.all();
    monitor.beginTask("Converting external ID note names", todo.size());

    manager.start();
    try {
      migratorFactory
          .create(!isUserNameCaseInsensitive, dryrun)
          .migrate(todo, () -> monitor.update(1));
    } finally {
      manager.stop();
      monitor.endTask();
    }

    int exitCode;
    if (!dryrun) {
      updateGerritConfig();

      exitCode = reindexAccounts();
    } else {
      exitCode = 0;
    }
    return exitCode;
  }

  private void updateGerritConfig() throws IOException, ConfigInvalidException {
    logger.atInfo().log("Setting auth.userNameCaseInsensitive to true in gerrit.config.");
    FileBasedConfig config =
        new FileBasedConfig(
            globalConfig, getSitePath().resolve("etc/gerrit.config").toFile(), FS.DETECTED);
    config.load();
    config.setBoolean("auth", null, "userNameCaseInsensitive", !isUserNameCaseInsensitive);
    config.save();
  }

  private int reindexAccounts() throws Exception {
    monitor.beginTask("Reindex accounts", ProgressMonitor.UNKNOWN);
    String[] reindexArgs = {
      "--site-path", getSitePath().toString(), "--index", AccountSchemaDefinitions.NAME
    };
    logger.atInfo().log(
        "Migration complete, reindexing accounts with: reindex %s", String.join(" ", reindexArgs));
    Reindex reindexPgm = new Reindex();
    int exitCode = reindexPgm.main(reindexArgs);
    monitor.endTask();
    return exitCode;
  }
}
