# 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.
"""Roll a CIPD package."""

import collections
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.cipd_roll.tests.full import InputProperties
from recipe_engine import recipe_test_api

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

PROPERTIES = InputProperties


def RunSteps(api, props):
    commit = api.cipd_roll.Commit()
    for pkg in props.packages:
        with api.step.nest(pkg.spec):
            roll = api.cipd_roll.process_package(
                api.path.start_dir / 'checkout',
                pkg,
            )
            if roll:
                commit.rolls.append(roll)

    if commit:
        pres = api.step.empty('commit').presentation
        pres.step_summary_text = commit.message()


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

    prefix = 'pigweed/host_tools/cp38'
    spec = f'{prefix}/${{platform}}'
    paths = (
        f'{prefix}/linux-amd64',
        f'{prefix}/windows-amd64',
    )

    def properties(packages, dry_run=True, **kwargs):
        props = InputProperties(**kwargs)
        props.packages.extend(packages)
        return api.properties(props)

    yield (
        api.test('success')
        + properties([api.cipd_roll.package_props(spec=spec)])
        + api.cipd_roll.read_file_step_data(
            spec,
            'pigweed.json',
            api.cipd_roll.package(
                spec,
                'git_revision:123',
                platforms=['linux-amd64', 'windows-amd64'],
            ),
        )
    )

    yield (
        api.test('rc', status='FAILURE')
        + properties([api.cipd_roll.package_props(spec=spec, tag='version')])
        + api.cipd_roll.read_file_step_data(
            spec,
            'pigweed.json',
            api.cipd_roll.package(
                spec,
                'version:123',
                platforms=['linux-amd64', 'windows-amd64'],
            ),
        )
        + api.cipd_roll.describe(spec, paths[0], (('version', '234-rc3'),))
        + api.cipd_roll.describe(spec, paths[1], (('version', '234-rc3'),))
    )

    yield (
        api.test('multiple')
        + properties(
            [
                api.cipd_roll.package_props(spec='foo/${platform}'),
                api.cipd_roll.package_props(spec='bar/${platform}'),
            ]
        )
        + api.cipd_roll.read_file_step_data(
            'foo/${platform}',
            'pigweed.json',
            api.cipd_roll.package(
                'foo/${platform}',
                'git_revision:foo123',
                platforms=['linux-amd64', 'windows-amd64'],
            ),
            api.cipd_roll.package(
                'bar/${platform}',
                'git_revision:bar123',
                platforms=['linux-amd64', 'windows-amd64'],
            ),
        )
        + api.cipd_roll.read_file_step_data(
            'bar/${platform}',
            'pigweed.json',
            api.cipd_roll.package(
                'foo/${platform}',
                'git_revision:397a2597cdc237f3026e6143b683be4b9ab60540',
                platforms=['linux-amd64', 'windows-amd64'],
            ),
            api.cipd_roll.package(
                'bar/${platform}',
                'git_revision:bar123',
                platforms=['linux-amd64', 'windows-amd64'],
            ),
        )
    )

    bad_spec = f'bad-{spec}'
    yield (
        api.test('bad_package_spec', status='FAILURE')
        + properties([api.cipd_roll.package_props(spec=bad_spec)])
        + api.cipd_roll.read_file_step_data(
            bad_spec,
            'pigweed.json',
            api.cipd_roll.package(spec, 'git_revision:123'),
        )
    )

    yield (
        api.test('no_common_tags', status='FAILURE')
        + properties([api.cipd_roll.package_props(spec=spec)])
        + api.cipd_roll.read_file_step_data(
            spec,
            'pigweed.json',
            api.cipd_roll.package(
                spec,
                'git_revision:123',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
        + api.cipd_roll.no_common_tags(spec, paths)
    )

    yield (
        api.test('no_common_tags_but_relaxing_ref_mismatch_helps')
        + properties(
            [api.cipd_roll.package_props(spec=spec, allow_mismatched_refs=True)]
        )
        + api.cipd_roll.read_file_step_data(
            spec,
            'pigweed.json',
            api.cipd_roll.package(
                spec,
                'git_revision:123',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
        # Package 0 exists at git_revision:0, package 1 at git_revision:1
        + api.cipd_roll.no_common_tags(spec, paths)
        # However, package 1 also exists at git_revision:0, so that revision is
        # good to use.
        + api.cipd_roll.relaxing_works(spec, paths)
    )

    yield (
        api.test(
            'no_common_tags_and_relaxing_ref_mismatch_does_not_help',
            status='FAILURE',
        )
        + properties(
            [api.cipd_roll.package_props(spec=spec, allow_mismatched_refs=True)]
        )
        + api.cipd_roll.read_file_step_data(
            spec,
            'pigweed.json',
            api.cipd_roll.package(
                spec,
                'git_revision:123',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
        # Package 0 exists at git_revision:0, package 1 at git_revision:1
        + api.cipd_roll.no_common_tags(spec, paths)
        # However, package 1 does not exist at git_revision:0.
        + api.cipd_roll.relaxing_does_not_work(spec, paths)
    )

    yield (
        api.test('multiple_common_tags')
        + properties([api.cipd_roll.package_props(spec=spec)])
        + api.cipd_roll.multiple_common_tags(spec, paths)
        + api.cipd_roll.read_file_step_data(
            spec,
            'pigweed.json',
            api.cipd_roll.package(
                spec,
                'git_revision:2',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
    )

    yield (
        api.test('missing_tag')
        + properties([api.cipd_roll.package_props(spec=spec)])
        + api.cipd_roll.multiple_common_tags(spec, paths)
        + api.cipd_roll.no_ref(spec, [f'{prefix}/fake-amd64'])
        + api.cipd_roll.read_file_step_data(
            spec,
            'pigweed.json',
            api.cipd_roll.package(
                spec,
                'git_revision:2',
                platforms=('linux-amd64', 'windows-amd64', 'fake-amd64'),
            ),
        )
    )

    no_curly_spec = 'pigweed/host_tools/linux-amd64'
    yield (
        api.test('no_curlies_in_spec')
        + properties([api.cipd_roll.package_props(spec=no_curly_spec)])
        + api.cipd_roll.read_file_step_data(
            no_curly_spec,
            'pigweed.json',
            api.cipd_roll.package(
                no_curly_spec,
                'git_revision:123',
                platforms=('linux-amd64', 'windows-amd64'),
            ),
        )
    )

    yield (
        api.test('platform-independent')
        + properties([api.cipd_roll.package_props(spec='foo/bar/baz')])
        + api.cipd_roll.read_file_step_data(
            'foo/bar/baz',
            'pigweed.json',
            api.cipd_roll.package(
                'foo/bar/baz',
                'git_revision:123',
                platforms=['linux-amd64', 'mac-amd64'],
            ),
        )
    )
