# 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, spec, package_path, tags, **kwargs):
        return self.step_data(
            f'{spec}.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, spec, package_paths):
        res = None
        for package_path in package_paths:
            step = self.describe(spec, package_path, (), retcode=1)
            res = res + step if res else step
        return res

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

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

    def relaxing_works(self, spec, package_paths, tagname='git_revision'):
        return self.step_data(
            f'{spec}.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,
        spec,
        package_paths,
        tagname='git_revision',
    ):
        # No version of package_paths[1] with hoped-for tag.
        return self.step_data(
            f'{spec}.find shared tag.cipd describe {package_paths[0]}',
            self.m.cipd.example_describe(package_paths[0]),
            retcode=1,
        ) + self.step_data(
            f'{spec}.find shared tag.cipd describe {package_paths[1]}',
            self.m.cipd.example_describe(package_paths[1]),
            retcode=1,
        )

    def read_file_step_data(self, spec, package_json_name, *packages):
        return self.step_data(
            f'{spec}.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)
