import unittest
import uuid
from analogai.foundation.extensions.fallback import Fallback
from analogai.foundation.extensions.fallback.factories import FallbackServiceFactory
from analogai.foundation.tests.functional.services.setup import ServicesTestConfig


class TestFallbackServiceFunctional(unittest.TestCase):
    def setUp(self):
        self.config = ServicesTestConfig()
        self.fallback_service = FallbackServiceFactory().create()
        self.user = self.config.user
        self.agent = self.config.agent

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

    def test_create_fallback(self):
        user_question = "What is the meaning of life?"
        fallback = self.fallback_service.create(
            user_id=self.user.id,
            agent_id=self.agent.id,
            user_question=user_question
        )

        self.assertIsNotNone(fallback.id)
        self.assertEqual(fallback.user_id, self.user.id)
        self.assertEqual(fallback.agent_id, self.agent.id)
        self.assertEqual(fallback.user_question, user_question)
        self.assertIsNotNone(fallback.timestamp)

    def test_find_fallback_by_id(self):
        created_fallback = self.fallback_service.create(
            user_id=self.user.id,
            agent_id=self.agent.id,
            user_question="Test question"
        )

        found_fallback = self.fallback_service.find_by_id(created_fallback.id)

        self.assertIsNotNone(found_fallback)
        self.assertEqual(found_fallback.id, created_fallback.id)
        self.assertEqual(found_fallback.user_question, created_fallback.user_question)
        self.assertEqual(found_fallback.user_id, self.user.id)
        self.assertEqual(found_fallback.agent_id, self.agent.id)

    def test_find_fallback_by_id_not_found(self):
        found_fallback = self.fallback_service.find_by_id("nonexistent_id")
        self.assertIsNone(found_fallback)

    def test_find_fallbacks_by_agent_id(self):
        fallback1 = self.fallback_service.create(
            user_id=self.user.id,
            agent_id=self.agent.id,
            user_question="Question 1"
        )
        fallback2 = self.fallback_service.create(
            user_id=self.user.id,
            agent_id=self.agent.id,
            user_question="Question 2"
        )

        fallbacks = self.fallback_service.find_by_agent_id(self.agent.id)

        self.assertEqual(len(fallbacks), 2)
        fallback_ids = {f.id for f in fallbacks}
        self.assertIn(fallback1.id, fallback_ids)
        self.assertIn(fallback2.id, fallback_ids)

    def test_fallback_isolation_by_agent(self):
        agent2 = self.config.agent_service.create(
            creator=self.user,
            id=str(uuid.uuid4()),
            name="Agent 2",
            knowledge_base="KB 2",
            roles=[]
        )

        fallback_agent1 = self.fallback_service.create(
            user_id=self.user.id,
            agent_id=self.agent.id,
            user_question="Agent 1 question"
        )
        fallback_agent2 = self.fallback_service.create(
            user_id=self.user.id,
            agent_id=agent2.id,
            user_question="Agent 2 question"
        )

        agent1_fallbacks = self.fallback_service.find_by_agent_id(self.agent.id)
        agent2_fallbacks = self.fallback_service.find_by_agent_id(agent2.id)

        self.assertEqual(len(agent1_fallbacks), 1)
        self.assertEqual(agent1_fallbacks[0].id, fallback_agent1.id)
        self.assertEqual(len(agent2_fallbacks), 1)
        self.assertEqual(agent2_fallbacks[0].id, fallback_agent2.id)

    def test_fallback_timestamp_preserved(self):
        fallback = self.fallback_service.create(
            user_id=self.user.id,
            agent_id=self.agent.id,
            user_question="Test question"
        )
        original_timestamp = fallback.timestamp

        found_fallback = self.fallback_service.find_by_id(fallback.id)

        self.assertIsNotNone(found_fallback.timestamp)
        self.assertEqual(found_fallback.timestamp.isoformat(), original_timestamp.isoformat())


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