// Copyright (C) 2025 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.server.account;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Stopwatch;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.server.account.storage.notedb.AccountsNoteDbImpl;
import com.google.gerrit.server.git.MultiProgressMonitor;
import com.google.gerrit.server.git.MultiProgressMonitor.Task;
import com.google.gerrit.server.git.MultiProgressMonitor.TaskKind;
import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
import com.google.gerrit.server.project.LockManager;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
import java.time.Instant;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.util.io.NullOutputStream;

public class MaxAuthTokenLifetimeApplier implements Runnable {
  static final FluentLogger logger = FluentLogger.forEnclosingClass();
  @VisibleForTesting public static final String DEFAULT_ID = "default";

  private final MultiProgressMonitor.Factory multiProgressMonitorFactory;
  private final AuthTokenAccessor tokenAccessor;
  private final LockManager lockManager;
  private final AccountsNoteDbImpl accounts;
  private final Instant expiryInstant;

  private MultiProgressMonitor mpm;
  private Task doneTask;
  private Task failedTask;

  public interface Factory {
    public MaxAuthTokenLifetimeApplier create(Instant expiryInstant);
  }

  @AssistedInject
  public MaxAuthTokenLifetimeApplier(
      MultiProgressMonitor.Factory multiProgressMonitorFactory,
      AuthTokenAccessor tokenAccessor,
      LockManager lockManager,
      AccountsNoteDbImpl accounts,
      @Assisted Instant expiryInstant) {
    this.multiProgressMonitorFactory = multiProgressMonitorFactory;
    this.tokenAccessor = tokenAccessor;
    this.lockManager = lockManager;
    this.accounts = accounts;
    this.expiryInstant = expiryInstant;
  }

  @Override
  public void run() {
    Lock lock = lockManager.getLock("ReduceMaxAuthTokenLifetime");
    if (!lock.tryLock()) {
      logger.atWarning().log("Task applying limit to auth token lifetime already running.");
      return;
    }
    try {
      Set<Account.Id> todo = accounts.allIds();

      Stopwatch sw = Stopwatch.createStarted();
      mpm =
          multiProgressMonitorFactory.create(
              NullOutputStream.INSTANCE, TaskKind.MIGRATION, "Limiting auth token lifetime", true);
      doneTask = mpm.beginSubTask("done", MultiProgressMonitor.UNKNOWN);
      failedTask = mpm.beginSubTask("failed", MultiProgressMonitor.UNKNOWN);
      for (Account.Id accountId : todo) {
        adaptTokenLifetime(accountId, expiryInstant);
        logger.atInfo().atMostEvery(30, TimeUnit.SECONDS).log(
            "Adapted lifetime of %d auth tokens (%d failed).",
            doneTask.getCount(), failedTask.getCount());
      }
      doneTask.end();
      failedTask.end();
      mpm.end();
      sw.stop();
      logger.atInfo().log(
          "Finished adapting lifetime of %d auth tokens. Total duration was %d min.",
          doneTask.getCount(), sw.elapsed(TimeUnit.MINUTES));
    } catch (IOException e) {
      logger.atSevere().withCause(e).log("Could not load accounts.");
    } finally {
      lock.unlock();
    }
  }

  private void adaptTokenLifetime(Account.Id accountId, Instant maxAllowedExpirationInstant) {
    try (TraceTimer traceTimer =
        TraceContext.newTimer(
            "Limiting lifetime of auth tokens",
            Metadata.builder().projectName("All-Users").accountId(accountId.get()).build())) {
      for (AuthToken authToken : tokenAccessor.getTokens(accountId)) {
        if (authToken.expirationDate().isEmpty()
            || authToken.expirationDate().get().isAfter(maxAllowedExpirationInstant)) {
          AuthToken updatedToken;
          try {
            updatedToken =
                AuthToken.create(
                    authToken.id(),
                    authToken.hashedToken(),
                    Optional.of(maxAllowedExpirationInstant));
            tokenAccessor.updateToken(accountId, updatedToken);
            doneTask.update(1);
          } catch (InvalidAuthTokenException | IOException | ConfigInvalidException e) {
            logger.atSevere().withCause(e).log(
                "Failed to limit lifetime of token %s for account %d",
                authToken.id(), accountId.get());
            failedTask.update(1);
          }
        }
      }
    } catch (IOException | ConfigInvalidException e) {
      logger.atSevere().withCause(e).log(
          "Failed to limit lifetime of tokens for account %d", accountId.get());
      failedTask.update(1);
    }
  }
}
