// 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.server.IdentifiedUser;
import com.google.gerrit.server.group.InternalGroup;
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) {
    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.atWarning().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;
  }
}
