# 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 API for cipd_roll."""

from __future__ import annotations

from PB.recipe_modules.pigweed.cipd_roll.package import Package
from recipe_engine import recipe_test_api


class CipdRollTestApi(recipe_test_api.RecipeTestApi):
    """Test API for cipd_roller."""

    def package(self, cipd_path, old_version, platforms=None):
        result = {
            'path': cipd_path,
            'tags': [old_version],
            '_comment': 'comments should be preserved',
        }

        if platforms is not None:
            result['platforms'] = list(platforms)

        return result

    def describe(self, prefix, package_path, tags, **kwargs):
        return self.step_data(
            f'{prefix}.cipd describe {package_path}',
            self.m.cipd.example_describe(
                package_path,
                test_data_tags=[f'{name}:{value}' for name, value in tags],
            ),
            **kwargs,
        )

    def no_ref(self, prefix, package_paths):
        res = None
        for package_path in package_paths:
            step = self.describe(prefix, package_path, (), retcode=1)
            res = res + step if res else step
        return res

    def no_common_tags(self, prefix, package_paths, tagname='git_revision'):
        res = None
        for i, package_path in enumerate(package_paths):
            step = self.describe(prefix, package_path, ((tagname, i),))
            res = res + step if res else step
        return res

    def multiple_common_tags(
        self,
        prefix,
        package_paths,
        tagname='git_revision',
        versions=(1, 2, 3),
    ):
        res = None
        for package_path in package_paths:
            step = self.describe(
                prefix,
                package_path,
                tuple((tagname, x) for x in versions),
            )
            res = res + step if res else step
        return res

    def relaxing_works(self, prefix, package_paths, tagname='git_revision'):
        return self.step_data(
            f'{prefix}.find shared tag.cipd describe {package_paths[1]}',
            self.m.cipd.example_describe(
                package_paths[1],
                test_data_tags=[f'{tagname}:{0}'],
            ),
        )

    def relaxing_does_not_work(
        self,
        prefix,
        package_paths,
        tagname='git_revision',
    ):
        # No version of package_paths[1] with hoped-for tag.
        return self.step_data(
            f'{prefix}.find shared tag.cipd describe {package_paths[0]}',
            self.m.cipd.example_describe(package_paths[0]),
            retcode=1,
        ) + self.step_data(
            f'{prefix}.find shared tag.cipd describe {package_paths[1]}',
            self.m.cipd.example_describe(package_paths[1]),
            retcode=1,
        )

    def read_file_step_data(self, prefix, package_json_name, *packages):
        return self.step_data(
            f'{prefix}.read {package_json_name}',
            self.m.file.read_json({'packages': packages}),
        )

    def package_props(self, spec, **kwargs):
        kwargs.setdefault('spec', spec)
        kwargs.setdefault('ref', 'latest')
        kwargs.setdefault('tag', 'git_revision')
        kwargs.setdefault(
            'json_path',
            'pw_env_setup/py/pw_env_setup/cipd_setup/pigweed.json',
        )
        return Package(**kwargs)
