# Copyright 2024 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 rolling of Android Repo Tool projects."""

import collections
import contextlib
import dataclasses
import re
from typing import Generator, List

from PB.recipe_engine import result as result_pb2
from PB.go.chromium.org.luci.buildbucket.proto import common as common_pb2
from PB.recipe_modules.pigweed.repo_roll.tests.full import InputProperties
from recipe_engine import post_process, recipe_test_api

DEPS = [
    'fuchsia/gitiles',
    'fuchsia/roll_commit_message',
    'pigweed/checkout',
    'pigweed/repo_roll',
    'recipe_engine/buildbucket',
    'recipe_engine/properties',
    'recipe_engine/step',
]

PROPERTIES = InputProperties


def RunSteps(api, props):
    checkout = api.checkout.fake_context()
    checkout.options.remote = 'https://host.googlesource.com/manifest'
    checkout.options.manifest_file = 'default.xml'

    for project in props.projects:
        with contextlib.ExitStack() as stack:
            if len(props.projects) != 1:  # pragma: no cover
                stack.enter(api.step.nest(project.path_to_update))
            rolls = api.repo_roll.update_project(checkout, project)
            assert len(rolls) <= 1

            if rolls:
                roll = rolls[0]
                with api.step.nest('roll'):
                    dir = api.step.empty('repo_url').presentation
                    dir.step_summary_text = roll.repo_url

                    dir = api.step.empty('repo_short_name').presentation
                    dir.step_summary_text = roll.repo_short_name

                    old = api.step.empty('old_revision').presentation
                    old.step_summary_text = roll.old_revision

                    new = api.step.empty('new_revision').presentation
                    new.step_summary_text = roll.new_revision

                    message = api.step.empty('commit message').presentation
                    message.step_summary_text = api.roll_commit_message.format(
                        *rolls,
                        send_comment=True,
                    )


def GenTests(api) -> Generator[recipe_test_api.TestData, None, None]:
    """Create tests."""

    def properties(*projects):
        props = InputProperties()
        props.projects.extend(projects)
        return api.properties(props)

    yield api.test(
        'success',
        properties(api.repo_roll.project('a1')),
        api.buildbucket.ci_build(git_repo='https://foo.googlesource.com/a'),
        api.repo_roll.read_step_data('a1'),
        api.gitiles.log('a1.log a1', 'A'),
    )

    yield api.test(
        'name-not-found',
        properties(api.repo_roll.project('missing')),
        api.buildbucket.ci_build(git_repo='https://bar.googlesource.com/b'),
        api.repo_roll.read_step_data('missing'),
        status='FAILURE',
    )

    yield api.test(
        'equivalent',
        properties(api.repo_roll.project('b2')),
        api.repo_roll.read_step_data('b2'),
        api.gitiles.log('b2.log b2', 'A'),
    )

    yield api.test(
        'upstream-not-set',
        properties(api.repo_roll.project('c3')),
        api.buildbucket.ci_build(git_repo='https://bar.googlesource.com/c'),
        api.repo_roll.read_step_data('c3'),
        api.gitiles.log('c3.log c3', 'A'),
    )

    yield api.test(
        'upstream-not-set-revision-not-branch',
        properties(api.repo_roll.project('d4')),
        api.buildbucket.ci_build(git_repo='https://bar.googlesource.com/c'),
        api.repo_roll.read_step_data('d4'),
        status='FAILURE',
    )

    yield api.test(
        'no-trigger-with-upstream',
        properties(api.repo_roll.project('a1')),
        api.repo_roll.read_step_data('a1'),
        api.gitiles.log('a1.log a1', 'A'),
    )

    yield api.test(
        'no-trigger-with-revision-branch',
        properties(api.repo_roll.project('c3')),
        api.repo_roll.read_step_data('c3'),
        api.gitiles.log('c3.log c3', 'A'),
    )

    yield api.test(
        'no-trigger-with-revision-hash',
        properties(api.repo_roll.project('d4')),
        api.repo_roll.read_step_data('d4'),
        status='FAILURE',
    )

    yield api.test(
        'no-trigger-with-revision-tag',
        properties(api.repo_roll.project('e5')),
        api.repo_roll.read_step_data('e5'),
        status='FAILURE',
    )

    yield api.test(
        'backwards',
        properties(api.repo_roll.project('a1')),
        api.repo_roll.read_step_data('a1'),
        api.gitiles.log('a1.log a1', 'A', n=0),
    )

    yield api.test(
        'host-dot-dot',
        properties(api.repo_roll.project('f6')),
        api.buildbucket.ci_build(git_repo='https://host.googlesource.com/f'),
        api.repo_roll.read_step_data('f6'),
        api.gitiles.log('f6.log f6', 'A'),
    )

    yield api.test(
        'dotdot-prefix',
        properties(api.repo_roll.project('g7')),
        api.buildbucket.ci_build(
            git_repo='https://host.googlesource.com/prefix/g'
        ),
        api.repo_roll.read_step_data('g7'),
        api.gitiles.log('g7.log g7', 'A'),
    )

    yield api.test(
        'host-prefix',
        properties(api.repo_roll.project('h8')),
        api.buildbucket.ci_build(
            git_repo='https://host.googlesource.com/prefix/h'
        ),
        api.repo_roll.read_step_data('h8'),
        api.gitiles.log('h8.log h8', 'A'),
    )
