// 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 com.google.common.collect.ImmutableList;
import com.google.common.collect.MoreCollectors;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.ParentCommitData;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.ReachabilityChecker;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

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

  private final Provider<InternalChangeQuery> queryProvider;

  @Inject
  public ParentDataProvider(Provider<InternalChangeQuery> queryProvider) {
    this.queryProvider = queryProvider;
  }

  /**
   * Returns data about a specific {@code revCommit}, specifically whether it's merged in a {@code
   * targetBranch}, or if it's a patch-set commit of some Gerrit change otherwise. This can be used
   * to get more information of parent commits of patch-sets.
   */
  public ParentCommitData get(
      Project.NameKey project, Repository repo, ObjectId parentCommitId, String targetBranch) {
    Optional<ParentCommitData> fromGerritChange =
        getFromGerritChange(project, parentCommitId, targetBranch);
    if (fromGerritChange.isPresent()) {
      return fromGerritChange.get();
    }

    boolean inTargetBranch = isMergedInTargetBranch(project, repo, parentCommitId, targetBranch);
    return ParentCommitData.builder()
        .branchName(Optional.of(targetBranch))
        .commitId(Optional.of(parentCommitId))
        .isMergedInTargetBranch(inTargetBranch)
        .autoBuild();
  }

  /** Returns true if the parent commit {@code parentCommitId} is merged in the target branch. */
  private boolean isMergedInTargetBranch(
      Project.NameKey project, Repository repo, ObjectId parentCommitId, String targetBranch) {
    try (RevWalk rw = new RevWalk(repo);
        ObjectReader reader = repo.newObjectReader()) {
      Ref targetBranchRef = repo.exactRef(targetBranch);
      if (targetBranchRef == null) {
        return false;
      }
      RevCommit parent = rw.parseCommit(parentCommitId);
      RevCommit targetBranchCommit = rw.parseCommit(targetBranchRef.getObjectId());
      ReachabilityChecker checker = reader.createReachabilityChecker(rw);
      Optional<RevCommit> unreachable =
          checker.areAllReachable(
              ImmutableList.of(parent), ImmutableList.of(targetBranchCommit).stream());
      return unreachable.isEmpty();
    } catch (IOException e) {
      logger.atWarning().withCause(e).log(
          "Failed to check if parent commit %s (project: %s) is merged into target branch %s",
          parentCommitId.name(), project, targetBranch);
    }
    return false;
  }

  /**
   * Returns {@link ParentCommitData} if there is a change associated with {@code parentCommitId}.
   */
  private Optional<ParentCommitData> getFromGerritChange(
      Project.NameKey project, ObjectId parentCommitId, String targetBranch) {
    List<ChangeData> changeData = queryProvider.get().byCommit(parentCommitId.name());
    if (changeData.size() > 1) {
      logger.atWarning().log(
          "Found more than one change associated with parent revision %s (project: %s). Found"
              + " changes %s.",
          parentCommitId.name(),
          project.get(),
          changeData.stream().map(ChangeData::getId).collect(ImmutableList.toImmutableList()));
    }
    if (changeData.size() != 1) {
      return Optional.empty();
    }
    ChangeData singleData = changeData.get(0);
    int patchSetNumber =
        singleData.patchSets().stream()
            .filter(p -> p.commitId().equals(parentCommitId))
            .collect(MoreCollectors.onlyElement())
            .number();
    return Optional.of(
        ParentCommitData.builder()
            .branchName(Optional.of(targetBranch))
            .commitId(Optional.of(parentCommitId))
            .changeKey(Optional.of(singleData.change().getKey()))
            .changeNumber(Optional.of(singleData.getId().get()))
            .patchSetNumber(Optional.of(patchSetNumber))
            .changeStatus(Optional.of(singleData.change().getStatus()))
            .isMergedInTargetBranch(
                patchSetNumber == singleData.change().currentPatchSetId().get()
                    && singleData.change().isMerged())
            .autoBuild());
  }
}
