# 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.
"""Assorted checks that do not require checking out code."""

import functools
import re

from PB.recipes.pigweed.static_checks import InputProperties
from recipe_engine import post_process

DEPS = [
    'fuchsia/gerrit',
    'fuchsia/status_check',
    'pigweed/checkout',
    'pigweed/util',
    'recipe_engine/buildbucket',
    'recipe_engine/cq',
    'recipe_engine/json',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = InputProperties

PYTHON_VERSION_COMPATIBILITY = "PY3"


def nest_step(func):
    @functools.wraps(func)
    def wrapper(api, *args, **kwargs):
        name = func.__name__.strip('_').replace('_', ' ')
        with api.step.nest(name):
            return func(api, *args, **kwargs)

    return wrapper


@nest_step
def _check_docs(api, details, commit_message, comments, doc_file_extensions=()):
    """Check that docs are included in the CL.

    If doc_file_extensions is set make sure at least one document change is in
    the CL. Can be overridden by adding "No-Docs-Update-Reason:" to the commit
    message, a Gerrit comment, or a patchset description.
    """
    if not doc_file_extensions:
        with api.step.nest('doc changes not required'):
            return

    if 'no-docs-update-reason:' in commit_message.lower():
        raise api.step.StepFailure(
            'Found "No-Docs-Update-Reason:" in the commit message which is no '
            'longer allowed. Please use a Gerrit comment instead (i.e., click '
            '"Reply" in the Gerrit UI).'
        )

    match = api.util.find_matching_comment(
        re.compile(r'No-Docs-Update-Reason: \w.*'), comments,
    )
    if match:
        with api.step.nest('found No-Docs-Update-Reason'):
            return

    with api.step.nest('checking changed files') as pres:
        current_revision = details['revisions'][details['current_revision']]
        files = tuple(current_revision.get('files', ()))
        pres.step_summary_text = '\n'.join(files)
        for path in files:
            if path.endswith(tuple(str(x) for x in doc_file_extensions)):
                with api.step.nest('found') as pres:
                    pres.step_summary_text = path
                    return

        # Only check that all files are OWNERS files if there are files. This
        # makes testing easier and should have no effect in production except
        # to fail some CLs that don't modify files.
        if files and all(api.path.basename(x) == 'OWNERS' for x in files):
            with api.step.nest('no non-OWNERS files'):
                return

    raise api.step.StepFailure(
        'No *.rst or *.md changes in CL and no exception applies. Add docs '
        "or explain why they're not needed in a Gerrit comment with "
        '"No-Docs-Update-Reason: <reason>".'
    )


@nest_step
def _check_requires(api, change, details, dry_run=False, allow_requires=True):
    """Check the format of "Requires:" lines and warn for common mistakes."""
    warnings = []

    requires_rx = re.compile(r'^\s*(Require(?:s|d|):).*', re.IGNORECASE)
    paragraphs = details['message'].split('\n\n')

    def _warn(warning):
        with api.step.nest('warning') as pres:
            pres.step_summary_text = warning
        warnings.append(warning)

    for paragraph in paragraphs[0:-1]:
        for line in paragraph.split('\n'):
            match = requires_rx.match(line)
            if match:
                _warn(
                    'Found "Requires:"-like line outside final '
                    'paragraph: {!r}. To pull in another change when '
                    'testing this change in CQ, move the "Requires:" '
                    'line to be adjacent to the "Change-Id:" line. '
                    'Example:\n\nRequires: pigweed:1234\nChange-Id: '
                    'I0123456789012345678901234567890123456789\n'.format(
                        match.group(0)
                    )
                )

    has_requires_line = False
    for line in paragraphs[-1].split('\n'):
        match = requires_rx.match(line)
        if match:
            if match.group(1) != 'Requires:':
                _warn(
                    'Found invalid "Requires:"-like line: {!r}. The line '
                    'should start with "Requires:" or be removed from the '
                    'final paragraph.'.format(match.group(0))
                )

        if line.startswith('Requires:'):
            has_requires_line = True

    if not allow_requires and has_requires_line:
        _warn(
            'Found "Requires:" line {!r} but they are not allowed for '
            'this repository.'.format(line)
        )

    if has_requires_line:
        for label in details['labels']:
            if 'autosubmit' in label.lower().replace('-', ''):
                if 'approved' in details['labels'][label]:
                    _warn(
                        'Using "Requires:" lines with "{}" is not permitted. '
                        'See http://go/pigweed-ci-cq-intro#dependent-cls for '
                        'information about ensuring dependent CLs are '
                        'submitted in the right order.'.format(label)
                    )

    if warnings and not dry_run:
        api.gerrit.set_review(
            'set review',
            str(change.change),
            host=change.host,
            message='\n\n'.join(warnings),
            revision=details['current_revision'],
            notify='OWNER',
        )


@nest_step
def _check_regexp(api, change, details, regexp, failure_message):
    if re.match(regexp, details['message']):
        with api.step.nest('matches') as pres:
            pres.step_summary_text = regexp
            return

    with api.step.nest('does not match') as pres:
        pres.step_summary_text = '{!r} does not match {!r}'.format(
            details['message'], regexp,
        )

    if failure_message:
        with api.step.nest('more details') as details:
            details.step_summary_text = failure_message
            details.status = 'FAILURE'

    raise api.step.StepFailure('commit message regexp match failed')


@nest_step
def _check_dns(api, details):
    """Check that the commit message doesn't contain "do not submit"."""

    regexes = [
        re.compile(r'do.not.(submit|com+it|merge)', re.IGNORECASE),
        re.compile(r'\bWIP\b', re.IGNORECASE),
    ]

    for regex in regexes:
        match = regex.search(details['message'])
        if match:
            raise api.step.StepFailure(
                'found "{}" in commit message'.format(match.group(0))
            )


@nest_step
def _check_tested(api, details):
    """Check for a "Tested:" line in the commit message."""

    for line in details['message'].split('\n'):
        if line.lower().startswith('tested:'):
            with api.step.nest('found tested line in commit message') as pres:
                pres.step_summary_text = line
                return

    raise api.step.StepFailure(
        'could not find "Tested:" line in commit message'
    )


def _check_readability(api, details, comments, readability):
    """Check that the readability label has been approved.

    Check that the readability label has been approved if files matching
    readability.file_extensions are in the CL.
    """

    with api.step.nest(readability.label):
        if api.cq.active and api.cq.run_mode != 'FULL_RUN':
            with api.step.nest('dry run'):
                return

        if readability.label not in details['labels']:
            with api.step.nest('no such label'):
                return

        # "approved" would mean +2 if values are [-2,+2].
        if 'approved' in details['labels'][readability.label]:
            with api.step.nest('label approved'):
                return

        # "recommended" would mean +1 if values are [-2,+2].
        if readability.allow_recommended:
            if 'recommended' in details['labels'][readability.label]:
                with api.step.nest('label recommended'):
                    return

        skip_line = 'Skip-{}-Justification'.format(readability.label)

        match = api.util.find_matching_comment(
            re.compile(r'{}: \w+'.format(skip_line)), comments,
        )
        if match:
            with api.step.nest('found {}'.format(skip_line)):
                return

        current_revision = details['revisions'][details['current_revision']]
        files = sorted(current_revision.get('files', ()))
        with api.step.nest('files') as pres:
            pres.step_summary_text = '\n'.join(files)
        for path in files:
            if path.endswith(tuple(readability.file_extensions)):
                raise api.step.StepFailure(
                    '{} not set but {} changed. If necessary this requirement '
                    'can be bypassed by adding a Gerrit comment like '
                    '"{}: <reason>"'.format(readability.label, path, skip_line,)
                )

        with api.step.nest('no matching files'):
            pass


def RunSteps(api, props):
    res = api.util.get_change_with_comments()
    change = res.change
    details = res.details
    commit_message = res.commit_message
    comments = res.comments

    api.cq.set_do_not_retry_build()

    # Make it just a little easier to retrieve the current commit message later.
    current_revision = details['revisions'][details['current_revision']]
    details['message'] = current_revision['commit']['message']

    with api.step.nest('checking if revert') as pres:
        pres.step_summary_text = str(details['revert_of'])
        if details['revert_of']:
            with api.step.nest('ignored'):
                return

    with api.step.nest('checking owner account') as pres:
        owner = details['owner']['email']
        pres.step_summary_text = owner
        if owner in props.ignored_accounts:
            with api.step.nest('ignored'):
                return

    _check_docs(api, details, commit_message, comments, props.doc_extensions)

    _check_requires(
        api,
        change,
        details,
        dry_run=props.dry_run,
        allow_requires=not props.forbid_requires,
    )

    if props.require_tested:
        _check_tested(api, details)

    if props.commit_message_regexp:
        _check_regexp(
            api,
            change,
            details,
            str(props.commit_message_regexp),
            str(props.commit_message_regexp_failure_message),
        )

    _check_dns(api, details)

    for readability in props.readability:
        _check_readability(api, details, comments, readability)


def change_details(
    api,
    msg,
    description='',
    files=(),
    owner='nobody@example.com',
    revert_of=0,
    votes=None,
):
    labels = {}
    if votes:
        for k, v in votes.items():
            labels[k] = {}
            if v is not None:
                assert v in "approved recommended disliked rejected".split()
                labels[k][v] = True

    return api.step_data(
        'change details',
        api.json.output(
            {
                'current_revision': 'HASH',
                'revisions': {
                    'HASH': {
                        '_number': 1,
                        'commit': {
                            'subject': msg.split('\n')[0],
                            'message': msg,
                            'parents': [{'commit': 'PARENT',}],
                        },
                        'files': {x: {} for x in files},
                        'description': description,
                    }
                },
                'owner': {'email': owner},
                'revert_of': revert_of,
                'labels': labels,
            },
        ),
    )


def must_run(api, step):
    return api.post_process(post_process.MustRun, step)


def requires_tests(api):
    def check_num_warnings(n):
        if not n:
            return api.post_process(
                post_process.DoesNotRun, 'check requires.warning'
            )

        else:
            # Make sure the first warning is found.
            result = must_run(api, 'check requires.warning')

            # Make sure the nth warning is also found.
            if n > 1:
                result += must_run(api, 'check requires.warning ({})'.format(n))

            # Make sure the nth warning is the last one.
            result += api.post_process(
                post_process.DoesNotRun,
                'check requires.warning ({})'.format(n + 1),
            )

            return result

    def requires_test(
        name, msg, warnings=0, status='success', votes=None, **kwargs
    ):
        res = api.status_check.test('requires.{}'.format(name), status=status)
        res += api.properties(**kwargs)
        res += api.checkout.try_test_data()
        res += change_details(api, msg, votes=votes)
        res += check_num_warnings(warnings)
        return res

    yield requires_test('no-requires', '')

    yield requires_test('valid', 'Foo\n\nRequires: foo:123')

    yield requires_test(
        'forbid', 'Foo\n\nRequires: foo:123', forbid_requires=True, warnings=1
    )

    yield requires_test(
        'first-paragraph', 'Requires: foo:123\n\nChange-Id: I1', warnings=1,
    )
    yield requires_test(
        'middle-paragraph',
        'Foo\n\nRequires: foo:123\n\nChange-Id: I1',
        warnings=1,
    )

    yield requires_test('require', 'Foo\n\nRequire: foo:123', warnings=1)
    yield requires_test('required', 'Foo\n\nRequired: foo:123', warnings=1)
    yield requires_test('case', 'Foo\n\nrEqUiReS: foo:123', warnings=1)

    yield requires_test(
        'multiple-warnings',
        'Foo\n\nRequires: foo:123\n\nrEqUiReS: foo:123',
        warnings=2,
    )

    yield requires_test(
        'requires-with-autosubmit',
        'Foo\n\nRequires: 123\nChange-Id: I1',
        votes={'auto-submit': 'approved'},
        warnings=1,
    )


def tested_tests(api):
    def test(name, msg, status='success', require_tested=True, **kwargs):
        res = api.status_check.test('tested.{}'.format(name), status=status)
        res += api.properties(require_tested=require_tested, **kwargs)
        res += api.checkout.try_test_data()
        res += change_details(api, msg)
        return res

    def tested_passes():
        return must_run(api, 'check tested.found tested line in commit message')

    def owner_ignored():
        return must_run(api, 'checking owner account.ignored')

    yield (test('tested-pass', 'Tested: maybe',) + tested_passes())

    yield test('tested-fail', 'Test: nope', status='failure')

    yield (
        test(
            'tested-skip',
            'Test: nope',
            ignored_accounts=['nobody@example.com'],
        )
        + owner_ignored()
    )


def docs_tests(api):
    def test(name, msg='', status='success', properties=None, **kwargs):
        final_props = {'doc_extensions': ['.rst', '.md']}
        if properties:
            final_props.update(properties)
        return (
            api.status_check.test('docs.{}'.format(name), status=status)
            + api.properties(**final_props)
            + change_details(api, msg=msg, **kwargs)
        )

    def comment(with_exception):
        message = 'Unrelated comment'
        if with_exception:
            message = 'No-Docs-Update-Reason: laziness'

        return api.util.change_comment(message, prefix='')

    yield (
        test('no_doc_changes', status='failure')
        + comment(with_exception=False)
        + api.checkout.try_test_data()
    )

    yield (
        test('has_doc_changes', files=('foo.rst',))
        + api.checkout.try_test_data()
        + must_run(api, 'check docs.checking changed files.found')
    )

    yield (
        test(
            'no_doc_changes_properties',
            status='failure',
            files=('foo.rst',),
            properties={'doc_extensions': ['.gn']},
        )
        + api.checkout.try_test_data()
    )

    yield (
        test(
            'has_doc_changes_properties',
            files=('foo.gn',),
            properties={'doc_extensions': ['.gn']},
        )
        + api.checkout.try_test_data()
        + must_run(api, 'check docs.checking changed files.found')
    )

    yield (
        test(
            'commit-message-ignored',
            status='failure',
            msg='No-Docs-Update-Reason: foo',
        )
        + api.checkout.try_test_data()
    )

    yield (
        test('owners-files', files=('foo/OWNERS', 'OWNERS'))
        + api.checkout.try_test_data()
        + must_run(api, 'check docs.checking changed files.no non-OWNERS files')
    )

    yield (
        test('gerrit-comment')
        + api.checkout.try_test_data()
        + comment(with_exception=True)
        + must_run(api, 'check docs.checking comments.found')
    )

    yield (
        test(
            'owner',
            owner='roller@example.com',
            properties={'ignored_accounts': ['roller@example.com']},
        )
        + api.checkout.try_test_data()
        + must_run(api, 'checking owner account.ignored')
    )

    yield (
        test('revert', revert_of=123456)
        + api.checkout.try_test_data()
        + must_run(api, 'checking if revert.ignored')
    )


def readability_tests(api):
    def test(name, msg='', status='success', **kwargs):
        final_props = {
            'readability': [
                {
                    'label': 'Readability',
                    'file_extensions': (
                        '.c .cc .cpp .cxx .C .h .hh .hpp .hxx .H'.split()
                    ),
                    'allow_recommended': True,
                },
            ],
        }

        return (
            api.status_check.test('readability.{}'.format(name), status=status)
            + api.properties(**final_props)
            + change_details(api, msg=msg, **kwargs)
            + api.cq(api.cq.FULL_RUN)
        )

    def comment(message='unrelated'):
        return api.util.change_comment(message, prefix='')

    yield (
        test('no_cpp_changes', votes={'Readability': None})
        + api.checkout.try_test_data()
        + must_run(api, 'Readability.no matching files')
    )

    yield (
        test(
            'has_cpp_changes_no_vote',
            files=('foo.cpp',),
            votes={'Readability': None},
            status='failure',
        )
        + api.checkout.try_test_data()
        + comment()
    )

    yield (
        test(
            'has_cpp_changes_approved',
            files=('foo.cpp',),
            votes={'Readability': 'approved'},
        )
        + api.checkout.try_test_data()
        + must_run(api, 'Readability.label approved')
    )

    yield (
        test(
            'has_cpp_changes_recommended',
            files=('foo.cpp',),
            votes={'Readability': 'recommended'},
        )
        + api.checkout.try_test_data()
        + must_run(api, 'Readability.label recommended')
    )

    yield (
        test(
            'has_cpp_changes_justification',
            files=('foo.cpp',),
            votes={'Readability': None},
        )
        + api.checkout.try_test_data()
        + comment('Skip-Readability-Justification: because')
        + must_run(api, 'Readability.found Skip-Readability-Justification')
    )

    yield (
        test('has_cpp_changes_no_label', files=('foo.cpp',))
        + api.checkout.try_test_data()
        + must_run(api, 'Readability.no such label')
    )

    yield (
        test('dry_run', files=('foo.cpp',))
        + api.cq(api.cq.DRY_RUN)
        + api.checkout.try_test_data()
        + must_run(api, 'Readability.dry run')
    )


def regexp_tests(api):
    def test(name, msg, regexp, failure_msg='', status='success', **kwargs):
        res = api.status_check.test('regexp.{}'.format(name), status=status)
        res += api.properties(
            commit_message_regexp=regexp,
            commit_message_regexp_failure_message=failure_msg,
        )
        res += api.checkout.try_test_data()
        res += change_details(api, msg)
        return res

    yield (
        test(
            'pass',
            'Bug: pwbug/99999999999999999999999999999999999999999999999999999',
            regexp='.*Bug: pwbug/\d+.*',
        )
        + must_run(api, 'check regexp.matches')
    )

    yield (
        test('fail', 'message', regexp='.*Bug: pwbug/\d+.*', status='failure',)
        + must_run(api, 'check regexp.does not match')
    )

    yield (
        test(
            'fail-msg',
            'message',
            regexp='.*Bug: pwbug/\d+.*',
            failure_msg='Did not reference a bug.',
            status='failure',
        )
        + must_run(api, 'check regexp.does not match')
        + must_run(api, 'check regexp.more details')
    )


def GenTests(api):
    for test in requires_tests(api):
        yield test

    for test in tested_tests(api):
        yield test

    for test in docs_tests(api):
        yield test

    for test in readability_tests(api):
        yield test

    for test in regexp_tests(api):
        yield test

    yield (
        api.status_check.test('do-not-submit', status='failure')
        + api.buildbucket.try_build()
        + change_details(api, 'Do_NoT-sUbMiT')
    )
