"""Unit tests for GitOperations."""

import asyncio
import os
import subprocess
import tempfile

import pytest

from src.models import Workspace
from src.services.git.git_operations import GitOperations


def _run_git(*args: str, cwd: str) -> None:
    subprocess.run(["git", *args], cwd=cwd, check=True, capture_output=True)


@pytest.fixture
def temp_workspace():
    """Create a temporary git workspace."""
    with tempfile.TemporaryDirectory() as tmpdir:
        _run_git("init", cwd=tmpdir)
        _run_git("config", "user.email", "test@test.com", cwd=tmpdir)
        _run_git("config", "user.name", "Test User", cwd=tmpdir)

        readme = os.path.join(tmpdir, "README.md")
        with open(readme, "w") as f:
            f.write("# Test\n")
        _run_git("add", "README.md", cwd=tmpdir)
        _run_git("commit", "-m", "Initial commit", cwd=tmpdir)

        ws = Workspace(
            id="00000000-0000-0000-0000-000000000001",
            name="test-ws",
            repo_id="00000000-0000-0000-0000-000000000002",
            user_id="00000000-0000-0000-0000-000000000003",
            branch="main",
            path=tmpdir,
        )
        yield ws


class TestGitOperationsStatus:
    """Tests for GitOperations.status."""

    def test_status_clean(self, temp_workspace: Workspace):
        git = GitOperations(temp_workspace)
        status = asyncio.run(git.status())
        assert status.branch == "main"
        assert status.modified == []
        assert status.added == []
        assert status.deleted == []
        assert status.untracked == []

    def test_status_modified(self, temp_workspace: Workspace):
        with open(os.path.join(temp_workspace.path, "README.md"), "a") as f:
            f.write("modified\n")

        git = GitOperations(temp_workspace)
        status = asyncio.run(git.status())
        assert "README.md" in status.modified

    def test_status_untracked(self, temp_workspace: Workspace):
        with open(os.path.join(temp_workspace.path, "new.py"), "w") as f:
            f.write("print('hello')\n")

        git = GitOperations(temp_workspace)
        status = asyncio.run(git.status())
        assert "new.py" in status.untracked


class TestGitOperationsCommit:
    """Tests for GitOperations.commit."""

    def test_commit_stages_and_commits(self, temp_workspace: Workspace):
        with open(os.path.join(temp_workspace.path, "new.py"), "w") as f:
            f.write("print('hello')\n")

        git = GitOperations(temp_workspace)
        asyncio.run(git.commit("Add new file"))

        status = asyncio.run(git.status())
        assert "new.py" not in status.untracked
        assert "new.py" not in status.added

        history = asyncio.run(git.history())
        assert history[0].message == "Add new file"

    def test_commit_fails_without_changes(self, temp_workspace: Workspace):
        git = GitOperations(temp_workspace)
        with pytest.raises(RuntimeError):
            asyncio.run(git.commit("Nothing to commit"))


class TestGitOperationsHistory:
    """Tests for GitOperations.history."""

    def test_history_returns_commits(self, temp_workspace: Workspace):
        git = GitOperations(temp_workspace)
        history = asyncio.run(git.history())
        assert len(history) >= 1
        assert history[0].message == "Initial commit"

    def test_history_filters_by_path(self, temp_workspace: Workspace):
        with open(os.path.join(temp_workspace.path, "new.py"), "w") as f:
            f.write("print('hello')\n")

        git = GitOperations(temp_workspace)
        asyncio.run(git.commit("Add new file"))

        history = asyncio.run(git.history(path="new.py"))
        assert len(history) == 1
        assert history[0].message == "Add new file"


class TestGitOperationsBranches:
    """Tests for GitOperations.branches."""

    def test_branches_lists_main(self, temp_workspace: Workspace):
        git = GitOperations(temp_workspace)
        branches, current = asyncio.run(git.branches())
        assert "main" in branches
        assert current == "main"

    def test_checkout_switches_branch(self, temp_workspace: Workspace):
        _run_git("checkout", "-b", "feature", cwd=temp_workspace.path)
        _run_git("checkout", "main", cwd=temp_workspace.path)

        git = GitOperations(temp_workspace)
        asyncio.run(git.checkout("feature"))

        status = asyncio.run(git.status())
        assert status.branch == "feature"
