from uuid import UUID

import pytest

from slices_typeid import DomainValidationException, SuffixValidationException, TypeID, TypeValidationException


@pytest.mark.parametrize(
    ("type_", "domain"),
    [
        ("a", "ex"),
        ("abcdef", "a.domain.with.the.maximum.length.of.56.char.example.com"),
    ],
)
def test_constructor_accepts_valid_type_and_domain(type_: str, domain: str):
    actual = TypeID(type=type_, domain=domain)

    assert actual.type == type_
    assert actual.domain == domain
    assert len(actual.suffix) == 26


@pytest.mark.parametrize(
    ("suffix", "expected_uuid"),
    [
        ("3hyvtc5ynb9wbtt3dyqkq2ebrn", UUID("71f6f4c2-faab-4f17-ad0d-bebcee272f15")),
        ("10fx3z89rk81da7fs4b9g5qwje", UUID("207f47f4-2713-405a-a3bf-245a605bf24e")),
        ("2ekxf93qtx8b4asx9hnamhhxsz", UUID("4e9f5e91-df5d-42c8-acf5-31aaa918f73f")),
    ],
)
def test_constructor_accepts_valid_suffix(suffix: str, expected_uuid: UUID):
    actual = TypeID(type="abc", domain="example.com", suffix=suffix)

    assert actual.type == "abc"
    assert actual.domain == "example.com"
    assert actual.suffix == suffix
    assert actual.uuid == expected_uuid
    assert str(actual) == f"abc_example.com_{suffix}"


@pytest.mark.parametrize(
    "invalid_type",
    [
        "",
        "ABCDEFG",
        "Abcdef",
        "abc123",
        "abc-def",
        "abcdefg",
    ],
)
def test_constructor_rejects_invalid_type(invalid_type: str):
    with pytest.raises(TypeValidationException):
        TypeID(type=invalid_type, domain="example.com")


@pytest.mark.parametrize(
    "invalid_domain",
    [
        "",
        "a",
        "Aexample.com",
        "1example.com",
        "example_com",
        "example!.com",
        "a" * 57,
    ],
)
def test_constructor_rejects_invalid_domain(invalid_domain: str):
    with pytest.raises(DomainValidationException):
        TypeID(type="abc", domain=invalid_domain)


@pytest.mark.parametrize(
    "invalid_suffix",
    [
        "0" * 25,
        "0" * 27,
        # correct: "10fx3z89rk81da7fs4b9g5qwje"
        "10fx3z89rk81da7fs4b9g5qwji",  # end with invalid char i
        "10fx3z89rk81da7fs4b9g5qwjl",  # end with invalid char l
        "10fx3z89rk81da7fs4b9g5qwju",  # end with invalid char u
        "10fx3z89rk81da7fs4b9g5qwjo",  # end with invalid char o
        "10fx3z89rk81da7fs4b9g5qwjE",  # ends with uppercase char
        "80fx3z89rk81da7fs4b9g5qwje",  # starts char valid for rest of suffix, but not valid for start char
        "z0fx3z89rk81da7fs4b9g5qwje",  # starts char valid for rest of suffix, but not valid for start char
        "i0fx3z89rk81da7fs4b9g5qwje",  # starts with invalid char
    ],
)
def test_constructor_rejects_invalid_suffix(invalid_suffix: str):
    with pytest.raises(SuffixValidationException):
        TypeID(type="abc", domain="example.com", suffix=invalid_suffix)


def test_constructor_validates_type_before_domain():
    with pytest.raises(TypeValidationException):
        TypeID(type="abc123", domain="1example.com")
