import pytest
from uuid import UUID
from flexoentity import FlexOID, EntityType
from flexoentity.domain import Domain
from flexoentity.domain_manager import DomainManager


# ---------------------------------------------------------------
# Setup/Teardown (clear DomainManager between tests)
# ---------------------------------------------------------------
@pytest.fixture(autouse=True)
def clear_domain_manager():
    DomainManager.clear()
    yield
    DomainManager.clear()


# ---------------------------------------------------------------
# Domain creation + registration
# ---------------------------------------------------------------
def test_domain_creation_and_registration():
    d = DomainManager.create(
        domain_id="PY_ARITHM",
        fullname="Python Arithmetic",
        description="Basic arithmetic operations",
        classification="UNCLASSIFIED",
    )

    assert d.domain_id == "PY_ARITHM"
    assert d.entity_type == EntityType.DOMAIN
    assert isinstance(d.flexo_id, FlexOID)

    # Manager must know it now
    assert DomainManager.get("PY_ARITHM") is d


# ---------------------------------------------------------------
# Uniqueness: registering the same code twice must fail
# ---------------------------------------------------------------
def test_domain_uniqueness_enforced():
    DomainManager.create("AF")

    with pytest.raises(ValueError):
        DomainManager.create("AF")   # duplicate code rejected


# ---------------------------------------------------------------
# Lookup by FlexOID
# ---------------------------------------------------------------
def test_lookup_by_oid():
    d = DomainManager.create("PY_ARITHM")
    found = DomainManager.get_by_oid(d.flexo_id)
    assert found is d


# ---------------------------------------------------------------
# JSON roundtrip should preserve identity and not regenerate FlexOID
# ---------------------------------------------------------------
def test_domain_json_roundtrip():
    orig = DomainManager.create(
        domain_id="ELEKTRO_BASICS",
        fullname="Elektronik Grundlagen",
    )

    data = orig.to_dict()
    loaded = Domain.from_dict(data)

    # Same exact instance
    assert loaded == orig

    # Same FlexOID
    assert str(loaded.flexo_id) == str(orig.flexo_id)


# ---------------------------------------------------------------
# Loading a domain from dict that was not previously registered
# ---------------------------------------------------------------
def test_domain_restore_new_from_dict():
    d = Domain.with_domain_id(
        domain_id="PY_LOOPS",
        fullname="Python Loops",
        classification="UNCLASSIFIED",
    )

    serialized = d.to_dict()

    # Simulate fresh startup — no domains registered
    DomainManager.clear()

    restored = Domain.from_dict(serialized)
    assert restored.domain_id == "PY_LOOPS"
    assert str(restored.flexo_id) == str(d.flexo_id)

    # Manager must now contain it
    # assert DomainManager.get("PY_LOOPS") == restored

