import unittest

from analogai.foundation.common.enums.criterion import Criterion
from analogai.foundation.common.enums.certainty import Certainty
from analogai.foundation.common.enums.deontic_modality import DeonticModality
from analogai.foundation.core.value_objects.relation import Relation
from analogai.foundation.core.value_objects.time import Time
from analogai.foundation.common.utils.statement_serializers.condition_serializer import serialize_condition
from analogai.foundation.common.utils.statement_serializers.hypothetical_statement_serializer import (
    serialize_hypothetical_statement,
)
from analogai.foundation.core.value_objects.cause import Cause
from analogai.foundation.core.value_objects.effect import Effect
from analogai.foundation.modules.conditionals.hypothetical_statement import HypotheticalStatement


class TestConditionSerializer(unittest.TestCase):
    def test_serialize_condition_basic(self):
        criteria = {
            Criterion.SubjectCaption: "socrates",
            Criterion.ObjectCaption: "mortal",
            Criterion.Relation: Relation.from_string("is"),
            Criterion.Location: "athens",
        }
        result = serialize_condition(criteria)
        self.assertIn("socrates", result.lower())
        self.assertIn("mortal", result.lower())
        self.assertIn("athens", result.lower())

    def test_serialize_condition_with_deontic(self):
        criteria = {
            Criterion.SubjectCaption: "aristotle",
            Criterion.ObjectCaption: "iphone",
            Criterion.Relation: Relation.from_string("do"),
            Criterion.DeonticModality: DeonticModality.OBLIGATORY,
        }
        result = serialize_condition(criteria)
        self.assertIn("aristotle", result.lower())
        self.assertIn("iphone", result.lower())
        self.assertIn("must", result.lower())

    def test_serialize_condition_missing_fields(self):
        criteria = {
            Criterion.SubjectCaption: "socrates",
        }
        result = serialize_condition(criteria)
        self.assertEqual(result, "")

    def test_serialize_condition_with_uncertain_certainty(self):
        criteria = {
            Criterion.SubjectCaption: "socrates",
            Criterion.ObjectCaption: "mortal",
            Criterion.Relation: Relation.from_string("is"),
            Criterion.Certainty: Certainty.UNCERTAIN,
            Criterion.RelationProbability: 1.0,
        }
        result = serialize_condition(criteria)
        self.assertIn("might be", result.lower())

    def test_serialize_condition_with_negated_certainty(self):
        criteria = {
            Criterion.SubjectCaption: "socrates",
            Criterion.ObjectCaption: "mortal",
            Criterion.Relation: Relation.from_string("is"),
            Criterion.Certainty: Certainty.NEGATED,
            Criterion.RelationProbability: 1.0,
        }
        result = serialize_condition(criteria)
        self.assertIn("is not", result.lower())

    def test_serialize_condition_negated_includes_time_and_location(self):
        criteria = {
            Criterion.SubjectCaption: "socrates",
            Criterion.ObjectCaption: "mortal",
            Criterion.Relation: Relation.from_string("is"),
            Criterion.Certainty: Certainty.NEGATED,
            Criterion.FromTime: Time(year=1991),
            Criterion.Location: "athens",
        }
        result = serialize_condition(criteria)
        self.assertIn("1991", result)
        self.assertIn("athens", result.lower())
        self.assertIn("not", result.lower())


class TestHypotheticalStatementSerializer(unittest.TestCase):
    def test_serialize_hypothetical_statement(self):
        hypothetical = HypotheticalStatement(
            agent_id="agent-1",
            causes=[
                Cause({
                    Criterion.SubjectCaption: "it",
                    Criterion.ObjectCaption: "rain",
                    Criterion.Relation: Relation.from_string("is"),
                }),
                Cause({
                    Criterion.SubjectCaption: "it",
                    Criterion.ObjectCaption: "cold",
                    Criterion.Relation: Relation.from_string("is"),
                    Criterion.FromTime: Time(year=2024, month=1, day=1),
                }),
            ],
            effect=Effect({
                Criterion.SubjectCaption: "it",
                Criterion.ObjectCaption: "wet",
                Criterion.Relation: Relation.from_string("is"),
                Criterion.Certainty: Certainty.CERTAIN,
            }),
        )
        result = serialize_hypothetical_statement(hypothetical)
        self.assertTrue(result.startswith("If "))
        self.assertIn("then", result.lower())
        self.assertIn("rain", result.lower())
        self.assertIn("wet", result.lower())


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