# Copyright (C) 2026 The Android Open Source Project
#
# 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
#
#      http://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.

"""Unittests for the command.py module."""

from typing import Iterable, List, Optional

import pytest

from command import Command


class FakeProject:
    """Minimal project double for Command.GetProjects tests."""

    def __init__(
        self,
        name,
        relpath,
        *,
        gitdir=None,
        derived_subprojects=None,
        sync_s=False,
    ):
        self.name = name
        self.relpath = relpath
        self.worktree = f"/work/{relpath}"
        self.manifest = None
        self.gitdir = gitdir or f"/git/{relpath}"
        self.sync_s = sync_s
        self.Exists = True
        self._derived_subprojects = derived_subprojects or []

    def GetDerivedSubprojects(self):
        return list(self._derived_subprojects)

    def MatchesGroups(self, _groups):
        return True

    def RelPath(self, local=True):
        return self.relpath


class FakeManifest:
    """Minimal manifest double for Command.GetProjects tests."""

    def __init__(
        self,
        projects: Iterable[FakeProject],
        *,
        all_projects: Optional[Iterable[FakeProject]] = None,
        effective_groups: str = "default",
    ):
        self.projects = list(projects)
        self.all_projects = (
            list(self.projects) if all_projects is None else list(all_projects)
        )
        self._effective_groups = effective_groups

        # all_projects may include projects owned by child manifests,
        # so only set this manifest on its direct projects.
        for project in self.projects:
            self._set_project_manifest(project)

    def _set_project_manifest(self, project: FakeProject) -> None:
        project.manifest = self
        for subproject in project.GetDerivedSubprojects():
            self._set_project_manifest(subproject)

    def GetManifestGroupsStr(self):
        return self._effective_groups

    def GetProjectsWithName(
        self, name: str, all_manifests: bool = False
    ) -> List[FakeProject]:
        projects = self.all_projects if all_manifests else self.projects
        return [project for project in projects if project.name == name]


class GroupMatchingFakeProject(FakeProject):
    """Fake project with predictable group matches for GetProjects tests.

    This lets the tests check which groups GetProjects uses without
    reimplementing Project.MatchesGroups.
    """

    def __init__(
        self,
        name: str,
        relpath: str,
        *,
        matching_groups: Iterable[str],
    ):
        super().__init__(name, relpath)
        self._matching_groups = set(matching_groups)

    def MatchesGroups(self, groups: Iterable[str]) -> bool:
        return bool(self._matching_groups.intersection(groups))


def test_get_projects_keeps_derived_subprojects_for_repeated_repo():
    """Derived subprojects are keyed by checkout path, not repo identity."""
    submodule_a = FakeProject(
        "submodule",
        "src/one/submodule",
        gitdir="/shared/modules/submodule.git",
    )
    submodule_b = FakeProject(
        "submodule",
        "src/two/submodule",
        gitdir="/shared/modules/submodule.git",
    )
    project_a = FakeProject(
        "project",
        "src/one",
        derived_subprojects=[submodule_a],
        sync_s=True,
    )
    project_b = FakeProject(
        "project",
        "src/two",
        derived_subprojects=[submodule_b],
        sync_s=True,
    )
    manifest = FakeManifest([project_a, project_b])
    cmd = Command(manifest=manifest)

    projects = cmd.GetProjects([])

    assert set(projects) == {project_a, project_b, submodule_a, submodule_b}


@pytest.mark.parametrize(
    "submodules_ok, sync_s, includes_submodule",
    [
        (None, False, False),
        (None, True, True),
        (True, False, True),
        (True, True, True),
        (False, False, False),
        (False, True, False),
    ],
)
def test_get_projects_submodule_override(
    submodules_ok, sync_s, includes_submodule
):
    """The CLI override takes precedence over a project's sync-s setting."""
    submodule = FakeProject("submodule", "project/submodule")
    project = FakeProject(
        "project",
        "project",
        derived_subprojects=[submodule],
        sync_s=sync_s,
    )
    cmd = Command(manifest=FakeManifest([project]))

    projects = cmd.GetProjects([], submodules_ok=submodules_ok)

    assert (submodule in projects) is includes_submodule


@pytest.mark.parametrize(
    ("groups", "expected_relpaths"),
    [
        (None, ["outer", "sub/child"]),
        ("", ["outer", "sub/child"]),
        ("override-group", ["sub/override"]),
    ],
    ids=("groups-omitted", "groups-empty", "explicit-override"),
)
def test_get_projects_uses_groups_from_each_manifest_unless_overridden(
    groups: Optional[str],
    expected_relpaths: List[str],
) -> None:
    """Use each manifest's effective groups unless the caller overrides them."""
    outer_project = GroupMatchingFakeProject(
        "outer",
        "outer",
        matching_groups={"outer-group"},
    )

    # Both child projects also match "outer". Reusing the outer manifest's
    # groups would therefore select both child projects.
    child_project = GroupMatchingFakeProject(
        "child",
        "sub/child",
        matching_groups={"outer-group", "child-group"},
    )
    override_project = GroupMatchingFakeProject(
        "override",
        "sub/override",
        matching_groups={"outer-group", "override-group"},
    )

    child_manifest = FakeManifest(
        [child_project, override_project],
        effective_groups="child-group",
    )
    outer_manifest = FakeManifest(
        [outer_project],
        all_projects=[outer_project, *child_manifest.projects],
        effective_groups="outer-group",
    )
    cmd = Command(manifest=outer_manifest)

    projects = cmd.GetProjects(
        [],
        manifest=outer_manifest,
        groups=groups,
        all_manifests=True,
    )

    assert [project.relpath for project in projects] == expected_relpaths


def test_get_projects_by_name_uses_groups_from_each_manifest() -> None:
    """Name matches use the groups from each project's owning manifest."""
    outer_project = GroupMatchingFakeProject(
        "shared",
        "outer/shared",
        matching_groups={"outer-group"},
    )
    child_project = GroupMatchingFakeProject(
        "shared",
        "sub/shared",
        matching_groups={"child-group"},
    )

    child_manifest = FakeManifest(
        [child_project],
        effective_groups="child-group",
    )
    outer_manifest = FakeManifest(
        [outer_project],
        all_projects=[outer_project, *child_manifest.projects],
        effective_groups="outer-group",
    )
    cmd = Command(manifest=outer_manifest)

    projects = cmd.GetProjects(
        ["shared"],
        manifest=outer_manifest,
        all_manifests=True,
    )

    assert [project.relpath for project in projects] == [
        "outer/shared",
        "sub/shared",
    ]
