# Copyright Spack Project Developers. See COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

import pytest

from spack.oci.image import Digest, ImageReference


@pytest.mark.parametrize(
    "image_ref, expected",
    [
        (
            f"example.com:1234/a/b/c:tag@sha256:{'a'*64}",
            ("example.com:1234", "a/b/c", "tag", Digest.from_sha256("a" * 64)),
        ),
        ("example.com:1234/a/b/c:tag", ("example.com:1234", "a/b/c", "tag", None)),
        ("example.com:1234/a/b/c", ("example.com:1234", "a/b/c", "latest", None)),
        (
            f"example.com:1234/a/b/c@sha256:{'a'*64}",
            ("example.com:1234", "a/b/c", "latest", Digest.from_sha256("a" * 64)),
        ),
        # ipv4
        ("1.2.3.4:1234/a/b/c:tag", ("1.2.3.4:1234", "a/b/c", "tag", None)),
        # ipv6
        ("[2001:db8::1]:1234/a/b/c:tag", ("[2001:db8::1]:1234", "a/b/c", "tag", None)),
        # Follow docker rules for parsing
        ("ubuntu:22.04", ("index.docker.io", "library/ubuntu", "22.04", None)),
        ("myname/myimage:abc", ("index.docker.io", "myname/myimage", "abc", None)),
        ("myname:1234/myimage:abc", ("myname:1234", "myimage", "abc", None)),
        ("localhost/myimage:abc", ("localhost", "myimage", "abc", None)),
        ("localhost:1234/myimage:abc", ("localhost:1234", "myimage", "abc", None)),
        (
            "example.com/UPPERCASE/lowercase:AbC",
            ("example.com", "uppercase/lowercase", "AbC", None),
        ),
    ],
)
def test_name_parsing(image_ref, expected):
    x = ImageReference.from_string(image_ref)
    assert (x.domain, x.name, x.tag, x.digest) == expected


@pytest.mark.parametrize(
    "image_ref",
    [
        # wrong order of tag and sha
        f"example.com:1234/a/b/c@sha256:{'a'*64}:tag",
        # double tag
        "example.com:1234/a/b/c:tag:tag",
        # empty tag
        "example.com:1234/a/b/c:",
        # empty digest
        "example.com:1234/a/b/c@sha256:",
        # unsupport digest algorithm
        f"example.com:1234/a/b/c@sha512:{'a'*128}",
        # invalid digest length
        f"example.com:1234/a/b/c@sha256:{'a'*63}",
        # whitespace
        "example.com:1234/a/b/c :tag",
        "example.com:1234/a/b/c: tag",
        "example.com:1234/a/b/c:tag ",
        " example.com:1234/a/b/c:tag",
        # broken ipv4
        "1.2..3:1234/a/b/c:tag",
    ],
)
def test_parsing_failure(image_ref):
    with pytest.raises(ValueError):
        ImageReference.from_string(image_ref)


def test_digest():
    valid_digest = "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"

    # Test string roundtrip
    assert str(Digest.from_string(f"sha256:{valid_digest}")) == f"sha256:{valid_digest}"

    # Invalid digest length
    with pytest.raises(ValueError):
        Digest.from_string("sha256:abcdef")

    # Missing algorithm
    with pytest.raises(ValueError):
        Digest.from_string(valid_digest)


def test_url_with_scheme():
    """Test that scheme=http translates to http:// URLs"""
    http = ImageReference.from_string("localhost:1234/myimage:abc", scheme="http")
    https = ImageReference.from_string("localhost:1234/myimage:abc", scheme="https")
    default = ImageReference.from_string("localhost:1234/myimage:abc")

    assert http != https
    assert https == default

    assert http.manifest_url() == "http://localhost:1234/v2/myimage/manifests/abc"
    assert https.manifest_url() == "https://localhost:1234/v2/myimage/manifests/abc"
    assert default.manifest_url() == "https://localhost:1234/v2/myimage/manifests/abc"
