"""Tests for find_orphans command."""

from pathlib import Path

from typer.testing import CliRunner

from repo_sync_kitty.cli import app
from repo_sync_kitty.commands.find_orphans import _find_git_repos
from repo_sync_kitty.util.git import is_git_repo


class TestIsGitRepo:
    """Tests for is_git_repo helper."""

    def test_returns_true_for_git_directory(self, tmp_path: Path) -> None:
        (tmp_path / ".git").mkdir()
        assert is_git_repo(tmp_path) is True

    def test_returns_false_without_git(self, tmp_path: Path) -> None:
        assert is_git_repo(tmp_path) is False

    def test_returns_false_for_nonexistent(self, tmp_path: Path) -> None:
        assert is_git_repo(tmp_path / "nonexistent") is False


class TestFindGitRepos:
    """Tests for _find_git_repos helper."""

    def test_finds_single_repo(self, tmp_path: Path) -> None:
        repo = tmp_path / "myrepo"
        repo.mkdir()
        (repo / ".git").mkdir()
        result = _find_git_repos(tmp_path)
        assert len(result) == 1
        assert result[0] == repo

    def test_finds_nested_repos(self, tmp_path: Path) -> None:
        r1 = tmp_path / "a" / "repo1"
        r1.mkdir(parents=True)
        (r1 / ".git").mkdir()
        r2 = tmp_path / "b" / "repo2"
        r2.mkdir(parents=True)
        (r2 / ".git").mkdir()
        result = _find_git_repos(tmp_path)
        assert len(result) == 2

    def test_stops_recursion_at_git_repo(self, tmp_path: Path) -> None:
        repo = tmp_path / "myrepo"
        repo.mkdir()
        (repo / ".git").mkdir()
        subrepo = repo / "subrepo"
        subrepo.mkdir()
        (subrepo / ".git").mkdir()
        result = _find_git_repos(tmp_path)
        assert len(result) == 1
        assert result[0] == repo

    def test_empty_directory(self, tmp_path: Path) -> None:
        result = _find_git_repos(tmp_path)
        assert result == []

    def test_returns_sorted(self, tmp_path: Path) -> None:
        for name in ["c", "a", "b"]:
            d = tmp_path / name
            d.mkdir()
            (d / ".git").mkdir()
        result = _find_git_repos(tmp_path)
        assert result == sorted(result)


class TestFindOrphansCommand:
    """Tests for find_orphans CLI command."""

    def test_no_manifest_shows_error(
        self, cli_runner: CliRunner, tmp_path: Path
    ) -> None:
        import os

        original = os.getcwd()
        os.chdir(tmp_path)
        try:
            result = cli_runner.invoke(app, ["find-orphans"])
            assert result.exit_code == 2
        finally:
            os.chdir(original)

    def test_path_not_found(self, cli_runner: CliRunner, tmp_manifest: Path) -> None:
        result = cli_runner.invoke(
            app, ["find-orphans", "-m", str(tmp_manifest), "/nonexistent/path"]
        )
        assert result.exit_code == 2

    def test_no_repos_found(
        self, cli_runner: CliRunner, tmp_manifest: Path, tmp_path: Path
    ) -> None:
        search = tmp_path / "empty"
        search.mkdir()
        result = cli_runner.invoke(
            app, ["find-orphans", "-m", str(tmp_manifest), str(search)]
        )
        assert result.exit_code == 0

    def test_finds_orphan_repos(
        self, cli_runner: CliRunner, tmp_manifest: Path, tmp_path: Path
    ) -> None:
        search = tmp_path / "repos"
        search.mkdir()
        orphan = search / "unknown-repo"
        orphan.mkdir()
        (orphan / ".git").mkdir()
        result = cli_runner.invoke(
            app, ["find-orphans", "-m", str(tmp_manifest), str(search)]
        )
        assert "unknown-repo" in result.stdout

    def test_all_repos_tracked(self, cli_runner: CliRunner, tmp_path: Path) -> None:
        manifest = tmp_path / "manifest.toml"
        root = tmp_path / "repos"
        root.mkdir()
        tracked = root / "myrepo"
        tracked.mkdir()
        (tracked / ".git").mkdir()
        manifest.write_text(f"""
[common]
root_path = "{root}"
branch = "main"
remote = "origin"

[[remotes]]
name = "origin"
base_url = "https://github.com/"

[[projects]]
slug = "owner/myrepo"
path = "myrepo"
""")
        result = cli_runner.invoke(
            app, ["find-orphans", "-m", str(manifest), str(root)]
        )
        assert result.exit_code == 0
        assert "no orphan" in result.stdout.lower() or "all" in result.stdout.lower()
