from unittest import TestCase

from edpdependencyinjection import DependencyLoader

import testmodule
from dimessageprocessor import DiMessageProcessorMessageHandler
from testmodule.processor import SimpleProcessor, AnotherProcessor
from testmodule.callback import TestCallback


class TestDiMessageProcessorMessageHandler(TestCase):

    def setUp(self):
        self.dependency_loader = DependencyLoader()
        self.dependency_loader.load_modules(modules=[testmodule])
        self.dependency_context = self.dependency_loader.build_context()

    def test_init_with_event_definitions(self):
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
            event_processor_definitions={"order_created": SimpleProcessor}
        )
        self.assertIsNotNone(handler.event_processors)
        self.assertIn("order_created", handler.event_processors)

    def test_init_with_message_definitions(self):
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
            message_processor_definitions={0x01: SimpleProcessor}
        )
        self.assertIsNotNone(handler.message_processors)
        self.assertIn(0x01, handler.message_processors)

    def test_init_with_callback_definitions(self):
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
            event_processor_definitions={"order_created": SimpleProcessor},
            callback_definitions=[TestCallback]
        )
        self.assertIsNotNone(handler.executor_factory)

    def test_init_with_no_definitions(self):
        empty_loader = DependencyLoader()
        empty_context = empty_loader.build_context()
        handler = DiMessageProcessorMessageHandler(
            dependency_context=empty_context,
        )
        self.assertIsNone(handler.event_processors)
        self.assertIsNone(handler.message_processors)

    def test_init_with_instance_event_processor(self):
        instance = SimpleProcessor()
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
            event_processor_definitions={"order_created": instance}
        )
        self.assertIsNotNone(handler.event_processors)
        self.assertIn("order_created", handler.event_processors)

    def test_init_with_instance_message_processor(self):
        instance = SimpleProcessor()
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
            message_processor_definitions={0x01: instance}
        )
        self.assertIsNotNone(handler.message_processors)
        self.assertIn(0x01, handler.message_processors)

    def test_init_with_subject_counter(self):
        counter = {}
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
            event_processor_definitions={"order_created": SimpleProcessor},
            subject_counter=counter
        )
        self.assertIs(handler.subject_counter, counter)

    def test_init_with_both_event_and_message_definitions(self):
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
            event_processor_definitions={
                "order_created": SimpleProcessor,
                "order_cancelled": AnotherProcessor,
            },
            message_processor_definitions={
                0x01: SimpleProcessor,
                0x02: AnotherProcessor,
            }
        )
        self.assertIsNotNone(handler.event_processors)
        self.assertIsNotNone(handler.message_processors)
        self.assertIn("order_created", handler.event_processors)
        self.assertIn("order_cancelled", handler.event_processors)
        self.assertIn(0x01, handler.message_processors)
        self.assertIn(0x02, handler.message_processors)


class TestDiMessageProcessorMessageHandlerAutoMapped(TestCase):

    def setUp(self):
        self.dependency_loader = DependencyLoader()
        self.dependency_loader.load_modules(modules=[testmodule])
        self.dependency_context = self.dependency_loader.build_context()

    def test_discovers_event_builders(self):
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
        )
        self.assertIsNotNone(handler.event_processors)
        self.assertIn("builder_event", handler.event_processors)
        self.assertIn("builder_event_type", handler.event_processors)

    def test_discovers_message_builders(self):
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
        )
        self.assertIsNotNone(handler.message_processors)
        self.assertIn(0x10, handler.message_processors)
        self.assertIn(0x20, handler.message_processors)

    def test_merges_explicit_and_discovered_event_definitions(self):
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
            event_processor_definitions={"explicit_event": SimpleProcessor}
        )
        self.assertIn("explicit_event", handler.event_processors)
        self.assertIn("builder_event", handler.event_processors)
        self.assertIn("builder_event_type", handler.event_processors)

    def test_merges_explicit_and_discovered_message_definitions(self):
        handler = DiMessageProcessorMessageHandler(
            dependency_context=self.dependency_context,
            message_processor_definitions={0x01: SimpleProcessor}
        )
        self.assertIn(0x01, handler.message_processors)
        self.assertIn(0x10, handler.message_processors)
        self.assertIn(0x20, handler.message_processors)
