import json
from importlib.metadata import PackageNotFoundError
from unittest import TestCase
from unittest.mock import MagicMock, patch

from abstra_internals.utils.packages import get_local_package_direct_url


def _mock_distribution(direct_url_content):
    dist = MagicMock()
    dist.read_text.return_value = direct_url_content
    return dist


class TestGetLocalPackageDirectUrl(TestCase):
    URL = "https://releases.abstra.cloud/abstra/user/branch/abc123.zip"

    def test_returns_url_for_remote_archive_install(self):
        content = json.dumps({"url": self.URL, "archive_info": {"hash": "sha256=abc"}})
        with patch(
            "abstra_internals.utils.packages.distribution",
            return_value=_mock_distribution(content),
        ):
            self.assertEqual(get_local_package_direct_url("abstra"), self.URL)

    def test_returns_none_for_index_install(self):
        # PyPI installs have no direct_url.json; read_text returns None.
        with patch(
            "abstra_internals.utils.packages.distribution",
            return_value=_mock_distribution(None),
        ):
            self.assertIsNone(get_local_package_direct_url("abstra"))

    def test_returns_none_for_local_dir_install(self):
        content = json.dumps(
            {"url": "file:///home/user/abstra-lib", "dir_info": {"editable": False}}
        )
        with patch(
            "abstra_internals.utils.packages.distribution",
            return_value=_mock_distribution(content),
        ):
            self.assertIsNone(get_local_package_direct_url("abstra"))

    def test_returns_none_for_local_archive_install(self):
        content = json.dumps({"url": "file:///tmp/abstra-lib.zip", "archive_info": {}})
        with patch(
            "abstra_internals.utils.packages.distribution",
            return_value=_mock_distribution(content),
        ):
            self.assertIsNone(get_local_package_direct_url("abstra"))

    def test_returns_none_for_invalid_json(self):
        with patch(
            "abstra_internals.utils.packages.distribution",
            return_value=_mock_distribution("not json"),
        ):
            self.assertIsNone(get_local_package_direct_url("abstra"))

    def test_returns_none_when_package_not_found(self):
        with patch(
            "abstra_internals.utils.packages.distribution",
            side_effect=PackageNotFoundError("abstra"),
        ):
            self.assertIsNone(get_local_package_direct_url("abstra"))
