// Copyright (C) 2020 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.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.server.IdentifiedUser;
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.inject.AbstractModule;
import com.google.inject.Module;
import com.google.inject.Scopes;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;

/**
 * An implementation of {@link ServiceUserClassifier} that will consider a user to be a robot if
 * they are a member in the {@code Service Users} group.
 */
@Singleton
public class ServiceUserClassifierImpl implements ServiceUserClassifier {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static Module module() {
    return new AbstractModule() {
      @Override
      protected void configure() {
        bind(ServiceUserClassifier.class).to(ServiceUserClassifierImpl.class).in(Scopes.SINGLETON);
      }
    };
  }

  private final GroupCache groupCache;
  private final InternalGroupBackend internalGroupBackend;
  private final IdentifiedUser.GenericFactory identifiedUserFactory;

  @Inject
  ServiceUserClassifierImpl(
      GroupCache groupCache,
      InternalGroupBackend internalGroupBackend,
      IdentifiedUser.GenericFactory identifiedUserFactory) {
    this.groupCache = groupCache;
    this.internalGroupBackend = internalGroupBackend;
    this.identifiedUserFactory = identifiedUserFactory;
  }

  @Override
  public boolean isServiceUser(Account.Id user) {
    try (TraceTimer timer = TraceContext.newTimer("isServiceUser", Metadata.empty())) {
      Optional<InternalGroup> maybeGroup = groupCache.get(AccountGroup.nameKey(SERVICE_USERS));
      if (!maybeGroup.isPresent()) {
        return false;
      }
      List<AccountGroup.UUID> toTraverse = new ArrayList<>();
      toTraverse.add(maybeGroup.get().getGroupUUID());
      Set<AccountGroup.UUID> seen = new HashSet<>();
      while (!toTraverse.isEmpty()) {
        InternalGroup currentGroup =
            groupCache
                .get(toTraverse.remove(0))
                .orElseThrow(() -> new IllegalStateException("invalid subgroup"));
        if (seen.contains(currentGroup.getGroupUUID())) {
          logger.atFine().log(
              "Skipping %s because it's a cyclic subgroup", currentGroup.getGroupUUID());
          continue;
        }
        seen.add(currentGroup.getGroupUUID());
        if (currentGroup.getMembers().contains(user)) {
          // The user is a member of the 'Service Users' group or a subgroup.
          return true;
        }
        boolean hasExternalSubgroup =
            currentGroup.getSubgroups().stream().anyMatch(g -> !internalGroupBackend.handles(g));
        if (hasExternalSubgroup) {
          // 'Service Users or a subgroup of Service User' contains an external subgroup, so we have
          // to default to the more expensive evaluation of getting all of the user's group
          // memberships.
          return identifiedUserFactory
              .create(user)
              .getEffectiveGroups()
              .contains(maybeGroup.get().getGroupUUID());
        }
        toTraverse.addAll(currentGroup.getSubgroups());
      }
      return false;
    }
  }
}
