# 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 Any, Sequence

import attrs
from google.protobuf import json_format
from PB.go.chromium.org.luci.buildbucket.proto import (
    build as build_pb2,
    common as common_pb2,
)
from recipe_engine import recipe_api


@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
            ],
        }
