# Copyright 2023 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.
"""Full test of bazel module."""

from __future__ import annotations

import dataclasses
import re
from collections.abc import Iterator

from recipe_engine import (
    config_types,
    post_process,
    recipe_api,
    recipe_test_api,
)

from PB.recipe_modules.pigweed.bazel.tests.rbe_arguments import (
    RbeInputProperties,
)

DEPS = [
    'pigweed/bazel',
    'recipe_engine/buildbucket',
    'recipe_engine/platform',
    'recipe_engine/properties',
    'recipe_engine/step',
]

INLINE_PROPERTIES_PROTO = """
message RbeInputProperties {
  bool remote = 1;
  bool remote_cache = 2;
  bool upload_local_results = 3;
}
"""

PROPERTIES = RbeInputProperties


@dataclasses.dataclass
class _FakeCheckoutContext:
    root: config_types.Path
    bazel_overrides: dict[str, config_types.Path] = dataclasses.field(
        default_factory=dict
    )


def RunSteps(api: recipe_api.RecipeScriptApi, props: RbeInputProperties):
    args = api.bazel.rbe_arguments(
        remote=props.remote,
        remote_cache=props.remote_cache,
        upload_local_results=props.upload_local_results,
    )

    if not args:
        api.step.empty('(no arguments)')

    for arg in args:
        api.step.empty(arg)


def GenTests(api) -> Iterator[recipe_test_api.TestData]:
    def props(
        remote: bool = True,
        remote_cache: bool = True,
        upload_local_results: bool = True,
    ):
        return api.properties(
            RbeInputProperties(
                remote=remote,
                remote_cache=remote_cache,
                upload_local_results=upload_local_results,
            ),
        )

    def assert_no_args():
        return api.post_process(post_process.MustRun, '(no arguments)')

    def assert_match(pattern: re.Pattern | str):
        return api.post_process(post_process.MustRunRE, pattern)

    def assert_no_match(pattern: re.Pattern | str):
        return api.post_process(post_process.DoesNotRunRE, pattern)

    yield api.test(
        'remote',
        props(remote=True, remote_cache=True, upload_local_results=True),
        assert_match(r'--config=remote$'),
        assert_no_match(r'--config=remote_cache$'),
        assert_match(r'^--remote_upload_local_results=true$'),
        api.post_process(post_process.DropExpectation),
    )

    yield api.test(
        'remote_cache',
        props(remote=False, remote_cache=True, upload_local_results=True),
        assert_match(r'--config=remote_cache$'),
        assert_no_match(r'^--config=remote$'),
        assert_match(r'^--remote_upload_local_results=true$'),
        api.post_process(post_process.DropExpectation),
    )

    yield api.test(
        'no_upload_local_results',
        props(remote_cache=True, upload_local_results=False),
        assert_no_match(r'^--remote_upload_local_results=true$'),
        api.post_process(post_process.DropExpectation),
    )

    yield api.test(
        'disable_rbe',
        api.buildbucket.ci_build(experiments=['pigweed.disable_rbe']),
        assert_no_args(),
        api.post_process(post_process.DropExpectation),
    )

    yield api.test(
        'disable_github',
        api.buildbucket.ci_build(experiments=['pigweed.disable_github']),
        assert_no_args(),
        api.post_process(post_process.DropExpectation),
    )

    yield api.test(
        'mac_remote',
        props(remote=True),
        api.platform.name('mac'),
        assert_match(r'ignoring remote because not running on Linux'),
        api.post_process(post_process.DropExpectation),
    )

    yield api.test(
        'private_project',
        props(remote=True),
        api.buildbucket.ci_build(project='not-pigweed'),
        assert_match(r'--bes_instance_name=pigweed-rbe-private'),
        api.post_process(post_process.DropExpectation),
    )

    yield api.test(
        'tryjob_pre',
        props(remote=True),
        api.buildbucket.try_build(project='pigweed'),
        assert_match(r'--bes_instance_name=pigweed-rbe-open-pre'),
        api.post_process(post_process.DropExpectation),
    )

    yield api.test(
        'upload_but_no_cache_warning',
        props(remote=False, remote_cache=False, upload_local_results=True),
        assert_match(
            r'ignoring upload_local_results since remote_cache is False'
        ),
        api.post_process(post_process.DropExpectation),
    )
