"""Unit tests for git mount resolution in tool instances."""

import os
from pathlib import Path

import pytest

from src.api.tool_instances import (
    _checkout_branch,
    _expand_glob_source,
    _resolve_single_git_mount,
)


class TestExpandGlobSource:
    """Unit tests for glob pattern expansion."""

    def test_no_glob_single_file(self, tmp_path: Path) -> None:
        """Test non-glob path returns single file."""
        test_file = tmp_path / "test.txt"
        test_file.write_text("content")
        
        result = _expand_glob_source(str(test_file), str(tmp_path))
        assert len(result) == 1
        assert result[0] == str(test_file)

    def test_no_glob_missing_file(self, tmp_path: Path) -> None:
        """Test non-glob missing file returns empty list."""
        missing_file = tmp_path / "missing.txt"
        
        result = _expand_glob_source(str(missing_file), str(tmp_path))
        assert len(result) == 0

    def test_glob_pattern(self, tmp_path: Path) -> None:
        """Test glob pattern matches files."""
        (tmp_path / "file1.txt").write_text("content1")
        (tmp_path / "file2.txt").write_text("content2")
        (tmp_path / "other.py").write_text("code")
        
        result = _expand_glob_source(str(tmp_path / "*.txt"), str(tmp_path))
        assert len(result) == 2
        assert all(f.endswith(".txt") for f in result)

    def test_glob_recursive(self, tmp_path: Path) -> None:
        """Test recursive glob pattern."""
        subdir = tmp_path / "subdir"
        subdir.mkdir()
        (subdir / "nested.txt").write_text("content")
        
        result = _expand_glob_source(str(tmp_path / "**" / "*.txt"), str(tmp_path))
        assert len(result) == 1
        assert "nested.txt" in result[0]

    def test_glob_limit_enforced(self, tmp_path: Path) -> None:
        """Test that glob matches are limited to prevent abuse."""
        # Create more than 100 files
        for i in range(105):
            (tmp_path / f"file{i}.txt").write_text("content")
        
        result = _expand_glob_source(str(tmp_path / "*.txt"), str(tmp_path))
        assert len(result) == 100  # MAX_GLOB_MATCHES limit

    def test_glob_escapes_repo(self, tmp_path: Path) -> None:
        """Test that glob results outside repo are filtered."""
        other_dir = tmp_path.parent / "other"
        other_dir.mkdir(exist_ok=True)
        (other_dir / "outside.txt").write_text("content")
        
        result = _expand_glob_source(str(tmp_path.parent / "*" / "*.txt"), str(tmp_path))
        # Should only include files within tmp_path, not other_dir
        assert all(r.startswith(str(tmp_path)) for r in result)


class TestCheckoutBranch:
    """Unit tests for branch checkout."""

    def test_checkout_existing_branch(self, tmp_path: Path) -> None:
        """Test checking out an existing branch."""
        # Initialize git repo
        os.system(f"cd {tmp_path} && git init && git config user.email 'test@test.com' && git config user.name 'Test'")
        (tmp_path / "file.txt").write_text("content")
        os.system(f"cd {tmp_path} && git add . && git commit -m 'initial'")
        os.system(f"cd {tmp_path} && git branch feature")
        
        _checkout_branch(str(tmp_path), "feature")
        
        # Verify we're on feature branch
        result = os.popen(f"cd {tmp_path} && git branch --show-current").read().strip()
        assert result == "feature"

    def test_checkout_nonexistent_branch(self, tmp_path: Path) -> None:
        """Test checking out a non-existent branch returns False."""
        os.system(f"cd {tmp_path} && git init && git config user.email 'test@test.com' && git config user.name 'Test'")
        (tmp_path / "file.txt").write_text("content")
        os.system(f"cd {tmp_path} && git add . && git commit -m 'initial'")
        
        result = _checkout_branch(str(tmp_path), "nonexistent")
        assert result is False


class TestResolveSingleGitMount:
    """Unit tests for resolving a single git mount."""

    @pytest.mark.asyncio
    async def test_resolve_missing_remote_url(self, db_session) -> None:
        """Test that missing remote_url returns empty list."""
        git_mount = {
            "source_path": ".",
            "target_path": "/app",
        }
        
        result = await _resolve_single_git_mount(db_session, git_mount)
        assert result == []

    @pytest.mark.asyncio
    async def test_resolve_missing_target_path(self, db_session) -> None:
        """Test that missing target path returns empty list."""
        git_mount = {
            "remote_url": "https://github.com/user/repo.git",
            "source_path": ".",
        }
        
        result = await _resolve_single_git_mount(db_session, git_mount)
        assert result == []
