// 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.google.gerrit.server.change;

import static com.google.gerrit.server.update.context.RefUpdateContext.RefUpdateType.CHANGE_MODIFICATION;

import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableListMultimap;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.InternalUser;
import com.google.gerrit.server.account.ServiceUserClassifier;
import com.google.gerrit.server.config.AttentionSetConfig;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.ChangeQueryProcessor;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.update.context.RefUpdateContext;
import com.google.gerrit.server.util.AttentionSetUtil;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.concurrent.TimeUnit;

@Singleton
public class ReaddOwnerUtil {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final AttentionSetConfig cfg;
  private final Provider<ChangeQueryProcessor> queryProvider;
  private final Supplier<ChangeQueryBuilder> queryBuilderSupplier;
  private final AddToAttentionSetOp.Factory opFactory;
  private final ServiceUserClassifier serviceUserClassifier;
  private final InternalUser internalUser;

  @Inject
  ReaddOwnerUtil(
      AttentionSetConfig cfg,
      Provider<ChangeQueryProcessor> queryProvider,
      Provider<ChangeQueryBuilder> queryBuilderProvider,
      AddToAttentionSetOp.Factory opFactory,
      ServiceUserClassifier serviceUserClassifier,
      InternalUser.Factory internalUserFactory) {
    this.cfg = cfg;
    this.queryProvider = queryProvider;
    this.queryBuilderSupplier = Suppliers.memoize(queryBuilderProvider::get);
    this.opFactory = opFactory;
    this.serviceUserClassifier = serviceUserClassifier;
    internalUser = internalUserFactory.create();
  }

  public void readdOwnerForInactiveOpenChanges(BatchUpdate.Factory updateFactory) {
    if (cfg.getReaddAfter() <= 0) {
      logger.atWarning().log("readdOwnerAfter needs to be set to a positive value");
      return;
    }

    try {
      String query =
          "status:new -is:wip -is:private age:"
              + TimeUnit.MILLISECONDS.toMinutes(cfg.getReaddAfter())
              + "m";

      ImmutableList<ChangeData> changesToAddOwner =
          queryProvider
              .get()
              .enforceVisibility(false)
              .query(queryBuilderSupplier.get().parse(query))
              .entities();

      ImmutableListMultimap.Builder<Project.NameKey, ChangeData> builder =
          ImmutableListMultimap.builder();
      for (ChangeData cd : changesToAddOwner) {
        builder.put(cd.project(), cd);
      }

      ImmutableListMultimap<Project.NameKey, ChangeData> ownerAdds = builder.build();
      int ownersAdded = 0;
      for (Project.NameKey project : ownerAdds.keySet()) {
        try (RefUpdateContext ctx = RefUpdateContext.open(CHANGE_MODIFICATION)) {
          try (BatchUpdate bu = updateFactory.create(project, internalUser, TimeUtil.now())) {
            for (ChangeData changeData : ownerAdds.get(project)) {
              Account.Id ownerId = changeData.change().getOwner();
              if (!inAttentionSet(changeData, ownerId)
                  && !serviceUserClassifier.isServiceUser(ownerId)) {
                logger.atFine().log(
                    "Batch owner for add to AS of change %s in project %s",
                    changeData.getId(), project.get());
                bu.addOp(
                    changeData.getId(), opFactory.create(ownerId, cfg.getReaddMessage(), true));
                ownersAdded++;
              }
            }
            bu.execute();
          } catch (RestApiException | UpdateException e) {
            logger.atSevere().withCause(e).log(
                "Failed to readd owners for changes in project %s", project.get());
          }
        }
      }
      logger.atInfo().log("Auto-Added %d owners to changes", ownersAdded);
    } catch (QueryParseException | StorageException e) {
      logger.atSevere().withCause(e).log(
          "Failed to query inactive open changes for readding owners.");
    }
  }

  private static boolean inAttentionSet(ChangeData changeData, Account.Id accountId) {
    return AttentionSetUtil.additionsOnly(changeData.attentionSet()).stream()
        .anyMatch(u -> u.account().equals(accountId));
  }
}
