# Copyright 2025 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.
from __future__ import annotations

from collections.abc import Iterator

from recipe_engine import recipe_api, recipe_test_api

from PB.recipe_modules.pigweed.variable_roll.tests.git import GitInputProperties

DEPS = [
    'fuchsia/gitiles',
    'fuchsia/roll_commit_message',
    'pigweed/checkout',
    'pigweed/variable_roll',
    'recipe_engine/properties',
    'recipe_engine/step',
]

INLINE_PROPERTIES_PROTO = """
import "recipe_modules/pigweed/variable_roll/variable_entry.proto";

message GitInputProperties {
  // Text entries to update.
  repeated recipe_modules.pigweed.variable_roll.VariableEntry variable_entries = 1;

  string commit_divider = 2;
}
"""

PROPERTIES = GitInputProperties


def RunSteps(  # pylint: disable=invalid-name
    api: recipe_api.RecipeScriptApi,
    props: GitInputProperties,
):
    checkout = api.checkout.fake_context()

    assert len(props.variable_entries) == 1
    variable_entry = props.variable_entries[0]

    rolls = api.variable_roll.update(
        checkout=checkout,
        variable_entry=variable_entry,
    )

    if rolls:
        pres = api.step.empty('commit message').presentation
        pres.step_summary_text = api.roll_commit_message.format(
            *rolls,
            roll_prefix='roll:',
            send_comment=True,
        )


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

    def _url(x):
        assert ':' not in x
        return 'https://foo.googlesource.com/' + x

    def trigger(url, **kwargs):
        return api.checkout.ci_test_data(git_repo=_url(url), **kwargs)

    def properties(*variable_entries, **kwargs):
        props = GitInputProperties(**kwargs)
        props.variable_entries.extend(variable_entries)
        return api.properties(props)

    yield api.test(
        'success',
        properties(
            api.variable_roll.entry(
                path='foo.py',
                variable='FOO',
                remote=_url('foo'),
            ),
            commit_divider='--divider--',
        ),
        trigger('foo'),
        api.gitiles.log('foo.py[FOO].log foo.py[FOO]', 'A'),
    )

    yield api.test(
        'backwards',
        properties(
            api.variable_roll.entry(
                path='foo.py',
                variable='FOO',
                remote=_url('foo'),
            ),
        ),
        api.gitiles.log('foo.py[FOO].log foo.py[FOO]', 'A', n=0),
    )

    yield api.test(
        'missing',
        properties(
            api.variable_roll.entry(
                path='foo.py',
                variable='VAR',
                remote=_url('foo'),
            ),
        ),
    )
