"""Git-related utility functions shared across commands."""

import re
from pathlib import Path


def is_git_repo(path: Path) -> bool:
    """Check if directory is a git repo (.git can be dir, file, or symlink).

    Args:
        path: Directory path to check

    Returns:
        True if path contains a .git entry, False if not or on permission error
    """
    try:
        return (path / ".git").exists()
    except PermissionError:
        return False


def git_url_to_web_url(git_url: str) -> str | None:
    """Convert a git remote URL to a web browser URL.

    Handles SSH shorthand, SSH URLs, HTTPS, and HTTP for GitHub,
    GitLab, Bitbucket, and similar forges.

    Args:
        git_url: Git remote URL (ssh or https)

    Returns:
        Web URL or None if pattern not recognized
    """
    url = git_url.strip()

    # Remove .git suffix
    if url.endswith(".git"):
        url = url[:-4]

    # SSH shorthand: git@github.com:owner/repo
    ssh_shorthand = re.match(r"^git@([^:]+):(.+)$", url)
    if ssh_shorthand:
        host, path = ssh_shorthand.groups()
        return f"https://{host}/{path}"

    # SSH URL: ssh://git@github.com/owner/repo
    ssh_url = re.match(r"^ssh://[^@]+@([^/]+)/(.+)$", url)
    if ssh_url:
        host, path = ssh_url.groups()
        return f"https://{host}/{path}"

    # HTTPS URL: already web-compatible
    if url.startswith("https://"):
        return url

    # HTTP URL
    if url.startswith("http://"):
        return url.replace("http://", "https://", 1)

    return None


def normalize_git_url(url: str) -> str:
    """Normalize a git URL for comparison.

    Handles variations like:
    - https://github.com/owner/repo vs https://github.com/owner/repo.git
    - git@github.com:owner/repo vs ssh://git@github.com/owner/repo
    - Trailing slashes

    Args:
        url: Git URL to normalize

    Returns:
        Normalized URL for comparison
    """
    url = url.strip().rstrip("/")

    # Remove .git suffix
    if url.endswith(".git"):
        url = url[:-4]

    # Convert SSH shorthand (git@host:path) to ssh:// format
    ssh_shorthand = re.match(r"^(\w+)@([^:]+):(.+)$", url)
    if ssh_shorthand:
        user, host, path = ssh_shorthand.groups()
        url = f"ssh://{user}@{host}/{path}"

    # Normalize to lowercase for comparison
    return url.lower()


def normalize_git_url_agnostic(url: str) -> str:
    """Normalize a git URL to protocol-agnostic form for comparison.

    Strips protocol and user info, returning only host/path.
    Use when comparing URLs that may differ only in protocol
    (e.g., ssh:// vs https:// to the same repo).

    Args:
        url: Git URL to normalize

    Returns:
        Protocol-agnostic normalized form (host/path, lowercase)
    """
    url = url.strip().rstrip("/")

    # Remove .git suffix
    if url.endswith(".git"):
        url = url[:-4]

    # SSH shorthand: git@host:path → host/path
    ssh_shorthand = re.match(r"^\w+@([^:]+):(.+)$", url)
    if ssh_shorthand:
        host, path = ssh_shorthand.groups()
        return f"{host}/{path}".lower()

    # SSH URL: ssh://user@host/path → host/path
    ssh_url = re.match(r"^ssh://[^@]+@([^/]+)/(.+)$", url)
    if ssh_url:
        host, path = ssh_url.groups()
        return f"{host}/{path}".lower()

    # HTTPS/HTTP URL: https://host/path → host/path
    http_url = re.match(r"^https?://([^/]+)/(.+)$", url)
    if http_url:
        host, path = http_url.groups()
        return f"{host}/{path}".lower()

    # Fallback: lowercase as-is
    return url.lower()


def _extract_host_and_path(url: str) -> tuple[str, str] | None:
    """Extract host and path from any git URL format.

    Returns (host, path) with .git suffix preserved, or None if unrecognized.
    """
    url = url.strip().rstrip("/")

    # SSH shorthand: git@host:owner/repo.git
    ssh_shorthand = re.match(r"^\w+@([^:]+):(.+)$", url)
    if ssh_shorthand:
        return ssh_shorthand.groups()  # type: ignore[return-value]

    # SSH URL: ssh://user@host/path
    ssh_url = re.match(r"^ssh://[^@]+@([^/]+)/(.+)$", url)
    if ssh_url:
        return ssh_url.groups()  # type: ignore[return-value]

    # HTTPS/HTTP URL: https://host/path
    http_url = re.match(r"^https?://([^/]+)/(.+)$", url)
    if http_url:
        return http_url.groups()  # type: ignore[return-value]

    return None


def _ensure_git_suffix(path: str) -> str:
    """Ensure path ends with .git suffix."""
    if not path.endswith(".git"):
        path = f"{path}.git"
    return path


def convert_url_to_https(url: str) -> str:
    """Convert any git URL to HTTPS format.

    Args:
        url: Git URL in any format (SSH shorthand, SSH URL, HTTPS, HTTP)

    Returns:
        HTTPS URL with .git suffix

    Raises:
        ValueError: If URL format is not recognized
    """
    parts = _extract_host_and_path(url)
    if parts is None:
        raise ValueError(f"Unrecognized git URL format: {url}")
    host, path = parts
    return f"https://{host}/{_ensure_git_suffix(path)}"


def convert_url_to_ssh(url: str) -> str:
    """Convert any git URL to SSH format.

    Args:
        url: Git URL in any format (SSH shorthand, SSH URL, HTTPS, HTTP)

    Returns:
        SSH URL (ssh://git@host/path.git format) with .git suffix

    Raises:
        ValueError: If URL format is not recognized
    """
    parts = _extract_host_and_path(url)
    if parts is None:
        raise ValueError(f"Unrecognized git URL format: {url}")
    host, path = parts
    return f"ssh://git@{host}/{_ensure_git_suffix(path)}"
