# Copyright 2020 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.
"""Test of rolls of one repository."""

from __future__ import annotations

from typing import TYPE_CHECKING

from PB.recipes.pigweed.submodule_roller import InputProperties
from PB.recipe_modules.fuchsia.auto_roller.options import Options
from recipe_engine import config, recipe_api

if TYPE_CHECKING:  # pragma: no cover
    from typing import Generator
    from recipe_engine import recipe_test_api

DEPS = [
    'pigweed/roll_util',
    'recipe_engine/path',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = {
    'project_name': recipe_api.Property(kind=str),
    'original_commits': recipe_api.Property(kind=config.List),
    'old_revision': recipe_api.Property(kind=str),
    'new_revision': recipe_api.Property(kind=str),
}


def RunSteps(  # pylint: disable=invalid-name
    api, project_name, old_revision, new_revision
):
    proj_dir = api.path.start_dir / 'project'

    direction = api.roll_util.get_roll_direction(
        api.path.start_dir / 'checkout', old_revision, new_revision
    )
    if api.roll_util.can_roll(direction):
        roll = api.roll_util.create_roll(
            project_name=project_name,
            old_revision=old_revision,
            new_revision=new_revision,
            proj_dir=proj_dir,
            direction=direction,
        )

        def steplog(name, value):
            with api.step.nest(name) as pres:
                pres.step_summary_text = repr(value)

        steplog('remote', roll.remote)
        steplog('gerrit_name', roll.gerrit_name)

        with api.step.nest('emails') as pres:
            pres.logs['authors'] = sorted(
                x.email for x in api.roll_util.authors(roll)
            )
            pres.logs['reviewers'] = sorted(
                x.email for x in api.roll_util.reviewers(roll)
            )

        message = api.roll_util.message(roll)
        with api.step.nest('message') as pres:
            pres.logs['message'] = message

    else:
        api.roll_util.skip_roll_step('remote', old_revision, new_revision)

    host = 'pigweed-review.googlesource.com'

    api.roll_util.can_cc_on_roll('email@example.com', host)
    api.roll_util.can_cc_on_roll('nobody@google.com', host)

    Account = api.roll_util.Account
    user = Account('user', 'user@example.com')

    assert (
        api.roll_util.fake_author(user).email
        == 'user@pigweed.infra.roller.example.com'
    )

    with api.step.nest('CCing'):
        api.roll_util.include_cc(user, ('example.com',), host)
    with api.step.nest('not CCing, domain excluded'):
        api.roll_util.include_cc(user, ('google.com',), host)
    with api.step.nest('not CCing, robot account'):
        api.roll_util.include_cc(
            Account('robot', 'robot@gserviceaccount.com'),
            (),
            host,
        )
    with api.step.nest('not CCing, no account in Gerrit'):
        api.roll_util.include_cc(
            Account('nobody', 'nobody@google.com'),
            (),
            host,
        )

    auto_roller_options = Options(upstream_ref="upstream_ref")
    auto_roller_options.push_options.append("push_option_1")
    override_auto_roller_options = Options()
    override_auto_roller_options.push_options.append("push_option_2")
    complete_auto_roller_options = api.roll_util.merge_auto_roller_overrides(
        auto_roller_options, override_auto_roller_options
    )
    # check that upstream_ref is not overwritten and push_options is merged
    assert complete_auto_roller_options.upstream_ref == "upstream_ref"
    assert complete_auto_roller_options.push_options == [
        "push_option_1",
        "push_option_2",
    ]


def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]:
    yield api.test(
        'singlecommit_singleline',
        api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='1' * 40
        ),
        api.roll_util.properties(
            commit_divider='--divider--',
            footer='Cq-Include-Trybots: foo',
        ),
        api.roll_util.commit_data(
            'proj',
            api.roll_util.commit('1' * 40, 'foo\n\nbar\n\nChange-Id: I11111'),
        ),
        api.roll_util.forward_roll(),
        api.roll_util.not_cancelled(),
    )

    yield api.test(
        'singlecommit_multiline',
        api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='1' * 40
        ),
        api.roll_util.properties(commit_divider='--divider--'),
        api.roll_util.commit_data(
            'proj',
            api.roll_util.commit(
                '1' * 40,
                'foo  ' * 20
                + '\n\nbar\n\nBug: 123\nCC: foo\nFoo-Auto-Submit: true\n',
            ),
        ),
        api.roll_util.forward_roll(),
        api.roll_util.not_cancelled(),
    )

    yield api.test(
        'multicommit',
        api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='4' * 40
        ),
        api.roll_util.commit_data(
            'proj',
            api.roll_util.commit('4' * 40, 'xyz\n\nxyz'),
            api.roll_util.commit('3' * 40, 'baz\n\nbaz'),
            api.roll_util.commit(
                '2' * 40, ''.join(x * 10 for x in '0123456789')
            ),
            api.roll_util.commit('1' * 40, 'foo\n\nfoo'),
        ),
        api.roll_util.forward_roll(),
        api.roll_util.not_cancelled(),
    )

    yield api.test(
        'manymanycommit',
        api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='4' * 40
        ),
        api.roll_util.commit_data(
            'proj',
            *[
                api.roll_util.commit(f'{i:040}', f'Commit {i}')
                for i in range(0, 600)
            ],
        ),
        api.roll_util.forward_roll(),
        api.roll_util.not_cancelled(),
    )

    yield api.test(
        'frombranch',
        api.properties(
            project_name='proj', old_revision='main', new_revision='5' * 40
        ),
        api.roll_util.commit_data(
            'proj',
            api.roll_util.commit('5' * 40, 'five'),
            api.roll_util.commit('4' * 40, 'four'),
            api.roll_util.commit('3' * 40, 'three'),
            api.roll_util.commit('2' * 40, 'two'),
            api.roll_util.commit('1' * 40, 'one'),
        ),
        api.roll_util.forward_roll(),
        api.roll_util.not_cancelled(),
    )

    yield api.test(
        'backwards',
        api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='1' * 40
        ),
        api.roll_util.backward_roll(),
        api.roll_util.cancelled(),
    )

    yield api.test(
        'up_to_date',
        api.properties(
            project_name='proj', old_revision='1' * 40, new_revision='1' * 40
        ),
        api.roll_util.cancelled(),
    )

    yield api.test(
        'up_to_date_testonly',
        api.properties(
            project_name='proj', old_revision='1' * 40, new_revision='2' * 40
        ),
        api.roll_util.noop_roll(),
        api.roll_util.cancelled(),
    )

    yield api.test(
        'rebase',
        api.properties(
            project_name='proj', old_revision='0' * 40, new_revision='5' * 40
        ),
        api.roll_util.commit_data(
            'proj',
            api.roll_util.commit('5' * 40, 'five'),
            api.roll_util.commit('4' * 40, 'four'),
            api.roll_util.commit('3' * 40, 'three'),
            api.roll_util.commit('2' * 40, 'two'),
            api.roll_util.commit('1' * 40, 'one'),
        ),
        api.roll_util.rebased_roll(),
        api.roll_util.not_cancelled(),
    )
