# 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."""

from __future__ import annotations

import collections
import dataclasses
import re
from typing import TYPE_CHECKING

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

if TYPE_CHECKING:  # pragma: no cover
    from typing import Generator, List
    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.update_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',
        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'),)),
        status='FAILURE',
    )

    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',
        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'),
        ),
        status='FAILURE',
    )

    yield api.test(
        'no_common_tags',
        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),
        status='FAILURE',
    )

    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',
        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),
        status='FAILURE',
    )

    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'],
            ),
        ),
    )
