"""Git operations for workspace management."""

import asyncio
import logging
import subprocess

logger = logging.getLogger(__name__)


class GitService:
    """Low-level git operations for creating and syncing workspaces."""

    @staticmethod
    async def clone(remote_url: str, branch: str, path: str) -> None:
        """Clone a repository to the given path.

        Args:
            remote_url: The git remote URL.
            branch: The branch to clone.
            path: The destination path for the clone.

        Raises:
            RuntimeError: If the clone fails.
        """
        cmd = [
            "git",
            "clone",
            "--branch",
            branch,
            "--single-branch",
            remote_url,
            path,
        ]
        proc = await asyncio.create_subprocess_exec(
            *cmd,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
        stdout, stderr = await proc.communicate()
        if proc.returncode != 0:
            error_msg = stderr.decode().strip() if stderr else "unknown error"
            logger.error("Git clone failed: %s", error_msg)
            raise RuntimeError(f"Git clone failed: {error_msg}")
        logger.debug("Cloned %s (branch: %s) to %s", remote_url, branch, path)

    @staticmethod
    async def fetch(path: str) -> None:
        """Fetch from origin.

        Args:
            path: The path to the local git repository.

        Raises:
            RuntimeError: If fetch fails.
        """
        proc = await asyncio.create_subprocess_exec(
            "git",
            "-C",
            path,
            "fetch",
            "origin",
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
        stdout, stderr = await proc.communicate()
        if proc.returncode != 0:
            error_msg = stderr.decode().strip() if stderr else "unknown error"
            logger.error("Git fetch failed: %s", error_msg)
            raise RuntimeError(f"Git fetch failed: {error_msg}")
        logger.debug("Fetched origin for %s", path)

    @staticmethod
    async def pull(path: str, branch: str) -> None:
        """Pull latest changes from origin.

        Args:
            path: The path to the local git repository.
            branch: The branch to pull.

        Raises:
            RuntimeError: If pull fails.
        """
        proc = await asyncio.create_subprocess_exec(
            "git",
            "-C",
            path,
            "pull",
            "origin",
            branch,
            stdout=asyncio.subprocess.PIPE,
            stderr=asyncio.subprocess.PIPE,
        )
        stdout, stderr = await proc.communicate()
        if proc.returncode != 0:
            error_msg = stderr.decode().strip() if stderr else "unknown error"
            logger.error("Git pull failed: %s", error_msg)
            raise RuntimeError(f"Git pull failed: {error_msg}")
        logger.debug("Pulled origin/%s for %s", branch, path)

    @staticmethod
    def branch_exists_remotely(path: str, branch: str) -> bool:
        """Check if a branch exists on the remote.

        Args:
            path: The path to the local git repository.
            branch: The branch name to check.

        Returns:
            True if the branch exists on origin, False otherwise.
        """
        result = subprocess.run(
            ["git", "-C", path, "ls-remote", "--heads", "origin", branch],
            capture_output=True,
            text=True,
        )
        exists = result.returncode == 0 and result.stdout.strip() != ""
        logger.debug("Branch %s exists on remote: %s", branch, exists)
        return exists
