# Protean
import pytest

from protean.core.unit_of_work import UnitOfWork

# Local/Relative Imports
from .aggregate_elements import Comment, Post, PostMeta, PostRepository


class TestUnitOfWorkRegistration:
    @pytest.fixture(autouse=True)
    def register_elements(self, test_domain):
        test_domain.register(Post)
        test_domain.register(PostMeta)
        test_domain.register(Comment)

        test_domain.register(PostRepository, aggregate_cls=Post)

        yield

    @pytest.fixture
    def persisted_post(self, test_domain):
        post = test_domain.get_dao(Post).create(title='Test Post', slug='test-post', content='Do Re Mi Fa')
        return post

    def test_that_an_entity_can_be_added_within_uow(self, test_domain, persisted_post):
        with UnitOfWork(test_domain) as uow:
            comment = Comment(content='So La Ti Do')
            persisted_post.comments.add(comment)

            repo = test_domain.repository_for(Post).within(uow)
            repo.add(persisted_post)

            assert comment.id in uow.changes_to_be_committed['default']['ADDED']

        repo = test_domain.repository_for(Post)
        post = repo.get(persisted_post.id)
        assert post.comments[0].content == 'So La Ti Do'

    def test_that_an_entity_can_be_updated_within_uow(self, test_domain, persisted_post):
        comment = Comment(content='So La Ti Do')
        persisted_post.comments.add(comment)

        repo = test_domain.repository_for(Post)
        repo.add(persisted_post)

        post = repo.get(persisted_post.id)
        assert post.comments[0].content == 'So La Ti Do'

        with UnitOfWork(test_domain) as uow:
            comment = persisted_post.comments[0]
            comment.content = ('Pa Da Ni Sa')
            persisted_post.comments.add(comment)

            repo = test_domain.repository_for(Post).within(uow)
            repo.add(persisted_post)

            assert comment.id in uow.changes_to_be_committed['default']['UPDATED']

        post = repo.get(persisted_post.id)
        assert post.comments[0].content == 'Pa Da Ni Sa'

    def test_that_an_entity_can_be_removed_within_uow(self, test_domain, persisted_post):
        comment = Comment(content='So La Ti Do')
        persisted_post.comments.add(comment)

        repo = test_domain.repository_for(Post)
        repo.add(persisted_post)

        with UnitOfWork(test_domain) as uow:
            comment = persisted_post.comments[0]
            persisted_post.comments.remove(comment)

            repo = test_domain.repository_for(Post).within(uow)
            repo.add(persisted_post)

            assert comment.id in uow.changes_to_be_committed['default']['REMOVED']

        post = repo.get(persisted_post.id)
        assert len(post.comments) == 0
