import unittest

from analogai.foundation.extensions.contradictions.contradiction_checker import is_belief_contradictory
from analogai.foundation.settings import config
from analogai.foundation.modules.belief.belief import Belief
from analogai.foundation.modules.direct_statement.direct_statement import DirectStatement
from analogai.foundation.modules.notion.notion import Notion
from analogai.foundation.core.value_objects.relation import Relation


class TestContradictionChecker(unittest.TestCase):
    def setUp(self):
        self.agent_id = "test_agent"
        self.user_id = "test_user"
        self.subject_notion = Notion(user_id=self.user_id, agent_id=self.agent_id, caption="Subject")
        self.complement_notion = Notion(user_id=self.user_id, agent_id=self.agent_id, caption="Object")
        self.relation = Relation.from_string("is")

    def _create_statement(self, probability, validity):
        return DirectStatement(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            complement_notion=self.complement_notion,
            relation=self.relation,
            probability=probability,
            validity=validity,
        )

    def _create_belief(self, statements):
        belief = Belief(agent_id=self.agent_id)
        for statement in statements:
            belief.add_statement(statement)
        return belief

    def test_high_variance_contradictory_belief(self):
        statement1 = self._create_statement(probability=0.9, validity=0.9)
        statement2 = self._create_statement(probability=0.1, validity=0.9)
        belief = self._create_belief([statement1, statement2])

        result = is_belief_contradictory(belief)

        self.assertTrue(result)

    def test_low_variance_non_contradictory_belief(self):
        statement1 = self._create_statement(probability=0.7, validity=0.8)
        statement2 = self._create_statement(probability=0.7, validity=0.8)
        statement3 = self._create_statement(probability=0.7, validity=0.8)
        belief = self._create_belief([statement1, statement2, statement3])

        result = is_belief_contradictory(belief)

        self.assertFalse(result)

    def test_single_statement_belief(self):
        statement = self._create_statement(probability=0.8, validity=0.8)
        belief = self._create_belief([statement])

        result = is_belief_contradictory(belief)

        self.assertFalse(result)

    def test_empty_belief_raises_error(self):
        belief = Belief(agent_id=self.agent_id)

        with self.assertRaises(ValueError) as context:
            is_belief_contradictory(belief)

        self.assertEqual(str(context.exception), "Cannot check contradiction for belief without statements")

    def test_variance_threshold_boundary(self):
        delta = (config.get("belief.variance", 0.1) ** 0.5) + 0.01
        statement1 = self._create_statement(probability=0.5 + delta, validity=1.0)
        statement2 = self._create_statement(probability=0.5 - delta, validity=1.0)
        belief = self._create_belief([statement1, statement2])

        result = is_belief_contradictory(belief)

        self.assertTrue(result)


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