#!/usr/bin/python3
"""Tests for slpkg/repositories.py using pytest."""

from pathlib import Path
from unittest.mock import patch, MagicMock

import pytest
from slpkg.repositories import Repositories, _parse_git_mirror, _parent_url


def test_parse_git_mirror_github():
    """Test resolving GitHub git URL to raw URL."""
    mirror = "https://github.com/user/repo.git"
    branch = "master"
    repo_path = Path("/tmp/repo")
    
    with patch("pathlib.Path.is_dir", return_value=True):
        result = _parse_git_mirror(mirror, branch, repo_path)
        assert result == "https://raw.githubusercontent.com/user/repo/master/"


def test_parse_git_mirror_gitlab():
    """Test resolving GitLab git URL to raw URL."""
    mirror = "https://gitlab.com/user/repo.git"
    branch = "main"
    repo_path = Path("/tmp/repo")
    
    with patch("pathlib.Path.is_dir", return_value=True):
        result = _parse_git_mirror(mirror, branch, repo_path)
        assert result == "https://gitlab.com/user/repo/-/raw/main/"


def test_parse_git_mirror_no_git_dir():
    """Test that it returns original mirror if .git dir is missing."""
    mirror = "https://github.com/user/repo.git"
    branch = "master"
    repo_path = Path("/tmp/repo")
    
    with patch("pathlib.Path.is_dir", return_value=False):
        result = _parse_git_mirror(mirror, branch, repo_path)
        assert result == mirror


def test_repositories_structure():
    """Test the basic structure of the Repositories class."""
    repos = Repositories()
    assert hasattr(repos, "repositories")
    assert "sbo" in repos.repositories
    assert "slack" in repos.repositories
    
    sbo_config = repos.repositories["sbo"]
    assert "enable" in sbo_config
    assert "path" in sbo_config
    assert isinstance(sbo_config["path"], Path)


def test_repositories_default_values():
    """Test some default class variables."""
    assert Repositories.slackbuilds_txt == "SLACKBUILDS.TXT"
    assert Repositories.packages_txt == "PACKAGES.TXT"
    assert Repositories.changelog_txt == "ChangeLog.txt"
    assert Repositories.all_repos_priority == []


# ---------------------------------------------------------------------------
# _parent_url
# ---------------------------------------------------------------------------


def test_parent_url_default_one_level() -> None:
    """Default (1 level) strips the last path component."""
    assert _parent_url("http://mirror/packages/file.txt") == "http://mirror/packages/"


def test_parent_url_two_levels() -> None:
    """2 levels strips the last two path components."""
    assert _parent_url("http://mirror/a/b/c", levels=2) == "http://mirror/a/"


def test_parent_url_three_levels() -> None:
    """3 levels strips the last three path components."""
    assert _parent_url("http://mirror/a/b/c/d", levels=3) == "http://mirror/a/"


def test_parent_url_four_levels() -> None:
    """4 levels strips the last four path components."""
    assert _parent_url("http://mirror/a/b/c/d/e", levels=4) == "http://mirror/a/"


def test_parent_url_trailing_slash_preserved() -> None:
    """Result always ends with a trailing slash."""
    result = _parent_url("http://mirror/dir/file")
    assert result.endswith("/")


def test_parent_url_typical_slack_extra() -> None:
    """Mirrors the real 2-level use-case for slack_extra-style URLs."""
    url = "http://example.com/pub/slackware/slackware64-15.0/extra/PACKAGES.TXT"
    assert _parent_url(url, levels=2) == "http://example.com/pub/slackware/slackware64-15.0/"


@patch("slpkg.repositories.tomlkit.parse")
@patch("pathlib.Path.is_file", return_value=True)
@patch("pathlib.Path.read_text", return_value="dummy")
def test_repositories_loading(mock_read, mock_exists, mock_parse):
    """Test the loading logic from TOML."""
    # Mock TOML data
    mock_toml = {
        "DEFAULT": {"REPOSITORY": "SBO"},
        "NEW_PACKAGES": {"REPOSITORIES": ["sbo"]},
        "REMOVE_PACKAGES": {"REPOSITORIES": []},
        "SBOSRCARCH": {"MIRROR": "http://fallback/"},
        "SBO": {"ENABLE": True, "MIRROR": "http://sbo/", "BRANCH": "master"},
        "PONCE": {"ENABLE": False, "MIRROR": "http://ponce/", "BRANCH": "current"},
        "SLACK": {"ENABLE": True, "MIRROR": "http://slack/"},
        "SLACK_EXTRA": {"ENABLE": False, "MIRROR": "http://extra/"},
        "SLACK_PATCHES": {"ENABLE": False, "MIRROR": "http://patches/"},
        "SLACK_TESTING": {"ENABLE": False, "MIRROR": "http://testing/"},
        "ALIEN": {"ENABLE": False, "MIRROR": "http://alien/"},
        "MULTILIB": {"ENABLE": False, "MIRROR": "http://multilib/"},
        "RESTRICTED": {"ENABLE": False, "MIRROR": "http://restricted/"},
        "GNOME": {"ENABLE": False, "MIRROR": "http://gnome/"},
        "COSMIC": {"ENABLE": False, "MIRROR": "http://cosmic/"},
        "MSB": {"ENABLE": False, "MIRROR": "http://msb/"},
        "CSB": {"ENABLE": False, "MIRROR": "http://csb/"},
        "CONRAID": {"ENABLE": False, "MIRROR": "http://conraid/"},
        "SLACKONLY": {"ENABLE": False, "MIRROR": "http://slackonly/"},
        "SALIX": {"ENABLE": False, "MIRROR": "http://salix/"},
        "SALIX_EXTRA": {"ENABLE": False, "MIRROR": "http://salix_extra/"},
        "SLACKEL": {"ENABLE": False, "MIRROR": "http://slackel/"},
        "SLINT": {"ENABLE": False, "MIRROR": "http://slint/"},
        "PPRKUT": {"ENABLE": False, "MIRROR": "http://pprkut/"},
        "SLACKDCE": {"ENABLE": False, "MIRROR": "http://slackdce/"},
        "D2SLACK": {"ENABLE": False, "MIRROR": "http://d2slack/"},
        "ALL_REPOS": {"PRIORITY": []}
    }
    mock_parse.return_value = mock_toml
    
    # Since the loading happens at class definition, we might need to 
    # re-trigger it or just check if the class variables are as expected.
    # For testing purposes, we can check a new instance.
    with patch("slpkg.repositories.config_load") as mock_config:
        mock_config.etc_path = "/etc/slpkg"
        mock_config.lib_path = "/var/lib/slpkg"
        
        repos = Repositories()
        # Note: Repositories logic runs once when the module is imported.
        # This test might be limited by that.
        assert repos.sbo_repo_name == "sbo"
