import unittest

from analogai.foundation.common.enums import RelationshipType
from analogai.foundation.core.value_objects.relation import Relation
from analogai.deepthink.presentation.intent_type import IntentType
from analogai.deepthink.presentation.parsers.parsers_factory import build_message_parser


class TestSentenceParserTransformed(unittest.TestCase):
    def setUp(self):
        self.parser = build_message_parser()

    def test_parses_statement(self):
        parsed_list = self.parser.parse('{"intent":"making_statement","subject":"socrates","relationship":"is_a","object":"mortal","probability":1.0}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_STATEMENT)
        self.assertEqual(parsed.data.relation, Relation.from_type(RelationshipType.IS_A))
        self.assertEqual(parsed.data.subject.caption, "socrates")
        self.assertEqual(parsed.data.complement.caption, "mortal")

    def test_parses_price_statement(self):
        parsed_list = self.parser.parse('{"intent":"attribute_quantity_statement","subject":"iphone 12","attributes":[{"tag":"price","value":"800","unit":"usd"}]}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_STATEMENT)
        self.assertEqual(len(parsed.data.subject.attributes), 1)
        attr = parsed.data.subject.attributes[0]
        self.assertEqual(attr.tag, "price")
        self.assertEqual(attr.value, 800.0)
        self.assertEqual(attr.unit, "USD")

    def test_parses_quantity_statement(self):
        parsed_list = self.parser.parse('{"intent":"attribute_quantity_statement","subject":"socrates","attributes":[{"tag":"height","value":"200","unit":"cm"}]}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_STATEMENT)
        self.assertEqual(len(parsed.data.subject.attributes), 1)
        attr = parsed.data.subject.attributes[0]
        self.assertEqual(attr.tag, "height")
        self.assertEqual(attr.value, 200.0)
        self.assertEqual(attr.unit, "cm")

    def test_parses_weight_statement(self):
        parsed_list = self.parser.parse('{"intent":"attribute_quantity_statement","subject":"box","attributes":[{"tag":"weight","value":"10","unit":"kg"}]}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_STATEMENT)
        self.assertEqual(len(parsed.data.subject.attributes), 1)
        attr = parsed.data.subject.attributes[0]
        self.assertEqual(attr.tag, "weight")
        self.assertEqual(attr.value, 10.0)
        self.assertEqual(attr.unit, "kg")

    def test_parses_width_statement(self):
        parsed_list = self.parser.parse('{"intent":"attribute_quantity_statement","subject":"table","attributes":[{"tag":"width","value":"120","unit":"cm"}]}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_STATEMENT)
        self.assertEqual(len(parsed.data.subject.attributes), 1)
        attr = parsed.data.subject.attributes[0]
        self.assertEqual(attr.tag, "width")
        self.assertEqual(attr.value, 120.0)
        self.assertEqual(attr.unit, "cm")

    def test_parses_length_statement(self):
        parsed_list = self.parser.parse('{"intent":"attribute_quantity_statement","subject":"rope","attributes":[{"tag":"length","value":"25","unit":"m"}]}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_STATEMENT)
        self.assertEqual(len(parsed.data.subject.attributes), 1)
        attr = parsed.data.subject.attributes[0]
        self.assertEqual(attr.tag, "length")
        self.assertEqual(attr.value, 25.0)
        self.assertEqual(attr.unit, "m")

    def test_parses_depth_statement(self):
        parsed_list = self.parser.parse('{"intent":"attribute_quantity_statement","subject":"lake","attributes":[{"tag":"depth","value":"30","unit":"m"}]}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_STATEMENT)
        self.assertEqual(len(parsed.data.subject.attributes), 1)
        attr = parsed.data.subject.attributes[0]
        self.assertEqual(attr.tag, "depth")
        self.assertEqual(attr.value, 30.0)
        self.assertEqual(attr.unit, "m")

    def test_parses_area_statement(self):
        parsed_list = self.parser.parse('{"intent":"attribute_quantity_statement","subject":"yard","attributes":[{"tag":"area","value":"50","unit":"sq ft"}]}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_STATEMENT)
        self.assertEqual(len(parsed.data.subject.attributes), 1)
        attr = parsed.data.subject.attributes[0]
        self.assertEqual(attr.tag, "area")
        self.assertEqual(attr.value, 50.0)
        self.assertEqual(attr.unit, "sq ft")

    def test_parses_price_statement_price_tag(self):
        parsed_list = self.parser.parse('{"intent":"attribute_quantity_statement","subject":"iphone 12","attributes":[{"tag":"price","value":"850","unit":"usd"}]}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_STATEMENT)
        self.assertEqual(len(parsed.data.subject.attributes), 1)
        attr = parsed.data.subject.attributes[0]
        self.assertEqual(attr.tag, "price")
        self.assertEqual(attr.value, 850.0)
        self.assertEqual(attr.unit, "USD")

    def test_parses_modifier_tags(self):
        parsed_list = self.parser.parse('{"intent":"making_statement","time_from":"14:00","time_to":"16:00","subject":"it","relationship":"has_property","object":"rain","probability":1.0}')
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.data.from_time, "14:00")
        self.assertEqual(parsed.data.to_time, "16:00")

    def test_parses_multiple_sentences(self):
        parsed_list = self.parser.parse(
            '{"sentences":[{"intent":"making_statement","subject":"iphone 12","relationship":"is","object":"product","probability":1.0},{"intent":"making_statement","subject":"macbook pro","relationship":"is","object":"product","probability":1.0}]}',
        )
        self.assertEqual(len(parsed_list), 2)
        self.assertEqual(parsed_list[0].data.subject.caption, "iphone 12")
        self.assertEqual(parsed_list[0].data.complement.caption, "product")
        self.assertEqual(parsed_list[1].data.subject.caption, "macbook pro")
        self.assertEqual(parsed_list[1].data.complement.caption, "product")

    def test_transforms_condition_to_causal(self):
        json_input = '{"sentences":[{"intent":"making_statement","condition":{"subject":"it","relationship":"is","object":"day","location":"london"},"subject":"stock market","relationship":"work","probability":1.0}]}'
        parsed_list = self.parser.parse(json_input)
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.intent_type, IntentType.MAKING_CAUSAL_STATEMENT)
        self.assertEqual(parsed.data.relation, Relation.from_type(RelationshipType.CAUSES))
        self.assertIn("day", parsed.data.subject.caption)
        self.assertIn("london", parsed.data.subject.caption)
        self.assertEqual(parsed.data.complement.caption, "stock market work")

    def test_parses_until_time_as_to_time(self):
        parsed_list = self.parser.parse(
            '{"intent":"making_statement","time":"until 1846","subject":"arthur\'s magazine","relationship":"is","object":"active","probability":1.0}'
        )
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertIsNone(parsed.data.from_time)
        self.assertEqual(parsed.data.to_time, "1846")

    def test_parses_till_time_as_to_time(self):
        parsed_list = self.parser.parse(
            '{"intent":"making_statement","time":"till 1846","subject":"arthur\'s magazine","relationship":"is","object":"active","probability":1.0}'
        )
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertIsNone(parsed.data.from_time)
        self.assertEqual(parsed.data.to_time, "1846")

    def test_parses_after_time_as_from_time(self):
        parsed_list = self.parser.parse(
            '{"intent":"making_statement","time":"after 1846","subject":"arthur\'s magazine","relationship":"is","object":"active","probability":1.0}'
        )
        self.assertTrue(parsed_list)
        parsed = parsed_list[0]
        self.assertEqual(parsed.data.from_time, "1846")
        self.assertIsNone(parsed.data.to_time)


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

