# Copyright 2025 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.
"""This module checks for approvals on Gerrit changes."""

from __future__ import annotations

import contextlib
import dataclasses
from collections.abc import Mapping, Sequence

from recipe_engine import recipe_api

from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb
from PB.recipe_engine import result as result_pb

_TRUSTED_DOMAINS = (
    'google.com',
    'pigweed-service-accounts.iam.gserviceaccount.com',
    'pw-internal-service-accounts.iam.gserviceaccount.com',
)


@dataclasses.dataclass
class Change:
    gerrit_name: str
    number: int
    submit_requirements: Mapping[str, str]
    uploader: str | None


class LimitedCqApi(recipe_api.RecipeApi):
    Change = Change

    def _change_approved(self, change: Change) -> bool:
        with self.m.step.nest(change.name):
            for req, status in change.submit_requirements.items():
                if req in ('Code-Owners', 'Code-Review', 'Review-Enforcement'):
                    if status in ('SATISFIED', 'OVERRIDDEN'):
                        with self.m.step.nest('continue'):
                            pres = self.m.step.empty(req).presentation
                            pres.step_summary_text = status
                            return True

            if not change.uploader:
                return False  # pragma: no cover

            _, domain = change.uploader.split('@')
            if domain in _TRUSTED_DOMAINS:
                with self.m.step.nest('continue'):
                    pres = self.m.step.empty('uploader').presentation
                    pres.step_summary_text = change.uploader
                    return True

            return False

    def exit_early_if_not_approved(
        self,
        changes: Sequence[Change],
        *,
        verbose: bool = False,
    ) -> result_pb.RawResult | None:
        """Exit the build early if the change isn't sufficiently approved.

        Continue the build (by returning None) if any of the following
        conditions are met:
        *   The build is in the pigweed LUCI project
        *   The build is not a tryjob
        *   The change has one of the following submit requirements met:
            *   Code-Review (somebody voted CR+2, only Googlers can do this)
            *   Review-Enforcement (meaning two Googlers approved it)
            *   Code-Owners (one Googler approved it or it's a pure revert)
        *   The change owner is a Googler or a trusted service account
        *   The CQ triggerer is a Googler or a trusted service account

        Otherwise, return a RawResult. The caller will also return the
        RawResult, exiting the build. In dry run mode, the result will be a
        success. In full run mode, it will be a failure.

        If returning a RawResult, disallow reuse of this build in future dry
        runs and full runs.
        """
        with contextlib.ExitStack() as stack:
            build_proto = self.m.buildbucket.build

            # If verbose, make sure everything is under this nested step.
            if verbose:
                stack.enter_context(
                    self.m.step.nest('checking change approvals'),
                )

            # If this builder is in a public project, do nothing and continue.
            project = build_proto.builder.project
            if project in ('fuchsia', 'pigweed'):
                if verbose:
                    pres = self.m.step.empty('project is public').presentation
                    pres.step_summary_text = project
                return None

            bucket = build_proto.builder.bucket
            if not self.m.buildbucket_util.is_tryjob:
                if verbose:
                    pres = self.m.step.empty('not a tryjob').presentation
                    pres.step_summary_text = bucket
                return None

            # If not verbose, only make this nested step appear if there's
            # something to show under it. (If we got here, there will always be
            # a step created.)
            if not verbose:
                stack.enter_context(  # pragma: no cover
                    self.m.step.nest('checking change approvals'),
                )

            # If any submit requirements that indicate Googlers have approved
            # the change, let the build continue. If there are multiple changes,
            # make sure all of them are approved.
            if all(self._change_approved(change) for change in changes):
                return None

            # If CQ was triggered by a Googler then allow the build to continue.
            for tag_pair in build_proto.tags:
                tag, value = tag_pair.key, tag_pair.value
                if tag == 'cq_triggerer':
                    _, domain = value.split('@')
                    if domain in _TRUSTED_DOMAINS:
                        with self.m.step.nest('continue'):
                            pres = self.m.step.empty('triggerer').presentation
                            pres.step_summary_text = value
                            return None

            # If the build was launched by a Googler outside of CV allow the
            # build to continue.
            created_by = build_proto.created_by
            if '@' in created_by:
                _, domain = created_by.removeprefix('user:').split('@')
                if domain in _TRUSTED_DOMAINS:
                    with self.m.step.nest('continue'):
                        pres = self.m.step.empty('created by').presentation
                        pres.step_summary_text = created_by
                        return None

            # If we got here, the change is not approved and we cannot continue.
            pres = self.m.step.empty('exit early').presentation
            pres.properties['early_exit_reason'] = 'not approved'

            # Only allow reuse for new patchset runs. Really, this is
            # disallowing reuse for dry runs and full runs, so short-circuited
            # builds won't be treated as passing builds in later CQ+1/+2 runs.
            # (Pigweed makes limited use of new patchset runs.)
            self.m.cv.allow_reuse_for(self.m.cv.NEW_PATCHSET_RUN)

            status: common_pb.Status = common_pb.SUCCESS
            # If CV is not active, any builds that exit early should fail.
            if not self.m.cv.active:
                status = common_pb.FAILURE

            # If we got here, the build will not continue. It shouldn't be
            # possible to get here via CQ+2 without submit requirements being
            # met, but just in case we'll fail those builders.
            elif self.m.cv.run_mode == self.m.cv.FULL_RUN:
                status = common_pb.FAILURE

            return result_pb.RawResult(
                summary_markdown=(
                    'Exiting early since not all triggering changes have been '
                    'approved.'
                ),
                status=status,
            )
