import unittest
from datetime import datetime
from unittest.mock import Mock

from analogai.foundation.common.enums import RelationshipType
from analogai.foundation.core.value_objects import Relation
from analogai.foundation.core.value_objects.modifier import Modifier
from analogai.foundation.core.value_objects.time import Time
from analogai.foundation.common.enums.deontic_modality import DeonticModality
from analogai.foundation.common.design_patterns.state_machine import StateMachine
from analogai.deepthink.application.usecases.learning.make_direct_statement.usecase import MakeDirectStatementUseCase
from analogai.deepthink.application.usecases.learning.make_direct_statement.states.context.learner_context import LearnerContext
from analogai.deepthink.application.usecases.learning.make_direct_statement.states.context.learner_context_handler import LearnerContextHandler


class TestCreateStatementUseCase(unittest.TestCase):
    def setUp(self):
        self.context = LearnerContext()
        self.context_handler = LearnerContextHandler(self.context, Mock())
        self.usecase = MakeDirectStatementUseCase(
            Mock(), Mock(), Mock(), self.context_handler, Mock()
        )
        self.find_statement_state = Mock()
        self.update_statement_state = Mock()
        self.create_statement_state = Mock()

    def test_init(self):
        self.assertIsInstance(self.usecase, StateMachine)
        self.assertIsNotNone(self.usecase.find_statement_state)
        self.assertIsNotNone(self.usecase.update_statement_state)
        self.assertIsNotNone(self.usecase.create_statement_state)
        self.assertEqual(self.usecase.context, self.context)

    def test_execute(self):
        request = Mock()
        request.user_agent = Mock()
        request.user_agent.user_id = "user"
        request.user_agent.agent_id = "agent"
        request.user_agent.user_authority = 0.8
        request.subject_notion_expression = Mock()
        request.complement_notion_expression = Mock()
        request.relation = Relation.from_type(RelationshipType.IS_A)
        request.probability = 1.0
        request.modifier = None
        self.context_handler.notion_service.find_or_create = Mock(side_effect=[Mock(), Mock()])
        self.usecase._execute_state_machine = Mock(return_value="find_state_result")
        self.usecase.set_context = Mock()

        result = self.usecase.execute(request)

        self.usecase._execute_state_machine.assert_called_once()
        self.assertEqual(result, "find_state_result")

    def test_set_find_statement_state(self):
        self.usecase.find_statement_state = self.find_statement_state
        self.assertEqual(self.usecase.find_statement_state, self.find_statement_state)

    def test_set_check_update_statement_applicable_state(self):
        self.usecase.update_statement_state = self.update_statement_state
        self.assertEqual(self.usecase.update_statement_state, self.update_statement_state)

    def test_set_create_statement_state(self):
        self.usecase.create_statement_state = self.create_statement_state
        self.assertEqual(self.usecase.create_statement_state, self.create_statement_state)

    def test_state_to_find_statement(self):
        self.usecase.find_statement_state = self.find_statement_state
        self.usecase.state_to = Mock(return_value="find_state_result")

        result = self.usecase.state_to_find_statement()

        self.usecase.state_to.assert_called_once_with(self.find_statement_state)
        self.assertEqual(result, "find_state_result")

    def test_state_to_check_update_statement_applicable(self):
        self.usecase.update_statement_state = self.update_statement_state
        self.usecase.state_to = Mock(return_value="update_result")

        result = self.usecase.state_to_update_statement()

        self.usecase.state_to.assert_called_once_with(self.update_statement_state)
        self.assertEqual(result, "update_result")

    def test_state_to_create_statement(self):
        self.usecase.create_statement_state = self.create_statement_state
        self.usecase.state_to = Mock(return_value="create_state_result")

        result = self.usecase.state_to_create_statement()

        self.usecase.state_to.assert_called_once_with(self.create_statement_state)
        self.assertEqual(result, "create_state_result")

    def test_context_handles_modifier(self):
        today = datetime.now()
        modifier = Modifier(
            location="Tbilisi",
            from_time=Time(year=today.year, month=today.month, day=today.day),
            deontic_modality=DeonticModality.OBLIGATORY
        )

        self.context.modifier = modifier

        self.assertEqual(self.context.modifier, modifier)
        self.assertEqual(self.context.modifier.location, "Tbilisi")
        self.assertEqual(self.context.modifier.deontic_modality, DeonticModality.OBLIGATORY)

    def test_context_handles_none_modifier(self):
        self.context.modifier = None

        self.assertIsNone(self.context.modifier)

if __name__ == '__main__':
    unittest.main()




