import unittest
from unittest.mock import Mock
from datetime import datetime
from analogai.foundation.extensions.conversation import ConversationService
from analogai.foundation.modules.user.user import User
from analogai.foundation.modules.agent.agent import Agent, Role
from analogai.foundation.extensions.conversation.conversation import Conversation
from analogai.foundation.extensions.conversation.turn import Turn


class TestConversationService(unittest.TestCase):
    def setUp(self):
        self.repository = Mock()
        self.conversation_service = ConversationService(self.repository)
        self.test_user = User(id="user_123", name="Test User", email="test@example.com")
        self.test_agent = Agent(
            id="agent_456",
            knowledge_base="Test KB",
            creator=self.test_user,
            roles=[Role(user=self.test_user, authority=1.0)],
        )

    def test_start_conversation(self):
        expected_conversation = Conversation(
            id="conv_1",
            user=self.test_user,
            agent=self.test_agent,
            created_at=datetime.now(),
            updated_at=datetime.now(),
        )
        self.repository.create_conversation.return_value = expected_conversation
        result = self.conversation_service.start_conversation(self.test_user.id, self.test_agent.id)
        self.repository.create_conversation.assert_called_once_with(self.test_user.id, self.test_agent.id)
        self.assertEqual(result, expected_conversation)

    def test_add_turn(self):
        self.repository.add_turn.return_value = None

        turn = self.conversation_service.add_turn(
            "conv_1", "user_123", "agent_456", "Hello", "Hi there",
        )

        self.repository.add_turn.assert_called_once()
        self.assertIsNotNone(turn)
        self.assertEqual(turn.user_id, "user_123")
        self.assertEqual(turn.agent_id, "agent_456")
        self.assertEqual(turn.user_message, "Hello")
        self.assertEqual(turn.agent_response, "Hi there")

    def test_find(self):
        expected_conversation = Conversation(
            id="conv_1",
            user=self.test_user,
            agent=self.test_agent,
            created_at=datetime.now(),
            updated_at=datetime.now(),
        )
        self.repository.find_by_id.return_value = expected_conversation

        result = self.conversation_service.find("conv_1")

        self.repository.find_by_id.assert_called_once_with("conv_1")
        self.assertEqual(result, expected_conversation)

    def test_get_conversations_by_agent(self):
        expected_conversations = [
            Conversation(
                id="conv_1",
                user=self.test_user,
                agent=self.test_agent,
                created_at=datetime.now(),
                updated_at=datetime.now(),
            ),
        ]
        self.repository.find_by_agent.return_value = expected_conversations

        result = self.conversation_service.get_conversations_by_agent_id(
            self.test_agent.id, page=1, page_size=10,
        )

        self.repository.find_by_agent.assert_called_once_with(
            self.test_agent.id, 1, 10,
        )
        self.assertEqual(result, expected_conversations)

    def test_delete_conversation(self):
        self.repository.delete_conversation.return_value = True

        result = self.conversation_service.delete_conversation("conv_1")

        self.repository.delete_conversation.assert_called_once_with("conv_1")
        self.assertTrue(result)


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