import unittest
import uuid
from analogai.foundation.modules.belief.belief import Belief
from analogai.foundation.modules.direct_statement.direct_statement import DirectStatement as Statement
from analogai.foundation.modules.notion.notion import Notion
from analogai.foundation.core.value_objects.time import Time
from analogai.foundation.core.value_objects.modifier import Modifier
from analogai.foundation.core.value_objects.relation import Relation
from analogai.foundation.common.enums.deontic_modality import DeonticModality


class TestBeliefSpatiotemporalDeontic(unittest.TestCase):
    def setUp(self):
        self.agent_id = str(uuid.uuid4())
        self.user_id = str(uuid.uuid4())
        self.subject_notion = Notion(user_id=self.user_id, agent_id=self.agent_id, caption="human", id="human_id")
        self.complement_notion = Notion(user_id=self.user_id, agent_id=self.agent_id, caption="mortal", id="mortal_id")
        self.relation = Relation.from_string("is")

        self.belief = Belief(agent_id=self.agent_id)

    def test_initial_spatiotemporal_deontic_properties_are_none(self):
        
        self.assertIsNone(self.belief.location)
        self.assertIsNone(self.belief.from_time)
        self.assertIsNone(self.belief.to_time)
        self.assertIsNone(self.belief.deontic_modality)

    def test_location_set_from_first_statement(self):
        
        modifier = Modifier(location="New York")
        statement = Statement(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            probability=0.8,
            validity=0.9,
            modifier=modifier
        )
        self.belief.add_statement(statement)
        self.assertEqual(self.belief.location, "New York")

    def test_from_time_set_from_first_statement(self):
        
        from_time = Time(year=2024, month=1, day=1)
        modifier = Modifier(from_time=from_time)
        statement = Statement(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            probability=0.8,
            validity=0.9,
            modifier=modifier
        )
        self.belief.add_statement(statement)
        self.assertEqual(self.belief.from_time, from_time)
        self.assertEqual(self.belief.from_time.year, 2024)
        self.assertEqual(self.belief.from_time.month, 1)
        self.assertEqual(self.belief.from_time.day, 1)

    def test_to_time_set_from_first_statement(self):
        
        to_time = Time(year=2024, month=12, day=31)
        modifier = Modifier(to_time=to_time)
        statement = Statement(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            probability=0.8,
            validity=0.9,
            modifier=modifier
        )
        self.belief.add_statement(statement)
        self.assertEqual(self.belief.to_time, to_time)
        self.assertEqual(self.belief.to_time.year, 2024)
        self.assertEqual(self.belief.to_time.month, 12)
        self.assertEqual(self.belief.to_time.day, 31)

    def test_deontic_modality_set_from_first_statement(self):
        
        modifier = Modifier(deontic_modality=DeonticModality.OBLIGATORY)
        statement = Statement(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            probability=0.8,
            validity=0.9,
            modifier=modifier
        )
        self.belief.add_statement(statement)
        self.assertEqual(self.belief.deontic_modality, DeonticModality.OBLIGATORY)

    def test_all_parameters_set_from_first_statement(self):
        
        from_time = Time(year=2024, month=1, day=1, hour=10, minute=30)
        to_time = Time(year=2024, month=12, day=31, hour=23, minute=59)
        modifier = Modifier(
            location="Paris",
            from_time=from_time,
            to_time=to_time,
            deontic_modality=DeonticModality.PERMITTED
        )
        statement = Statement(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            probability=0.8,
            validity=0.9,
            modifier=modifier
        )
        self.belief.add_statement(statement)

        self.assertEqual(self.belief.location, "Paris")
        self.assertEqual(self.belief.from_time, from_time)
        self.assertEqual(self.belief.to_time, to_time)
        self.assertEqual(self.belief.deontic_modality, DeonticModality.PERMITTED)

    def test_parameters_persist_after_adding_multiple_statements(self):
        
        from_time = Time(year=2024, month=1)
        modifier1 = Modifier(
            location="London",
            from_time=from_time,
            deontic_modality=DeonticModality.FORBIDDEN
        )
        statement1 = Statement(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            probability=0.8,
            validity=0.9,
            modifier=modifier1
        )
        self.belief.add_statement(statement1)

        modifier2 = Modifier(
            location="London",
            from_time=from_time,
            deontic_modality=DeonticModality.FORBIDDEN
        )
        statement2 = Statement(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            probability=0.7,
            validity=0.8,
            modifier=modifier2
        )
        self.belief.add_statement(statement2)

        # Parameters should still be from first statement
        self.assertEqual(self.belief.location, "London")
        self.assertEqual(self.belief.from_time, from_time)
        self.assertEqual(self.belief.deontic_modality, DeonticModality.FORBIDDEN)


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