# 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.
"""Set a "Verified" label with the results of CQ.

Find CLs where CQ has completed and set a label to +1 or -1 based on the status
of CQ. Also find CLs where CQ is running and clear that +1 or -1.
"""

import collections
import re

from recipe_engine import post_process, recipe_test_api
from PB.go.chromium.org.luci.buildbucket.proto import common
from PB.recipe_engine import result
from PB.recipes.pigweed.cq_label import InputProperties
from RECIPE_MODULES.fuchsia.auto_roller.api import (
    FAILED_DRY_RUN_MESSAGES,
    PASSED_DRY_RUN_MESSAGES,
)

DEPS = [
    'fuchsia/auto_roller',
    'fuchsia/gerrit',
    'fuchsia/status_check',
    'recipe_engine/json',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = InputProperties


def _summary(api, host, change_id, action):
    return '[{change_id}](https://{host}/{change_id}): {action}'.format(
        change_id=change_id,
        host=api.gerrit.normalize_host(host),
        action=action,
    )


def _label_completed_unlabelled(
    api, host, projects, label, cq_account, dry_run,
):
    project_part = ' OR '.join(f'project:{p}' for p in projects)
    query_string = (
        f'is:open '
        f'-(label:Commit-Queue+1 OR label:Commit-Queue+2) '
        f'-(label:{label}-1 OR label:{label}+1) '
        f'(r:{cq_account} OR cc:{cq_account}) '
        f'({project_part}) '
    )

    changes = (
        api.gerrit.change_query(
            name='get unlabeled changes',
            query_string=query_string,
            host=host,
            max_attempts=5,
            timeout=30,
        )
        .get_result()
        .json.output
    )

    for change in changes or ():
        change_id = str(change['_number'])

        with api.step.nest(change_id) as pres:
            pres.links[
                change_id
            ] = f'https://{api.gerrit.normalize_host(host)}/{change_id}'

            details = (
                api.gerrit.change_details(
                    'details',
                    change_id,
                    query_params=['CURRENT_REVISION'],
                    host=host,
                )
                .get_result()
                .json.output
            )

            patch = details['revisions'][details['current_revision']]['_number']
            value = 0
            # Look at messages in reverse order so we always set based on the
            # most recent CQ results.
            for message in reversed(details['messages']):
                if message['author']['email'] != cq_account:
                    continue

                if not message['message'].startswith(f'Patch Set {patch}:'):
                    continue

                for msg in PASSED_DRY_RUN_MESSAGES:
                    if msg in message['message']:
                        with api.step.nest('passed'):
                            value = 1
                            break

                for msg in FAILED_DRY_RUN_MESSAGES:
                    if msg in message['message']:
                        with api.step.nest('failed'):
                            value = -1
                            break

                if value:
                    break

            if value:
                if dry_run:
                    action = 'would set {} to {}'.format(label, value)
                    pres.step_summary_text = action
                    with api.step.nest(action):
                        pass

                else:
                    action = 'set {} to {}'.format(label, value)
                    pres.step_summary_text = action
                    api.gerrit.set_review(
                        action,
                        change_id,
                        labels={label: value},
                        host=host,
                        notify='NONE',
                    )

                yield _summary(api, host, change_id, action)

            else:
                pres.step_summary_text = 'no action'


def _remove_running_labelled(api, host, projects, label, cq_account, dry_run):
    project_part = ' OR '.join('project:{}'.format(p) for p in projects)
    query_string = (
        f'is:open '
        f'(label:Commit-Queue+1 OR label:Commit-Queue+2) '
        f'(label:{label}-1 OR label:{label}+1) '
        f'(r:{cq_account} OR cc:{cq_account}) '
        f'({project_part}) '
    )

    changes = (
        api.gerrit.change_query(
            name='get labeled changes',
            query_string=query_string,
            host=host,
            max_attempts=5,
            timeout=30,
        )
        .get_result()
        .json.output
    )

    for change in changes or ():
        change_id = str(change['_number'])

        with api.step.nest(change_id) as pres:
            pres.links[
                change_id
            ] = f'https://{api.gerrit.normalize_host(host)}/{change_id}'

            if dry_run:
                action = f'would clear {label}'
                pres.step_summary_text = action
                with api.step.nest(action):
                    pass

            else:
                action = f'clear {label}'
                pres.step_summary_text = action
                api.gerrit.set_review(
                    action,
                    change_id,
                    labels={label: 0},
                    host=host,
                    notify='NONE',
                )

            yield _summary(api, host, change_id, action)


def RunSteps(api, props):
    assert re.match(r'^[-\w]+$', props.label)
    assert re.match(r'^[-\w.@]+$', props.cq_account)

    projects_by_host = collections.defaultdict(list)
    for repo in props.repo:
        match = re.search(
            r'^https://(?P<host>.*).googlesource.com/(?P<project>.*)$', repo,
        )
        assert match, repo
        host = match.group('host')
        project = match.group('project')
        projects_by_host[host].append(project)

    actions = []

    with api.step.defer_results():
        for host, projects in projects_by_host.items():
            with api.step.nest(host):
                actions.extend(
                    _label_completed_unlabelled(
                        api=api,
                        host=host,
                        projects=projects,
                        label=props.label,
                        cq_account=props.cq_account,
                        dry_run=props.dry_run,
                    )
                )

                actions.extend(
                    _remove_running_labelled(
                        api=api,
                        host=host,
                        projects=projects,
                        label=props.label,
                        cq_account=props.cq_account,
                        dry_run=props.dry_run,
                    )
                )

    return result.RawResult(
        summary_markdown='\n\n'.join(actions), status=common.SUCCESS,
    )


def GenTests(api):
    CQ_BOT_ACCOUNT = 'cq-bot-account@gserviceaccount.com'
    VERIFIED_LABEL = 'CQ-Verified'
    PROJECT = 'pigweed'

    def properties(
        repo=(f'https://pigweed.googlesource.com/{PROJECT}'),
        cq_account=CQ_BOT_ACCOUNT,
        label=VERIFIED_LABEL,
        dry_run=False,
    ):
        if isinstance(repo, str):
            repo = [repo]

        return api.properties(
            repo=list(repo),
            cq_account=cq_account,
            label=label,
            dry_run=dry_run,
        )

    def unlabeled_query_results(project='pigweed'):
        return api.step_data(
            'pigweed.get unlabeled changes',
            api.json.output([{'_number': 1, 'project': project}]),
        )

    def labeled_query_results(project='pigweed'):
        return api.step_data(
            'pigweed.get labeled changes',
            api.json.output([{'_number': 1, 'project': project}]),
        )

    def message(patch_set, passed, author=CQ_BOT_ACCOUNT):
        passfail = FAILED_DRY_RUN_MESSAGES[0]
        if passed:
            passfail = PASSED_DRY_RUN_MESSAGES[0]

        return {
            'author': {'email': author,},
            'message': f'Patch Set {patch_set}: {passfail}',
        }

    def details(*messages, **kwargs):
        res = {
            'current_revision': 'h3110',
            'revisions': {'h3110': {'_number': 2}},
            'messages': list(messages),
            'project': PROJECT,
        }
        res.update(kwargs)
        return api.step_data('pigweed.1.details', api.json.output(res))

    def set_passed(label=VERIFIED_LABEL, dry_run=False):
        dry_run_part = 'would ' if dry_run else ''
        return api.post_process(
            post_process.MustRun, f'pigweed.1.{dry_run_part}set {label} to 1',
        )

    def set_failed(label=VERIFIED_LABEL, dry_run=False):
        dry_run_part = 'would ' if dry_run else ''
        return api.post_process(
            post_process.MustRun, f'pigweed.1.{dry_run_part}set {label} to -1',
        )

    def no_set(label=VERIFIED_LABEL):
        return (
            api.post_process(
                post_process.DoesNotRun, f'pigweed.1.set {label} to 1',
            )
            + api.post_process(
                post_process.DoesNotRun, f'pigweed.1.would set {label} to 1',
            )
            + api.post_process(
                post_process.DoesNotRun, f'pigweed.1.set {label} to -1',
            )
            + api.post_process(
                post_process.DoesNotRun, f'pigweed.1.would set {label} to -1',
            )
        )

    def does_not_clear(label=VERIFIED_LABEL):
        return api.post_process(
            post_process.DoesNotRun, f'pigweed.1.clear {label}',
        ) + api.post_process(
            post_process.DoesNotRun, f'pigweed.1.would clear {label}'
        )

    def clear(label=VERIFIED_LABEL, dry_run=False):
        dry_run_part = 'would ' if dry_run else ''
        return api.post_process(
            post_process.MustRun, f'pigweed.1.{dry_run_part}clear {label}',
        )

    yield (
        api.status_check.test('passed')
        + properties()
        + unlabeled_query_results()
        + details(message(2, True))
        + set_passed()
        + does_not_clear()
    )

    yield (
        api.status_check.test('failed')
        + properties()
        + unlabeled_query_results()
        + details(message(2, False))
        + set_failed()
        + does_not_clear()
    )

    yield (
        api.status_check.test('wrong-author')
        + properties()
        + unlabeled_query_results()
        + details(message(2, True, author='test@example.com'))
        + no_set()
        + does_not_clear()
    )

    yield (
        api.status_check.test('wrong-patchset')
        + properties()
        + unlabeled_query_results()
        + details(message(1, True))
        + no_set()
        + does_not_clear()
    )

    yield (
        api.status_check.test('dry-run')
        + properties(dry_run=True)
        + unlabeled_query_results()
        + details(message(2, True))
        + set_passed(dry_run=True)
        + does_not_clear()
    )

    yield (
        api.status_check.test('clear')
        + properties()
        + labeled_query_results()
        + no_set()
        + clear()
    )

    yield (
        api.status_check.test('clear-dryrun')
        + properties(dry_run=True)
        + labeled_query_results()
        + no_set()
        + clear(dry_run=True)
    )
