import unittest
from unittest import TestCase
from unittest.mock import Mock
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.infrastructure.repositories.in_memory.in_memory_notion_repository_impl import InMemoryNotionRepositoryImpl
from analogai.foundation.infrastructure.storage.storage_adapter import StorageAdapter
from analogai.foundation.common.dtos.notion_expression import NotionExpression
from analogai.foundation.infrastructure.mappers.notion_storage_mapper import NotionStorageMapper
from analogai.foundation.settings import config

class TestInMemoryNotionRepositoryImpl(TestCase):
    def setUp(self):
        self._config_override = config.override(**{"vector.enabled": False})
        self._config_override.__enter__()
        self.storage_adapter = Mock(spec=StorageAdapter)
        self.repository = InMemoryNotionRepositoryImpl(storage_adapter=self.storage_adapter)
        
        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.test_notion = Notion(user_id=self.user.id, agent_id=self.agent.id, caption="human", id="notion_id")
        self.test_expression = NotionExpression(caption="human")
        self.test_id = "notion_id"
        self.test_collection = "notions"

    def test_create_calls_store_and_returns_notion(self):
        expected_data = NotionStorageMapper.to_dict(self.test_notion)
        self.storage_adapter.store.return_value = expected_data
        
        result = self.repository.create(self.test_notion)
        
        self.storage_adapter.store.assert_called_once_with(self.test_collection, expected_data)
        self.assertEqual(result, self.test_notion)

    def test_find_calls_retrieve_by_attributes(self):
        notion_data = NotionStorageMapper.to_dict(self.test_notion)
        self.storage_adapter.retrieve_by_attributes.return_value = [notion_data]
        
        result = self.repository.find(self.agent.id, self.test_expression)
        
        self.storage_adapter.retrieve_by_attributes.assert_called_once_with(self.test_collection, {"caption": "human", "agent_id": self.agent.id})
        self.assertEqual(result.id, self.test_notion.id)

    def test_find_no_result(self):
        self.storage_adapter.retrieve_by_attributes.return_value = []
        
        result = self.repository.find(self.agent.id, self.test_expression)
        
        self.storage_adapter.retrieve_by_attributes.assert_called_once_with(self.test_collection, {"caption": "human", "agent_id": self.agent.id})
        self.assertIsNone(result)

    def test_find_by_id(self):
        notion_data = NotionStorageMapper.to_dict(self.test_notion)
        self.storage_adapter.retrieve_by_id.return_value = notion_data
        
        result = self.repository.find_by_id(self.test_id)
        
        self.storage_adapter.retrieve_by_id.assert_called_once_with(self.test_collection, self.test_id)
        self.assertEqual(result.id, self.test_notion.id)

    def test_find_by_id_not_found(self):
        self.storage_adapter.retrieve_by_id.return_value = None
        
        result = self.repository.find_by_id("nonexistent_id")
        
        self.storage_adapter.retrieve_by_id.assert_called_once_with(self.test_collection, "nonexistent_id")
        self.assertIsNone(result)

    def tearDown(self):
        if self._config_override:
            self._config_override.__exit__(None, None, None)

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