# Copyright 2022 The Pigweed Authors
#
# 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
#
#     https://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.

from recipe_engine import recipe_api

from PB.recipe_modules.pigweed.gerrit_comment.options import (
    CommentBehavior,
    Options,
)
from RECIPE_MODULES.recipe_engine.defer import api as defer_api


class GerritCommentApi(recipe_api.RecipeApi):
    def maybe_post(self, options: Options, result: defer_api.DeferredResult):
        """Maybe post a comment on a Gerrit CL.

        Post a comment on the CL associated with this build (or not, depending
        on the options).

        Args:
          options: Options.
          result: DeferredResult object.
        """
        if options.comment_behavior == CommentBehavior.COMMENT_UNSPECIFIED:
            return

        with self.m.step.nest("maybe post") as pres:
            if (
                options.comment_behavior == CommentBehavior.COMMENT_ON_FAILURE
                and result.is_ok()
            ):
                pres.step_summary_text = (
                    "No-op: Comments requested only on failures, "
                    "but the step passed."
                )
                return

            changes = self.m.buildbucket.build.input.gerrit_changes
            if len(changes) == 0:
                pres.step_summary_text = (
                    "No-op: no Gerrit change to comment on "
                    "(expected for CI builds)."
                )
                return

            change = changes[-1]
            if (
                self.m.gerrit.normalize_host(change.host)
                not in options.allowed_gerrit_hosts
            ):
                pres.step_summary_text = (
                    "No-op: "
                    "the change is on a host that's not explicitly allowlisted."
                )
                return

            # If we made it here, we should post a comment on the CL.
            pres.step_summary_text = "Posting CL comment"
            if result.is_ok():
                status = "OK"
            else:
                try:
                    result.result()
                    assert False, "shouldn't get here"  # pragma: no cover
                except Exception as exc:
                    status = str(exc)

            self.m.gerrit.set_review(
                "post CL comment",
                change.change,
                host=change.host,
                message="{} completed with status {}: http://go/bbid/{}".format(
                    self.m.buildbucket.builder_name,
                    status,
                    self.m.buildbucket.build.id,
                ),
                notify="OWNER",
                tag="autogenerated:pigweed:gerrit_comment",
            )
