import logging, pytest
from common.database.api.Database import Database
from common.database.api.entity._Entity import _Entity
from common.database.api.entity.EntityAttributes import EntityAttributes
from common.database.api.Exceptions import WrongDatabaseEngine
from common.database.engines._DatabaseEngine import _DatabaseEngine
from common.database.engines.inmemory.InMemoryDatabaseEngine import InMemoryDatabaseEngine

logging.basicConfig(level=logging.INFO)

def test_database_gets_none_database_engine():
    # should fail with invalid database engine
    with pytest.raises(WrongDatabaseEngine) as e:
        Database(None)
    assert str(e.value) == 'database_engine must inherit from _DatabaseEngine'

def test_database_gets_correct_database_engine():
    # should work
    assert Database(InMemoryDatabaseEngine()) is not None

def test_entity_gets_invalid_parameters():

    # should fail with invalid parent
    with pytest.raises(AttributeError) as e:
        _Entity(None, 'valid-uuid', 'valid-attributes-key', {}, {})
    assert str(e.value) == 'parent must be an instance of _Entity'

    # should fail with invalid entity uuid
    with pytest.raises(AttributeError) as e:
        _Entity(Database(InMemoryDatabaseEngine()), None, 'valid-attributes-key', {}, {})
    assert str(e.value) == 'entity_uuid must be a non-empty instance of str'

    # should fail with invalid entity uuid
    with pytest.raises(AttributeError) as e:
        _Entity(Database(InMemoryDatabaseEngine()), '', 'valid-attributes-key', {}, {})
    assert str(e.value) == 'entity_uuid must be a non-empty instance of str'

    # should fail with invalid attribute key
    with pytest.raises(AttributeError) as e:
        _Entity(Database(InMemoryDatabaseEngine()), 'valid-uuid', None, {}, {})
    assert str(e.value) == 'attributes_key must be a non-empty instance of str'

    # should fail with invalid attribute key
    with pytest.raises(AttributeError) as e:
        _Entity(Database(InMemoryDatabaseEngine()), 'valid-uuid', '', {}, {})
    assert str(e.value) == 'attributes_key must be a non-empty instance of str'

    # should fail with invalid attribute validators
    with pytest.raises(AttributeError) as e:
        _Entity(Database(InMemoryDatabaseEngine()), 'valid-uuid', 'valid-attributes-key', [], {})
    assert str(e.value) == 'attribute_validators must be an instance of dict'

    # should fail with invalid attribute transcoders
    with pytest.raises(AttributeError) as e:
        _Entity(Database(InMemoryDatabaseEngine()), 'valid-uuid', 'valid-attributes-key', {}, [])
    assert str(e.value) == 'attribute_transcoders must be an instance of dict'

    # should work
    assert _Entity(Database(InMemoryDatabaseEngine()), 'valid-uuid', 'valid-attributes-key', {}, {}) is not None

def test_entity_attributes_gets_invalid_parameters():

    # should work
    root_entity = Database(InMemoryDatabaseEngine())
    validators = {'attr': lambda v: True}
    entity_attrs = EntityAttributes(root_entity, 'valid-attributes-key', validators, {})
    assert entity_attrs is not None

    with pytest.raises(AttributeError) as e:
        entity_attrs.update(update_attributes={'non-defined-attr': 'random-value'})
    assert str(e.value) == "Unexpected update_attributes: {'non-defined-attr': 'random-value'}"

    with pytest.raises(AttributeError) as e:
        entity_attrs.update(remove_attributes=['non-defined-attr'])
    assert str(e.value) == "Unexpected remove_attributes: {'non-defined-attr'}"
