import unittest
from analogai.foundation.extensions.conversation.factories import ConversationServiceFactory
from analogai.foundation.tests.functional.services.setup import ServicesTestConfig


class TestConversationServiceFunctional(unittest.TestCase):
    def setUp(self):
        self.config = ServicesTestConfig()
        self.conversation_service = ConversationServiceFactory().create()
        self.test_user = self.config.user
        self.test_agent = self.config.agent

    def tearDown(self):
        self.config.tear_down()

    def test_start_and_add_turns_to_conversation(self):
        conversation = self.conversation_service.start_conversation(self.test_user.id, self.test_agent.id)

        self.assertIsNotNone(conversation.id)
        self.assertEqual(conversation.user.id, self.test_user.id)
        self.assertEqual(conversation.agent.id, self.test_agent.id)

        turn = self.conversation_service.add_turn(
            conversation.id, self.test_user.id, self.test_agent.id,
            "Hello", "Hi there"
        )

        self.assertIsNotNone(turn.id)
        self.assertEqual(turn.user_id, self.test_user.id)
        self.assertEqual(turn.agent_id, self.test_agent.id)
        self.assertEqual(turn.user_message, "Hello")
        self.assertEqual(turn.agent_response, "Hi there")

    def test_get_conversations_by_agent(self):
        conv1 = self.conversation_service.start_conversation(self.test_user.id, self.test_agent.id)
        conv2 = self.conversation_service.start_conversation(self.test_user.id, self.test_agent.id)

        conversations = self.conversation_service.get_conversations_by_agent_id(self.test_agent.id)

        self.assertEqual(len(conversations), 2)
        self.assertIn(conv1.id, [c.id for c in conversations])
        self.assertIn(conv2.id, [c.id for c in conversations])

    def test_get_recent_turns_from_conversation(self):
        conversation = self.conversation_service.start_conversation(self.test_user.id, self.test_agent.id)
        self.conversation_service.add_turn(conversation.id, self.test_user.id, self.test_agent.id, "Message 1", "Response 1")
        self.conversation_service.add_turn(conversation.id, self.test_user.id, self.test_agent.id, "Message 2", "Response 2")

        retrieved_conversation = self.conversation_service.find(conversation.id)
        recent_turns = retrieved_conversation.get_recent_turns(limit=10)

        self.assertEqual(len(recent_turns), 2)
        self.assertEqual(recent_turns[0].user_message, "Message 1")
        self.assertEqual(recent_turns[1].user_message, "Message 2")

    def test_get_latest_turn_from_conversation(self):
        conversation = self.conversation_service.start_conversation(self.test_user.id, self.test_agent.id)
        self.conversation_service.add_turn(conversation.id, self.test_user.id, self.test_agent.id, "Message 1", "Response 1")
        self.conversation_service.add_turn(conversation.id, self.test_user.id, self.test_agent.id, "Message 2", "Response 2")

        retrieved_conversation = self.conversation_service.find(conversation.id)
        latest_turn = retrieved_conversation.get_latest_turn()

        self.assertIsNotNone(latest_turn)
        self.assertEqual(latest_turn.user_message, "Message 2")
        self.assertEqual(latest_turn.agent_response, "Response 2")

    def test_delete_conversation(self):
        conversation = self.conversation_service.start_conversation(self.test_user.id, self.test_agent.id)

        success = self.conversation_service.delete_conversation(conversation.id)

        self.assertTrue(success)
        retrieved = self.conversation_service.find(conversation.id)
        self.assertIsNone(retrieved)

    def test_ensure_conversation_exists_returns_existing_conversation(self):
        conversation = self.conversation_service.start_conversation(self.test_user.id, self.test_agent.id)

        ensured_conversation = self.conversation_service.ensure_conversation_exists(self.test_user.id, self.test_agent.id)

        self.assertIsNotNone(ensured_conversation)
        self.assertEqual(ensured_conversation.id, conversation.id)
        self.assertEqual(ensured_conversation.user.id, self.test_user.id)
        self.assertEqual(ensured_conversation.agent.id, self.test_agent.id)

    def test_ensure_conversation_exists_creates_new_conversation_when_none_exists(self):
        ensured_conversation = self.conversation_service.ensure_conversation_exists(self.test_user.id, self.test_agent.id)

        self.assertIsNotNone(ensured_conversation)
        self.assertIsNotNone(ensured_conversation.id)
        self.assertEqual(ensured_conversation.user.id, self.test_user.id)
        self.assertEqual(ensured_conversation.agent.id, self.test_agent.id)

        retrieved = self.conversation_service.find(ensured_conversation.id)
        self.assertIsNotNone(retrieved)
        self.assertEqual(retrieved.id, ensured_conversation.id)


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