"""Tests for util.git shared functions."""

from pathlib import Path

import pytest

from repo_sync_kitty.util.git import (
    convert_url_to_https,
    convert_url_to_ssh,
    git_url_to_web_url,
    is_git_repo,
    normalize_git_url,
    normalize_git_url_agnostic,
)


class TestIsGitRepo:
    """Tests for is_git_repo."""

    def test_directory_with_dot_git_dir(self, tmp_path: Path) -> None:
        (tmp_path / ".git").mkdir()
        assert is_git_repo(tmp_path) is True

    def test_directory_without_dot_git(self, tmp_path: Path) -> None:
        assert is_git_repo(tmp_path) is False

    def test_nonexistent_path(self, tmp_path: Path) -> None:
        assert is_git_repo(tmp_path / "nonexistent") is False

    def test_dot_git_as_file(self, tmp_path: Path) -> None:
        (tmp_path / ".git").write_text("gitdir: /somewhere/else")
        assert is_git_repo(tmp_path) is True

    def test_dot_git_as_symlink(self, tmp_path: Path) -> None:
        target = tmp_path / "target"
        target.mkdir()
        (tmp_path / "sub").mkdir()
        (tmp_path / "sub" / ".git").symlink_to(target)
        assert is_git_repo(tmp_path / "sub") is True


class TestGitUrlToWebUrl:
    """Tests for git_url_to_web_url."""

    def test_ssh_shorthand(self) -> None:
        assert (
            git_url_to_web_url("git@github.com:owner/repo")
            == "https://github.com/owner/repo"
        )

    def test_ssh_shorthand_with_git_suffix(self) -> None:
        assert (
            git_url_to_web_url("git@github.com:owner/repo.git")
            == "https://github.com/owner/repo"
        )

    def test_ssh_url(self) -> None:
        assert (
            git_url_to_web_url("ssh://git@github.com/owner/repo")
            == "https://github.com/owner/repo"
        )

    def test_ssh_url_with_git_suffix(self) -> None:
        assert (
            git_url_to_web_url("ssh://git@github.com/owner/repo.git")
            == "https://github.com/owner/repo"
        )

    def test_https_url(self) -> None:
        assert (
            git_url_to_web_url("https://github.com/owner/repo")
            == "https://github.com/owner/repo"
        )

    def test_https_url_with_git_suffix(self) -> None:
        assert (
            git_url_to_web_url("https://github.com/owner/repo.git")
            == "https://github.com/owner/repo"
        )

    def test_http_url_upgrades_to_https(self) -> None:
        assert (
            git_url_to_web_url("http://github.com/owner/repo")
            == "https://github.com/owner/repo"
        )

    def test_unrecognized_returns_none(self) -> None:
        assert git_url_to_web_url("ftp://example.com/repo") is None

    def test_strips_whitespace(self) -> None:
        assert (
            git_url_to_web_url("  https://github.com/owner/repo  ")
            == "https://github.com/owner/repo"
        )

    def test_gitlab_ssh(self) -> None:
        assert (
            git_url_to_web_url("git@gitlab.com:group/project")
            == "https://gitlab.com/group/project"
        )


class TestNormalizeGitUrl:
    """Tests for normalize_git_url."""

    def test_strips_git_suffix(self) -> None:
        assert (
            normalize_git_url("https://github.com/o/r.git") == "https://github.com/o/r"
        )

    def test_strips_trailing_slash(self) -> None:
        assert normalize_git_url("https://github.com/o/r/") == "https://github.com/o/r"

    def test_converts_ssh_shorthand(self) -> None:
        result = normalize_git_url("git@github.com:owner/repo")
        assert result == "ssh://git@github.com/owner/repo"

    def test_lowercases(self) -> None:
        assert (
            normalize_git_url("https://GitHub.COM/Owner/Repo")
            == "https://github.com/owner/repo"
        )

    def test_ssh_and_https_normalize_differently(self) -> None:
        ssh = normalize_git_url("git@github.com:owner/repo")
        https = normalize_git_url("https://github.com/owner/repo")
        assert ssh != https  # They normalize to different schemes

    def test_strips_whitespace(self) -> None:
        assert (
            normalize_git_url("  https://github.com/o/r  ") == "https://github.com/o/r"
        )

    def test_ssh_url_format(self) -> None:
        result = normalize_git_url("ssh://git@github.com/owner/repo")
        assert result == "ssh://git@github.com/owner/repo"


class TestNormalizeGitUrlAgnostic:
    """Tests for normalize_git_url_agnostic."""

    def test_https_url(self) -> None:
        result = normalize_git_url_agnostic("https://github.com/owner/repo")
        assert result == "github.com/owner/repo"

    def test_https_url_with_git_suffix(self) -> None:
        result = normalize_git_url_agnostic("https://github.com/owner/repo.git")
        assert result == "github.com/owner/repo"

    def test_ssh_url(self) -> None:
        result = normalize_git_url_agnostic("ssh://git@github.com/owner/repo")
        assert result == "github.com/owner/repo"

    def test_ssh_url_with_git_suffix(self) -> None:
        result = normalize_git_url_agnostic("ssh://git@github.com/owner/repo.git")
        assert result == "github.com/owner/repo"

    def test_ssh_shorthand(self) -> None:
        result = normalize_git_url_agnostic("git@github.com:owner/repo")
        assert result == "github.com/owner/repo"

    def test_ssh_shorthand_with_git_suffix(self) -> None:
        result = normalize_git_url_agnostic("git@github.com:owner/repo.git")
        assert result == "github.com/owner/repo"

    def test_http_url(self) -> None:
        result = normalize_git_url_agnostic("http://github.com/owner/repo")
        assert result == "github.com/owner/repo"

    def test_ssh_and_https_match(self) -> None:
        ssh = normalize_git_url_agnostic("ssh://git@github.com/vladistan/repo")
        https = normalize_git_url_agnostic("https://github.com/vladistan/repo")
        assert ssh == https

    def test_ssh_shorthand_and_https_match(self) -> None:
        ssh = normalize_git_url_agnostic("git@github.com:vladistan/repo.git")
        https = normalize_git_url_agnostic("https://github.com/vladistan/repo.git")
        assert ssh == https

    def test_lowercases(self) -> None:
        result = normalize_git_url_agnostic("https://GitHub.COM/Owner/Repo")
        assert result == "github.com/owner/repo"

    def test_strips_whitespace(self) -> None:
        result = normalize_git_url_agnostic("  https://github.com/o/r  ")
        assert result == "github.com/o/r"

    def test_strips_trailing_slash(self) -> None:
        result = normalize_git_url_agnostic("https://github.com/o/r/")
        assert result == "github.com/o/r"


class TestConvertUrlToHttps:
    """Tests for convert_url_to_https."""

    def test_from_ssh_shorthand(self) -> None:
        assert (
            convert_url_to_https("git@github.com:owner/repo.git")
            == "https://github.com/owner/repo.git"
        )

    def test_from_ssh_url(self) -> None:
        assert (
            convert_url_to_https("ssh://git@github.com/owner/repo.git")
            == "https://github.com/owner/repo.git"
        )

    def test_from_https_noop(self) -> None:
        assert (
            convert_url_to_https("https://github.com/owner/repo.git")
            == "https://github.com/owner/repo.git"
        )

    def test_from_http(self) -> None:
        assert (
            convert_url_to_https("http://github.com/owner/repo.git")
            == "https://github.com/owner/repo.git"
        )

    def test_adds_git_suffix_if_missing(self) -> None:
        assert (
            convert_url_to_https("git@github.com:owner/repo")
            == "https://github.com/owner/repo.git"
        )

    def test_unrecognized_raises(self) -> None:
        with pytest.raises(ValueError, match="Unrecognized"):
            convert_url_to_https("ftp://example.com/repo")

    def test_gitlab_ssh(self) -> None:
        assert (
            convert_url_to_https("git@gitlab.com:group/project.git")
            == "https://gitlab.com/group/project.git"
        )


class TestConvertUrlToSsh:
    """Tests for convert_url_to_ssh."""

    def test_from_https(self) -> None:
        assert (
            convert_url_to_ssh("https://github.com/owner/repo.git")
            == "ssh://git@github.com/owner/repo.git"
        )

    def test_from_http(self) -> None:
        assert (
            convert_url_to_ssh("http://github.com/owner/repo.git")
            == "ssh://git@github.com/owner/repo.git"
        )

    def test_from_ssh_url_noop(self) -> None:
        assert (
            convert_url_to_ssh("ssh://git@github.com/owner/repo.git")
            == "ssh://git@github.com/owner/repo.git"
        )

    def test_from_ssh_shorthand(self) -> None:
        assert (
            convert_url_to_ssh("git@github.com:owner/repo.git")
            == "ssh://git@github.com/owner/repo.git"
        )

    def test_adds_git_suffix_if_missing(self) -> None:
        assert (
            convert_url_to_ssh("https://github.com/owner/repo")
            == "ssh://git@github.com/owner/repo.git"
        )

    def test_unrecognized_raises(self) -> None:
        with pytest.raises(ValueError, match="Unrecognized"):
            convert_url_to_ssh("ftp://example.com/repo")

    def test_roundtrip_ssh_to_https_to_ssh(self) -> None:
        original = "ssh://git@github.com/owner/repo.git"
        https = convert_url_to_https(original)
        back = convert_url_to_ssh(https)
        assert back == original

    def test_roundtrip_https_to_ssh_to_https(self) -> None:
        original = "https://github.com/owner/repo.git"
        ssh = convert_url_to_ssh(original)
        back = convert_url_to_https(ssh)
        assert back == original
