"""Tests for git control utilities."""

import os
import tempfile

import pytest

from src.utils.git_control import (
    GitStatus,
    checkout_branch,
    commit_changes,
    create_branch,
    delete_branch,
    get_current_branch,
    get_status,
)


@pytest.fixture
def temp_repo():
    """Create a temporary git repository."""
    with tempfile.TemporaryDirectory() as tmpdir:
        # Initialize git repo
        os.system(f"cd {tmpdir} && git init && git config user.email 'test@test.com' && git config user.name 'Test User'")
        
        # Create initial commit
        with open(os.path.join(tmpdir, "README.md"), "w") as f:
            f.write("# Test Repo\n")
        os.system(f"cd {tmpdir} && git add README.md && git commit -m 'Initial commit'")
        
        yield tmpdir


class TestGitStatus:
    """Tests for get_status function."""

    def test_clean_repo(self, temp_repo):
        """Test status of a clean repository."""
        status = get_status(temp_repo)
        assert isinstance(status, GitStatus)
        assert status.branch in ["main", "master"]
        assert len(status.modified) == 0
        assert len(status.added) == 0
        assert len(status.deleted) == 0
        assert len(status.untracked) == 0

    def test_modified_file(self, temp_repo):
        """Test detecting modified files."""
        # Modify a file
        with open(os.path.join(temp_repo, "README.md"), "w") as f:
            f.write("# Modified\n")
        
        status = get_status(temp_repo)
        assert "README.md" in status.modified

    def test_untracked_file(self, temp_repo):
        """Test detecting untracked files."""
        # Create new file
        with open(os.path.join(temp_repo, "new.py"), "w") as f:
            f.write("print('hello')\n")
        
        status = get_status(temp_repo)
        assert "new.py" in status.untracked


def test_get_current_branch_handles_unborn_main() -> None:
    with tempfile.TemporaryDirectory() as tmpdir:
        os.system(f"git init -b main {tmpdir} >/dev/null 2>&1")

        assert get_current_branch(tmpdir) == "main"


def test_create_branch_on_bare_repo_with_no_commits() -> None:
    with tempfile.TemporaryDirectory() as tmpdir:
        os.system(f"git init --bare {tmpdir}/bare.git >/dev/null 2>&1")
        create_branch(f"{tmpdir}/bare.git", "main")
        assert get_current_branch(f"{tmpdir}/bare.git") == "main"


def test_checkout_branch_on_bare_repo_with_no_commits() -> None:
    with tempfile.TemporaryDirectory() as tmpdir:
        os.system(f"git init --bare {tmpdir}/bare.git >/dev/null 2>&1")
        checkout_branch(f"{tmpdir}/bare.git", "main")
        assert get_current_branch(f"{tmpdir}/bare.git") == "main"


class TestBranchOperations:
    """Tests for branch management functions."""

    def test_create_branch(self, temp_repo):
        """Test creating a new branch."""
        # Get the actual default branch name
        default_branch = get_current_branch(temp_repo)
        create_branch(temp_repo, "feature/test", default_branch)
        
        # Check branch exists
        branches = get_status(temp_repo)
        # Branch should still be on default
        assert branches.branch == default_branch

    def test_checkout_branch(self, temp_repo):
        """Test checking out a branch."""
        default_branch = get_current_branch(temp_repo)
        create_branch(temp_repo, "feature/test", default_branch)
        checkout_branch(temp_repo, "feature/test")
        
        current = get_current_branch(temp_repo)
        assert current == "feature/test"

    def test_delete_branch(self, temp_repo):
        """Test deleting a branch."""
        default_branch = get_current_branch(temp_repo)
        create_branch(temp_repo, "feature/delete", default_branch)
        delete_branch(temp_repo, "feature/delete")
        
        # Should be back on default
        current = get_current_branch(temp_repo)
        assert current == default_branch

    def test_get_current_branch(self, temp_repo):
        """Test getting current branch."""
        branch = get_current_branch(temp_repo)
        assert branch in ["main", "master"]


class TestCommit:
    """Tests for commit function."""

    def test_commit_changes(self, temp_repo):
        """Test committing changes."""
        # Modify file
        with open(os.path.join(temp_repo, "README.md"), "w") as f:
            f.write("# Updated\n")
        
        # Commit
        commit_changes(
            temp_repo,
            "Update README",
            "Test User",
            "test@test.com",
            ["README.md"]
        )
        
        # Check status is clean
        status = get_status(temp_repo)
        assert "README.md" not in status.modified

    def test_commit_all_changes(self, temp_repo):
        """Test committing all changes."""
        # Modify file
        with open(os.path.join(temp_repo, "README.md"), "w") as f:
            f.write("# All updated\n")
        
        # Commit all
        commit_changes(
            temp_repo,
            "Update all",
            "Test User",
            "test@test.com"
        )
        
        # Check status is clean
        status = get_status(temp_repo)
        assert len(status.modified) == 0
