import unittest
from datetime import datetime
from analogai.foundation.modules.direct_statement.direct_statement import DirectStatement
from analogai.foundation.modules.notion.notion import Notion
from analogai.foundation.modules.user.user import User
from analogai.foundation.modules.agent.agent import Agent
from analogai.foundation.core.value_objects.relation import Relation
from analogai.foundation.core.value_objects.modifier import Modifier


class TestStatement(unittest.TestCase):
    def setUp(self):
        self.user = User(id="user_id", name="Test User", email="test@example.com")
        self.agent = Agent(id="agent_id", knowledge_base="Test KB", creator=self.user, roles=[])

        self.subject_notion = Notion(
            user_id=self.user.id,
            agent_id=self.agent.id,
            caption="socrates",
            id="socrates_id",
        )
        self.relation = Relation.from_string("sell")
        self.complement_notion = Notion(
            user_id=self.user.id,
            agent_id=self.agent.id,
            caption="iphone",
            id="iphone_id",
        )

    def test_statement_initialization(self):
        statement = DirectStatement(
            user_id=self.user.id,
            agent_id=self.agent.id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
        )

        self.assertIsNotNone(statement.id)
        self.assertEqual(statement.user_id, self.user.id)
        self.assertEqual(statement.agent_id, self.agent.id)
        self.assertEqual(statement.subject_notion, self.subject_notion)
        self.assertEqual(statement.relation, self.relation)
        self.assertEqual(statement.complement_notion, self.complement_notion)
        self.assertIsNone(statement.quantity)
        self.assertIsNotNone(statement.created_at)
        self.assertIsInstance(statement.created_at, datetime)

    def test_statement_with_quantity(self):
        statement = DirectStatement(
            user_id=self.user.id,
            agent_id=self.agent.id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            modifier=Modifier(quantity=2.0),
        )
        self.assertEqual(statement.quantity, 2.0)

    def test_statement_with_custom_created_at(self):
        custom_time = datetime(2024, 1, 15, 10, 30, 0)
        statement = DirectStatement(
            user_id=self.user.id,
            agent_id=self.agent.id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            created_at=custom_time,
        )
        self.assertEqual(statement.created_at, custom_time)

    def test_statement_with_custom_id(self):
        custom_id = "custom_statement_id"
        statement = DirectStatement(
            user_id=self.user.id,
            agent_id=self.agent.id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
            id=custom_id,
        )
        self.assertEqual(statement.id, custom_id)

    def test_statement_raises_error_on_empty_user_id(self):
        with self.assertRaises(ValueError) as context:
            DirectStatement(
                user_id="",
                agent_id=self.agent.id,
                subject_notion=self.subject_notion,
                relation=self.relation,
                complement_notion=self.complement_notion,
            )
        self.assertIn("user_id must be a non-empty string", str(context.exception))

    def test_statement_raises_error_on_empty_relation(self):
        with self.assertRaises(ValueError) as context:
            DirectStatement(
                user_id=self.user.id,
                agent_id=self.agent.id,
                subject_notion=self.subject_notion,
                relation=Relation.from_string(""),
                complement_notion=self.complement_notion,
            )
        self.assertIn("relation cannot be empty", str(context.exception))


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