// Copyright (C) 2017 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.group.db;

import static com.google.gerrit.extensions.api.config.ConsistencyCheckInfo.ConsistencyProblemInfo.error;
import static com.google.gerrit.extensions.api.config.ConsistencyCheckInfo.ConsistencyProblemInfo.warning;

import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.extensions.api.config.ConsistencyCheckInfo.ConsistencyProblemInfo;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.Accounts;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.InternalGroup;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Repository;

/**
 * Checks individual groups for oddities, such as cycles, non-existent subgroups, etc. Only works if
 * we are writing to NoteDb.
 */
@Singleton
public class GroupsConsistencyChecker {
  private final AllUsersName allUsersName;
  private final GroupBackend groupBackend;
  private final Accounts accounts;
  private final GitRepositoryManager repoManager;
  private final GroupsNoteDbConsistencyChecker globalChecker;

  @Inject
  GroupsConsistencyChecker(
      AllUsersName allUsersName,
      GroupBackend groupBackend,
      Accounts accounts,
      GitRepositoryManager repositoryManager,
      GroupsNoteDbConsistencyChecker globalChecker) {
    this.allUsersName = allUsersName;
    this.groupBackend = groupBackend;
    this.accounts = accounts;
    this.repoManager = repositoryManager;
    this.globalChecker = globalChecker;
  }

  /** Checks that all internal group references exist, and that no groups have cycles. */
  public List<ConsistencyProblemInfo> check() throws IOException {
    try (Repository repo = repoManager.openRepository(allUsersName)) {
      GroupsNoteDbConsistencyChecker.Result result = globalChecker.check(repo);
      if (!result.problems.isEmpty()) {
        return result.problems;
      }

      for (InternalGroup g : result.uuidToGroupMap.values()) {
        result.problems.addAll(checkGroup(g, result.uuidToGroupMap));
      }

      return result.problems;
    }
  }

  /** Checks the metadata for a single group for problems. */
  private List<ConsistencyProblemInfo> checkGroup(
      InternalGroup g, Map<AccountGroup.UUID, InternalGroup> byUUID) throws IOException {
    List<ConsistencyProblemInfo> problems = new ArrayList<>();

    problems.addAll(checkCycle(g, byUUID));

    if (byUUID.get(g.getOwnerGroupUUID()) == null
        && groupBackend.get(g.getOwnerGroupUUID()) == null) {
      problems.add(
          error(
              "group %s (%s) has nonexistent owner group %s",
              g.getName(), g.getGroupUUID(), g.getOwnerGroupUUID()));
    }

    for (AccountGroup.UUID subUuid : g.getSubgroups()) {
      if (byUUID.get(subUuid) == null && groupBackend.get(subUuid) == null) {
        problems.add(
            error(
                "group %s (%s) has nonexistent subgroup %s",
                g.getName(), g.getGroupUUID(), subUuid));
      }
    }

    for (Account.Id id : g.getMembers().asList()) {
      Optional<AccountState> account;
      try {
        account = accounts.get(id);
      } catch (ConfigInvalidException e) {
        problems.add(
            error(
                "group %s (%s) has member %s with invalid configuration: %s",
                g.getName(), g.getGroupUUID(), id, e.getMessage()));
        continue;
      }
      if (!account.isPresent()) {
        problems.add(
            error("group %s (%s) has nonexistent member %s", g.getName(), g.getGroupUUID(), id));
      }
    }
    return problems;
  }

  /** checkCycle walks through root's subgroups recursively, and checks for cycles. */
  private List<ConsistencyProblemInfo> checkCycle(
      InternalGroup root, Map<AccountGroup.UUID, InternalGroup> byUUID) {
    List<ConsistencyProblemInfo> problems = new ArrayList<>();
    Set<InternalGroup> todo = new LinkedHashSet<>();
    Set<InternalGroup> seen = new HashSet<>();

    todo.add(root);
    while (!todo.isEmpty()) {
      InternalGroup t = todo.iterator().next();
      todo.remove(t);

      if (seen.contains(t)) {
        continue;
      }
      seen.add(t);

      // We don't check for owner cycles, since those are normal in self-administered groups.
      for (AccountGroup.UUID subUuid : t.getSubgroups()) {
        InternalGroup g = byUUID.get(subUuid);
        if (g == null) {
          continue;
        }

        if (Objects.equals(g, root)) {
          problems.add(
              warning(
                  "group %s (%s) contains a cycle: %s (%s) points to it as subgroup.",
                  root.getName(), root.getGroupUUID(), t.getName(), t.getGroupUUID()));
        }

        todo.add(g);
      }
    }
    return problems;
  }
}
