"""Git URL parsing utilities to extract base repository URLs from browser URLs."""

from urllib.parse import urlparse


def extract_base_repo_url(url: str) -> str | None:
    """Extract base repository URL from a browser/git URL.

    Examples:
        https://github.com/user/repo/tree/main → https://github.com/user/repo.git
        https://github.com/user/repo.git → https://github.com/user/repo.git
        git@github.com:user/repo.git → git@github.com:user/repo.git
        https://gitlab.com/user/repo/-/blob/main/README.md → https://gitlab.com/user/repo.git

    Returns None if URL doesn't match known patterns.
    """
    # Handle SSH URLs (pass through unchanged)
    if url.startswith("git@"):
        return url if url.endswith(".git") else f"{url}.git"

    try:
        parsed = urlparse(url)
    except Exception:
        return None

    # Remove query parameters
    url = f"{parsed.scheme}://{parsed.netloc}{parsed.path}"

    # Extract host
    host = parsed.netloc.lower()

    # Split path
    path_parts = [p for p in parsed.path.split("/") if p]

    if not path_parts:
        return None

    # Determine host type and extract base
    if "github.com" in host:
        return _extract_github_url(url, path_parts)
    elif "gitlab.com" in host:
        return _extract_gitlab_url(url, path_parts)
    elif "bitbucket.org" in host:
        return _extract_bitbucket_url(url, path_parts)
    else:
        # Generic host - try basic extraction
        return _extract_generic_url(url, path_parts)


def _extract_github_url(url: str, path_parts: list[str]) -> str | None:
    """Extract base repo URL from GitHub URL."""
    # Need at least owner/repo
    if len(path_parts) < 2:
        return None

    # Find the repo name (second path part)
    # Remove trailing .git if present
    repo_name = path_parts[1]
    if repo_name.endswith(".git"):
        repo_name = repo_name[:-4]

    # Reconstruct base URL
    base = f"https://github.com/{path_parts[0]}/{repo_name}"

    # Add .git suffix
    return f"{base}.git"


def _extract_gitlab_url(url: str, path_parts: list[str]) -> str | None:
    """Extract base repo URL from GitLab URL."""
    # Need at least owner/repo
    if len(path_parts) < 2:
        return None

    # Find the repo name (second path part)
    repo_name = path_parts[1]
    if repo_name.endswith(".git"):
        repo_name = repo_name[:-4]

    # Reconstruct base URL
    base = f"https://gitlab.com/{path_parts[0]}/{repo_name}"

    return f"{base}.git"


def _extract_bitbucket_url(url: str, path_parts: list[str]) -> str | None:
    """Extract base repo URL from Bitbucket URL."""
    # Need at least owner/repo
    if len(path_parts) < 2:
        return None

    # Find the repo name (second path part)
    repo_name = path_parts[1]
    if repo_name.endswith(".git"):
        repo_name = repo_name[:-4]

    # Reconstruct base URL
    base = f"https://bitbucket.org/{path_parts[0]}/{repo_name}"

    return f"{base}.git"


def _extract_generic_url(url: str, path_parts: list[str]) -> str | None:
    """Extract base repo URL from generic git host URL."""
    # Need at least owner/repo
    if len(path_parts) < 2:
        return None

    # Find the repo name (second path part)
    repo_name = path_parts[1]
    if repo_name.endswith(".git"):
        repo_name = repo_name[:-4]

    # Reconstruct base URL
    parsed = urlparse(url)
    base = f"{parsed.scheme}://{parsed.netloc}/{path_parts[0]}/{repo_name}"

    return f"{base}.git"


def is_valid_clone_url(url: str) -> bool:
    """Check if URL is already a valid git clone URL.

    A valid clone URL:
    - Is an SSH URL (git@host:path)
    - Ends with .git
    - Has no browser-specific path segments
    """
    # SSH URLs are always valid
    if url.startswith("git@"):
        return True

    try:
        parsed = urlparse(url)
    except Exception:
        return False

    path = parsed.path

    # Must end with .git for HTTPS
    if not path.endswith(".git"):
        return False

    # Check for browser-specific paths
    browser_paths = ["/tree/", "/blob/", "/pull/", "/issues/", "/actions/",
                     "-/tree/", "-/blob/", "-/merge_requests/",
                     "/src/"]

    for bp in browser_paths:
        if bp in path:
            return False

    return True


def parse_git_url(url: str) -> dict:
    """Parse a git URL and return detailed information.

    Returns:
        {
            "original_url": str,
            "base_url": str | None,
            "is_valid_clone_url": bool,
            "needs_parsing": bool,
            "host": str | None,
            "message": str,
            "error_code": str | None,
        }
    """
    result = {
        "original_url": url,
        "base_url": None,
        "is_valid_clone_url": False,
        "needs_parsing": False,
        "host": None,
        "message": "",
        "error_code": None,
    }

    # Check if empty
    if not url or not url.strip():
        result["message"] = "Please enter a URL"
        result["error_code"] = "INVALID_URL"
        return result

    url = url.strip()

    # Try to parse
    try:
        parsed = urlparse(url)
    except Exception:
        result["message"] = "Please enter a valid URL"
        result["error_code"] = "INVALID_URL"
        return result

    # Extract host
    if parsed.netloc:
        result["host"] = parsed.netloc.lower()
    elif url.startswith("git@"):
        # SSH URL: git@host:path
        parts = url.split(":", 1)
        if len(parts) == 2:
            result["host"] = parts[0].replace("git@", "")
    else:
        result["message"] = "Please enter a valid URL"
        result["error_code"] = "INVALID_URL"
        return result

    # Check if already valid
    if is_valid_clone_url(url):
        result["base_url"] = url
        result["is_valid_clone_url"] = True
        result["needs_parsing"] = False
        result["message"] = "Valid git repository URL"
        return result

    # Try to extract base URL
    base = extract_base_repo_url(url)
    if base:
        result["base_url"] = base
        result["needs_parsing"] = True
        result["message"] = f"This looks like a browser URL. Did you mean: {base}?"
        result["error_code"] = "URL_NEEDS_PARSING"
    else:
        result["message"] = "Could not parse this URL. Please enter a valid git repository URL."
        result["error_code"] = "INVALID_URL"

    return result
