# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""
Recipe to autoroll CIPD packages pinned in CIPD ensure files.
TODO(atyfto): Merge into cipd_ensure_file_roller.py.
"""

from PB.infra.roller_metadata import RollerMetadata
from PB.recipes.fuchsia.cipd_json_roller import InputProperties

DEPS = [
    "fuchsia/auto_roller",
    "fuchsia/buildbucket_util",
    "fuchsia/cipd_ensure",
    "fuchsia/cipd_resolver",
    "fuchsia/git_checkout",
    "recipe_engine/cipd",
    "recipe_engine/file",
    "recipe_engine/json",
    "recipe_engine/path",
    "recipe_engine/properties",
    "recipe_engine/step",
]

PROPERTIES = InputProperties


def RunSteps(api, props):
    checkout_root, _ = api.git_checkout(repo=props.remote)
    updated_packages = roll_ensure_files(api, checkout_root, props)

    for cmd in props.postprocess_commands:
        api.step(
            f"run {cmd.path}",
            [checkout_root / cmd.path] + list(cmd.args),
        )

    commit_message = props.commit_message
    assert commit_message, "commit_message property is required"

    if updated_packages:
        commit_message += "\n\n" + "\n".join(f"- {p}" for p in updated_packages) + "\n"

    change = api.auto_roller.attempt_roll(
        props.roll_options,
        repo_dir=checkout_root,
        commit_message=commit_message,
    )
    return api.auto_roller.raw_result(change)


def roll_ensure_files(api, checkout_root, props):
    ensure_files = []
    with api.step.nest("search for ensure files"):
        for glob in props.ensure_file_globs:
            ensure_files += api.file.glob_paths(f"glob `{glob}`", checkout_root, glob)

    updated_packages = []
    # Ensure all ensure files match their target ref.
    for ensure_file in ensure_files:
        # Get relpath with a stripped extension for a unique and valid step
        # name.
        ensure_file_relpath = api.path.relpath(
            api.path.splitext(ensure_file)[0],
            checkout_root,
        )
        with api.step.nest(f"read {ensure_file_relpath}") as presentation:
            # Roller metadata must have a specific filename within the ensure
            # file's directory. This can be changed if we decide there is a
            # better naming convention.
            metadata_path = ensure_file.parent / "roller_metadata.json"
            # Do not attempt to roll an ensure file that doesn't specify roller
            # metadata. We may decide at a future point that this should be an
            # opt-out instead of opt-in.
            api.path.mock_add_paths(metadata_path)
            if not api.path.exists(metadata_path):  # pragma: no cover
                continue
            metadata = api.cipd_ensure.get_roller_metadata(metadata_path)
            if metadata.do_not_autoroll:
                presentation.step_text = "autoroll disabled by roller metadata"
                continue
        with api.step.nest(f"ensure {ensure_file_relpath} is {metadata.ref}"):
            packages = api.cipd_ensure.get_packages(
                "get packages",
                ensure_file,
            )
            platforms = api.cipd_ensure.get_platforms(
                "get platforms",
                ensure_file,
            )
            expanded_packages = api.cipd_ensure.expand_packages_by_platforms(
                packages=packages,
                platforms=platforms,
            )
            candidate_versions = api.cipd_resolver.resolve_common_tags(
                ref=metadata.ref,
                # TODO(fxbug.dev/130779): Add a utility to resolve the tag
                # prefix of the packages in the ensure file, and remove `tag`
                # from the roller metadata.
                tag_name=metadata.tag,
                packages=expanded_packages,
            )
            updated_packages += api.cipd_ensure.update_packages(
                "update packages",
                ensure_file=ensure_file,
                packages=packages,
                version=candidate_versions[0],
            )
            api.cipd.ensure_file_resolve(ensure_file)

    return updated_packages


def GenTests(api):
    def resolved_tags(step_name, tags):
        return api.step_data(
            f"{step_name}.resolve common tags",
            api.json.output(tags),
        )

    yield (
        api.buildbucket_util.test("successful_roll")
        + api.properties(
            remote="https://example.googlesource.com/foo",
            commit_message="[roll] Update pinned packages",
            ensure_file_globs=[
                "subdir1/**/cipd.ensure",
                "subdir2/**/cipd.ensure",
            ],
            postprocess_commands=[
                {
                    "path": "scripts/foo.sh",
                    "args": ["-a", "bar"],
                }
            ],
            roll_options=api.auto_roller.Options(
                remote="https://example.googlesource.com/foo",
            ),
        )
        + api.step_data(
            "search for ensure files.glob `subdir1/**/cipd.ensure`",
            api.file.glob_paths(
                [
                    "subdir1/a/cipd.ensure",
                    "subdir1/b/cipd.ensure",
                ]
            ),
        )
        + api.step_data(
            "search for ensure files.glob `subdir2/**/cipd.ensure`",
            api.file.glob_paths(
                [
                    "subdir2/c/cipd.ensure",
                ]
            ),
        )
        + api.cipd_ensure.get_packages(
            "ensure subdir1/a/cipd is latest.get packages",
            {"path/to/tool": "version:pinned-version"},
        )
        + resolved_tags(
            "ensure subdir1/a/cipd is latest",
            ["version:pinned-version"],
        )
        + api.cipd_ensure.get_packages(
            "ensure subdir1/b/cipd is latest.get packages",
            {"path/to/tool": "version:old"},
        )
        + resolved_tags(
            "ensure subdir1/b/cipd is latest",
            ["version:new-version-to-pin"],
        )
        + api.cipd_ensure.update_packages(
            "ensure subdir1/b/cipd is latest.update packages",
            ["path/to/tool"],
        )
        + api.step_data(
            "read subdir2/c/cipd.read roller metadata",
            api.file.read_proto(
                RollerMetadata(
                    ref="latest",
                    do_not_autoroll=True,
                    tag="version",
                ),
            ),
        )
        + api.auto_roller.success()
    )
