// Copyright (C) 2024 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.acceptance;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.truth.TruthJUnit.assume;
import static java.util.Objects.requireNonNull;

import com.google.gerrit.acceptance.GerritServer.TestSshServerAddress;
import com.google.gerrit.acceptance.testsuite.account.AccountOperations;
import com.google.gerrit.acceptance.testsuite.account.TestSshKeys;
import com.google.gerrit.acceptance.testsuite.request.SshSessionFactory;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.testing.SshMode;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class GerritServerTestRule implements ServerTestRule {
  /**
   * Test methods without special annotations will use a common server for efficiency reasons. The
   * server is torn down after the test class is done or when the config is changed.
   */
  private static GerritServer commonServer;

  private static Description firstTest;

  private final TemporaryFolder temporaryFolder;
  @Nullable private final Supplier<Module> testSysModule;
  @Nullable private final Supplier<Module> testAuditModule;
  @Nullable private final Supplier<Module> testSshModule;
  private final TestConfigRule config;

  @Inject private TestSshKeys sshKeys;
  @Inject @Nullable @TestSshServerAddress private InetSocketAddress sshAddress;

  @Inject private AccountOperations accountOperations;

  private boolean sshInitialized;

  private final HashMap<RequestContext, SshSession> sshSessionByContext = new HashMap<>();

  public GerritServer server;

  public GerritServerTestRule(
      TestConfigRule config,
      TemporaryFolder temporaryFolder,
      @Nullable Supplier<Module> testSysModule,
      @Nullable Supplier<Module> testAuditModule,
      @Nullable Supplier<Module> testSshModule) {
    this.config = config;
    this.testSysModule = testSysModule;
    this.testAuditModule = testAuditModule;
    this.testSshModule = testSshModule;
    this.temporaryFolder = temporaryFolder;
  }

  @Override
  public Statement apply(Statement statement, Description description) {
    return new Statement() {
      @Override
      public void evaluate() throws Throwable {
        if (firstTest == null) {
          firstTest = description;
        }
        if (config.testRequiresSsh()) {
          // If the test uses ssh, we use assume() to make sure ssh is enabled on
          // the test suite. JUnit will skip tests annotated with @UseSsh if we
          // disable them using the command line flag.
          assume().that(SshMode.useSsh()).isTrue();
        }
        statement.evaluate();
        afterTest();
      }
    };
  }

  public void afterTest() throws Exception {
    closeSsh();
    if (server != commonServer) {
      server.close();
      server = null;
    }
  }

  @Override
  public void initServer() throws Exception {

    if (config.classDescription().equals(config.methodDescription())
        && !config.classDescription().sandboxed()
        && !config.methodDescription().sandboxed()) {
      if (commonServer == null) {
        commonServer =
            GerritServer.initAndStart(
                temporaryFolder,
                config.classDescription(),
                config.baseConfig(),
                testSysModule.get(),
                testAuditModule.get(),
                testSshModule.get());
      }
      server = commonServer;
    } else {
      server =
          GerritServer.initAndStart(
              temporaryFolder,
              config.methodDescription(),
              config.baseConfig(),
              testSysModule.get(),
              testAuditModule.get(),
              testSshModule.get());
    }
    getTestInjector().injectMembers(this);
  }

  @Override
  public void initSsh() throws Exception {
    if (config.testRequiresSsh() && SshMode.useSsh()) {
      checkState(!sshInitialized, "The ssh has been alread initialized. Call closeSsh first.");
      // Create Ssh sessions
      SshSessionFactory.initSsh();
      sshInitialized = true;
    }
  }

  @Override
  public boolean sshInitialized() {
    return sshInitialized;
  }

  @Override
  public SshSession getOrCreateSshSessionForContext(RequestContext ctx) {
    checkState(
        config.testRequiresSsh(),
        "The test or the test class must be annotated with @UseSsh to use this method.");
    return sshSessionByContext.computeIfAbsent(
        ctx,
        (c) ->
            SshSessionFactory.createSession(
                sshKeys,
                sshAddress,
                accountOperations.account(ctx.getUser().getAccountId()).get()));
  }

  /**
   * This method is only required for some tests and is not a part of interface.
   *
   * <p>After restarting the server with this method, the caller can still get exit value of the
   * last command executed before restarting (using non-closed sessions). This is used in
   * SshDaemonIT tests.
   */
  public void restartKeepSessionOpen() throws Exception {
    checkState(
        server != commonServer,
        "The commonServer can't be restarted; to use this method, the test must be @Sandboxed");
    server = GerritServer.restart(server, testSysModule.get(), testSshModule.get());
    getTestInjector().injectMembers(this);
  }

  @Override
  public void restart() throws Exception {
    checkState(
        server != commonServer,
        "The commonServer can't be restarted; to use this method, the test must be @Sandboxed");
    closeSsh();
    server = GerritServer.restart(server, testSysModule.get(), testSshModule.get());
    getTestInjector().injectMembers(this);
    initSsh();
  }

  @Override
  public void restartAsSlave() throws Exception {
    checkState(
        server != commonServer,
        "The commonServer can't be restarted; to use this method, the test must be @Sandboxed");
    closeSsh();
    server = GerritServer.restartAsSlave(server);
    getTestInjector().injectMembers(this);
    initSsh();
  }

  protected void closeSsh() {
    sshSessionByContext.values().forEach(SshSession::close);
    sshSessionByContext.clear();
    sshInitialized = false;
  }

  @Override
  public Injector getTestInjector() {
    return server.getTestInjector();
  }

  @Override
  public Optional<Injector> getHttpdInjector() {
    return server.getHttpdInjector();
  }

  @Override
  public RestSession createRestSession(@Nullable TestAccount account) {
    return new GerritServerRestSession(server, account);
  }

  @Nullable
  @Override
  public ProjectResetter createProjectResetter(
      BiFunction<AllProjectsName, AllUsersName, ProjectResetter.Config> resetConfigSupplier)
      throws Exception {
    // Only commonServer can be shared between tests and should be restored after each
    // test. It can be that the commonServer is started, but a test actually don't use
    // it and instead the test uses a separate server instance.
    // In this case, the separate server is stopped after each test and so doesn't require
    // cleanup (for simplicity, the commonServer is always cleaned up even if it is not
    // used in a test).
    if (commonServer == null) {
      return null;
    }
    Injector testInjector = commonServer.testInjector;
    ProjectResetter.Config config =
        requireNonNull(
            resetConfigSupplier.apply(
                testInjector.getInstance(AllProjectsName.class),
                testInjector.getInstance(AllUsersName.class)));
    ProjectResetter.Builder.Factory projectResetterFactory =
        testInjector.getInstance(ProjectResetter.Builder.Factory.class);
    return projectResetterFactory != null ? projectResetterFactory.builder().build(config) : null;
  }

  @Override
  public boolean isReplica() {
    return server.isReplica();
  }

  @Override
  public Optional<InetSocketAddress> getHttpAddress() {
    return server.getHttpAddress();
  }

  @Override
  public String getGitUrl() {
    return server.getUrl();
  }

  @Override
  public boolean isUsernameSupported() {
    return true;
  }

  public static void afterConfigChanged() {
    if (commonServer != null) {
      try {
        commonServer.close();
      } catch (Exception e) {
        throw new AssertionError(
            "Error stopping common server in "
                + (firstTest != null ? firstTest.getTestClass().getName() : "unknown test class"),
            e);
      } finally {
        commonServer = null;
      }
    }
  }
}
