# Copyright 2021 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.
"""Utility functions common to multiple recipes that don't fit elsewhere."""

from __future__ import annotations

import json
import re
from typing import TYPE_CHECKING

import attrs
from google.protobuf import json_format
from recipe_engine import recipe_api

if TYPE_CHECKING:  # pragma: no cover
    from typing import Any, Sequence
    from PB.go.chromium.org.luci.buildbucket.proto import (
        build as build_pb2,
        common as common_pb2,
    )


@attrs.define
class ChangeWithComments:
    change: common_pb2.GerritChange
    details: dict[str, Any]
    commit_message: str
    comments: Sequence[str]


class UtilApi(recipe_api.RecipeApi):
    ChangeWithComments = ChangeWithComments

    def get_change_with_comments(self) -> ChangeWithComments:
        input_: build_pb2.Build.Input = self.m.buildbucket.build.input
        change: common_pb2.GerritChange = input_.gerrit_changes[0]
        change_id: str = str(change.change)
        details: dict[str, Any] = self.m.gerrit.change_details(
            'change details',
            change_id=change_id,
            host=input_.gerrit_changes[0].host,
            query_params=['ALL_COMMITS', 'ALL_REVISIONS', 'ALL_FILES'],
            test_data=self.m.json.test_api.output(
                {
                    'owner': {
                        'email': 'coder@example.com',
                    },
                    'current_revision': 'a' * 40,
                    'revisions': {
                        'a'
                        * 40: {
                            'files': [],
                            'commit': {
                                'message': '',
                            },
                            'description': 'description',
                        }
                    },
                    'revert_of': 0,
                }
            ),
        ).json.output

        current_revision: str = details['revisions'][
            details['current_revision']
        ]
        commit_message: str = current_revision['commit']['message']

        comments: list[str] = []

        for revision in details['revisions'].values():
            if revision.get('description'):
                comments.append(revision['description'])

        comments_result: dict[str, Any] = self.m.gerrit.list_change_comments(
            "list change comments",
            change_id,
            test_data=self.m.json.test_api.output(
                {
                    '/PATCHSET_LEVEL': [{'message': ''}],
                }
            ),
        ).json.output

        for _, comment_data in comments_result.items():
            comments.extend(x['message'] for x in comment_data)

        return ChangeWithComments(change, details, commit_message, comments)

    def find_matching_comment(
        self, rx: re.Pattern, comments: Sequence[str]
    ) -> str | None:
        """Find a comment in comments that matches regex object rx."""
        result: str | None = None
        with self.m.step.nest('checking comments'):
            for i, comment in enumerate(comments):
                with self.m.step.nest(f'comment ({i})') as pres:
                    pres.step_summary_text = comment
                    match: re.Match = re.search(rx, comment)
                    if match:
                        pres.step_summary_text = f'MATCH: {comment}'
                        result: str = match.group(0)
                        break

            if result:
                with self.m.step.nest('found'):
                    pass

        return result

    def build_metadata(self) -> dict[str, Any]:
        return {
            'bb_id': self.m.buildbucket.build.id,
            'swarming_id': self.m.swarming.task_id,
            'builder': self.m.buildbucket_util.full_builder_name(),
            'url': self.m.buildbucket_util.build_url,
            'triggers': [
                json.loads(json_format.MessageToJson(x))
                for x in self.m.scheduler.triggers
            ],
        }
