// Copyright (C) 2025 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.restapi.change;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableMap.toImmutableMap;

import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.PredicateResult;
import com.google.gerrit.extensions.common.EvaluateChangeQueryExpressionResultInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.List;
import java.util.Map;
import org.kohsuke.args4j.Option;

/** REST endpoint to evaluate whether a change query expression matches the change. */
public class EvaluateChangeQueryExpression implements RestReadView<ChangeResource> {
  @Option(
      name = "--expression",
      usage = "Change query expression for which it should be checked if the change matches.")
  public String expression;

  @Option(
      name = "--use-index",
      usage =
          "Whether the change query expression should be evaluated against the change state in the"
              + " index.")
  public boolean useIndex;

  private final Provider<ChangeQueryBuilder> queryBuilder;
  private final Provider<InternalChangeQuery> internalChangeQuery;
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  @Inject
  EvaluateChangeQueryExpression(
      Provider<ChangeQueryBuilder> queryBuilder,
      Provider<InternalChangeQuery> internalChangeQuery) {
    this.queryBuilder = queryBuilder;
    this.internalChangeQuery = internalChangeQuery;
  }

  @Override
  public Response<EvaluateChangeQueryExpressionResultInfo> apply(ChangeResource rsrc)
      throws BadRequestException {
    if (Strings.isNullOrEmpty(expression)) {
      throw new BadRequestException("expression is required");
    }

    logger.atFine().log("parsing expression %s", expression);
    Predicate<ChangeData> predicate = parseExpression(expression);
    logger.atFine().log("evaluating predicate string %s", predicate.getPredicateString());
    PredicateResult predicateResult = getChangeData(rsrc).evaluatePredicateTree(predicate);
    return Response.ok(toInfo(predicateResult));
  }

  private ChangeData getChangeData(ChangeResource rsrc) {
    if (useIndex) {
      // Loading the change from the index populates ChangeData with the data that is stored in the
      // index, including submit requirement results.
      List<ChangeData> changeDatas =
          internalChangeQuery.get().byProjectChangeNumber(rsrc.getProject(), rsrc.getId());
      checkState(
          changeDatas.size() == 1,
          "Got %s matches for change %s, expected 1",
          changeDatas.size() == 1,
          rsrc.getId());
      return Iterables.getOnlyElement(changeDatas);
    }

    // The ChangeData in ChangeResource has been loaded from NoteDb. It doesn't contain submit
    // requirement results yet. Submit requirement results are loaded lazily by executing the submit
    // requirements. Executing the submit requirements is rather expensive. This means if an
    // expression is evaluated that requires checking if the change is submittable (e.g.
    // "is:submittable") this is slower than using the change data from the index where submit
    // requirement results are already present.
    return rsrc.getChangeData();
  }

  private Predicate<ChangeData> parseExpression(String expression) throws BadRequestException {
    try {
      return queryBuilder.get().parse(expression);
    } catch (QueryParseException e) {
      throw new BadRequestException(String.format("invalid query expression: %s", e.getMessage()));
    }
  }

  private static EvaluateChangeQueryExpressionResultInfo toInfo(PredicateResult predicateResult) {
    EvaluateChangeQueryExpressionResultInfo info = new EvaluateChangeQueryExpressionResultInfo();
    info.status = predicateResult.status();
    info.passingAtoms = predicateResult.getPassingAtoms();
    info.failingAtoms = predicateResult.getFailingAtoms();
    ImmutableMap<String, String> atomExplanations =
        predicateResult.getAtomExplanations().entrySet().stream()
            .filter(e -> !Strings.isNullOrEmpty(e.getValue()))
            .collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
    info.atomExplanations = !atomExplanations.isEmpty() ? atomExplanations : null;
    return info;
  }
}
