import unittest
from collections import deque
from unittest import TestCase
from unittest.mock import MagicMock
from analogai.deepthink.application.usecases.chat.chat_response_stack import ChatResponseStack
from analogai.deepthink.tests.mocks.entities.mock_belief_factory import MockBeliefFactory
from analogai.deepthink.tests.mocks.entities.mock_notion_factory import MockNotionFactory

class TestChatResponseStack(TestCase):
    def setUp(self):
        self.stack = ChatResponseStack()
        self.user_id = "test-user"
        self.agent_id = "test-agent"

        def create_belief(object_caption: str, relation: str, subject_caption: str):
            subject_notion = MockNotionFactory.create(caption=subject_caption)
            complement_notion = MockNotionFactory.create(caption=object_caption)
            belief = MockBeliefFactory.create(
                subject_notion=subject_notion,
                complement_notion=complement_notion,
            )
            belief.relation = relation
            return belief

        self.create_belief = create_belief

    def test_add_valid_response(self):
        response = self.create_belief("test_response", "positive", "user")
        self.stack.add(response)
        self.assertEqual(self.stack.get_size(), 1)
        latest = self.stack.get_latest()
        self.assertEqual(latest.complement_notion.caption, response.complement_notion.caption)
        self.assertEqual(latest.relation, response.relation)
        self.assertEqual(latest.subject_notion.caption, response.subject_notion.caption)

    def test_add_empty_response(self):
        initial_size = self.stack.get_size()
        self.stack.add(self.create_belief("", "positive", "user"))
        self.assertEqual(self.stack.get_size(), initial_size + 1)

    def test_add_none_response(self):
        initial_size = self.stack.get_size()
        self.stack.add(None)
        self.assertEqual(self.stack.get_size(), initial_size)

    def test_add_exceeds_max_size(self):
        for i in range(ChatResponseStack.MAX_SIZE + 2):
            self.stack.add(self.create_belief(f"response_{i}", "positive", "user"))
        self.assertEqual(self.stack.get_size(), ChatResponseStack.MAX_SIZE)
        expected = [
            self.create_belief(f"response_{i}", "positive", "user")
            for i in range(2, ChatResponseStack.MAX_SIZE + 2)
        ]
        actual = list(self.stack.get_all())
        for a, e in zip(actual, expected):
            self.assertEqual(a.complement_notion.caption, e.complement_notion.caption)
            self.assertEqual(a.relation, e.relation)
            self.assertEqual(a.subject_notion.caption, e.subject_notion.caption)

    def test_get_latest_empty_stack(self):
        result = self.stack.get_latest()
        self.assertIsNone(result)

    def test_get_latest_with_responses(self):
        self.stack.add(self.create_belief("first", "positive", "user"))
        self.stack.add(self.create_belief("second", "positive", "user"))
        result = self.stack.get_latest()
        self.assertEqual(result.complement_notion.caption, "second")
        self.assertEqual(result.relation, "positive")
        self.assertEqual(result.subject_notion.caption, "user")

    def test_get_size_empty(self):
        self.assertEqual(self.stack.get_size(), 0)

    def test_get_size_with_responses(self):
        self.stack.add(self.create_belief("first", "positive", "user"))
        self.stack.add(self.create_belief("second", "positive", "user"))
        self.assertEqual(self.stack.get_size(), 2)

    def test_get_all_empty(self):
        self.assertEqual(list(self.stack.get_all()), [])

    def test_get_all_with_responses(self):
        responses = [
            self.create_belief("first", "positive", "user"),
            self.create_belief("second", "positive", "user"),
            self.create_belief("third", "positive", "user")
        ]
        for response in responses:
            self.stack.add(response)
        actual = list(self.stack.get_all())
        for a, e in zip(actual, responses):
            self.assertEqual(a.complement_notion.caption, e.complement_notion.caption)
            self.assertEqual(a.relation, e.relation)
            self.assertEqual(a.subject_notion.caption, e.subject_notion.caption)

    def test_clear(self):
        self.stack.add(self.create_belief("first", "positive", "user"))
        self.stack.add(self.create_belief("second", "positive", "user"))
        self.stack.clear()
        self.assertEqual(self.stack.get_size(), 0)
        self.assertEqual(list(self.stack.get_all()), [])
        result = self.stack.get_latest()
        self.assertIsNone(result)

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


