import unittest
from analogai.foundation.modules.agent.agent_service import AgentService
from analogai.foundation.modules.agent.agent import Agent, Role
from analogai.foundation.modules.user.user import User
from analogai.foundation.common.enums.agent_openness import AgentOpenness
from analogai.foundation.tests.functional.services.setup import ServicesTestConfig
from analogai.foundation.tests.functional.storage_cleaner import cleanup_storages
import uuid

class TestAgentServiceFunctional(unittest.TestCase):
    def setUp(self):
        self.config = ServicesTestConfig()
        self.agent_repository = self.config.agent_repository
        self.agent_service = AgentService(self.agent_repository)
        self.test_user = User(id=str(uuid.uuid4()), name="Test User", email="test@example.com")
        self.test_agent_id = str(uuid.uuid4())

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

    def test_create_and_find_agent(self):
        agent = self.agent_service.create(
            creator=self.test_user,
            id=self.test_agent_id,
            name="Test Agent",
            knowledge_base="Test knowledge base",
            roles=[]
        )
        
        self.assertEqual(agent.id, self.test_agent_id)
        self.assertEqual(agent.name, "Test Agent")
        self.assertEqual(agent.knowledge_base, "Test knowledge base")
        self.assertEqual(agent.creator, self.test_user)
        
        found_agent = self.agent_service.find(self.test_agent_id)
        self.assertIsNotNone(found_agent)
        self.assertEqual(found_agent.id, self.test_agent_id)
        self.assertEqual(found_agent.name, "Test Agent")

    def test_update_agent_success(self):
        original_agent = self.agent_service.create(
            creator=self.test_user,
            id=self.test_agent_id,
            knowledge_base="Original knowledge base",
            roles=[]
        )
        
        updated_agent = Agent(
            id=self.test_agent_id,
            knowledge_base="Updated knowledge base",
            creator=self.test_user,
            roles=[]
        )
        
        result = self.agent_service.update(updated_agent)
        
        self.assertEqual(result.id, self.test_agent_id)
        self.assertEqual(result.knowledge_base, "Updated knowledge base")
        
        found_agent = self.agent_service.find(self.test_agent_id)
        self.assertEqual(found_agent.knowledge_base, "Updated knowledge base")

    def test_update_agent_with_roles(self):
        role_user = User(id=str(uuid.uuid4()), name="Role User", email="role@example.com")
        role = Role(user=role_user, authority=0.8)
        
        original_agent = self.agent_service.create(
            creator=self.test_user,
            id=self.test_agent_id,
            knowledge_base="Original knowledge base",
            roles=[]
        )
        
        updated_agent = Agent(
            id=self.test_agent_id,
            knowledge_base="Updated knowledge base",
            creator=self.test_user,
            roles=[role]
        )
        
        result = self.agent_service.update(updated_agent)
        
        self.assertEqual(result.id, self.test_agent_id)
        self.assertEqual(len(result.roles), 1)
        self.assertEqual(result.roles[0].user, role_user)
        self.assertEqual(result.roles[0].authority, 0.8)
        
        found_agent = self.agent_service.find(self.test_agent_id)
        self.assertEqual(len(found_agent.roles), 1)
        self.assertEqual(found_agent.roles[0].user.id, role_user.id)

    def test_delete_agent_success(self):
        agent = self.agent_service.create(
            creator=self.test_user,
            id=self.test_agent_id,
            knowledge_base="Test knowledge base",
            roles=[]
        )
        
        found_agent = self.agent_service.find(self.test_agent_id)
        self.assertIsNotNone(found_agent)
        
        result = self.agent_service.delete(self.test_agent_id)
        
        self.assertTrue(result)
        
        deleted_agent = self.agent_service.find(self.test_agent_id)
        self.assertIsNone(deleted_agent)

    def test_delete_nonexistent_agent(self):
        result = self.agent_service.delete("nonexistent_agent_id")
        
        self.assertFalse(result)

    def test_delete_agent_with_empty_id(self):
        result = self.agent_service.delete("")
        
        self.assertFalse(result)

    def test_get_agents_by_creator(self):
        agent1 = self.agent_service.create(
            creator=self.test_user,
            id=str(uuid.uuid4()),
            knowledge_base="Knowledge base 1",
            roles=[]
        )
        
        agent2 = self.agent_service.create(
            creator=self.test_user,
            id=str(uuid.uuid4()),
            knowledge_base="Knowledge base 2",
            roles=[]
        )
        
        another_user = User(id=str(uuid.uuid4()), name="Another User", email="another@example.com")
        agent3 = self.agent_service.create(
            creator=another_user,
            id=str(uuid.uuid4()),
            knowledge_base="Knowledge base 3",
            roles=[]
        )
        
        creator_agents = self.agent_service.get_agents_by_creator(self.test_user.id)
        
        self.assertEqual(len(creator_agents), 2)
        agent_ids = [agent.id for agent in creator_agents]
        self.assertIn(agent1.id, agent_ids)
        self.assertIn(agent2.id, agent_ids)
        self.assertNotIn(agent3.id, agent_ids)

    def test_crud_operations_integration(self):
        agent_id = str(uuid.uuid4())
        
        created_agent = self.agent_service.create(
            creator=self.test_user,
            id=agent_id,
            name="CRUD Test Agent",
            knowledge_base="Test knowledge base",
            roles=[]
        )
        
        self.assertEqual(created_agent.id, agent_id)
        self.assertEqual(created_agent.name, "CRUD Test Agent")
        
        found_agent = self.agent_service.find(agent_id)
        self.assertIsNotNone(found_agent)
        self.assertEqual(found_agent.name, "CRUD Test Agent")
        self.assertEqual(found_agent.knowledge_base, "Test knowledge base")
        
        updated_agent = Agent(
            id=agent_id,
            name="Updated CRUD Agent",
            knowledge_base="Updated test knowledge base",
            creator=self.test_user,
            roles=[]
        )
        
        update_result = self.agent_service.update(updated_agent)
        self.assertEqual(update_result.name, "Updated CRUD Agent")
        self.assertEqual(update_result.knowledge_base, "Updated test knowledge base")
        
        verify_updated = self.agent_service.find(agent_id)
        self.assertEqual(verify_updated.name, "Updated CRUD Agent")
        self.assertEqual(verify_updated.knowledge_base, "Updated test knowledge base")
        
        delete_result = self.agent_service.delete(agent_id)
        self.assertTrue(delete_result)
        
        deleted_agent = self.agent_service.find(agent_id)
        self.assertIsNone(deleted_agent)

    def test_agent_openness_persistence(self):
        agent = self.agent_service.create(
            creator=self.test_user,
            id=self.test_agent_id,
            knowledge_base="Test knowledge base",
            roles=[]
        )
        
        agent.set_openness(AgentOpenness.CLOSED)
        
        updated_agent = self.agent_service.update(agent)
        
        self.assertEqual(updated_agent.openness, AgentOpenness.CLOSED)
        self.assertTrue(updated_agent.is_closed())
        self.assertFalse(updated_agent.is_open())
        
        found_agent = self.agent_service.find(self.test_agent_id)
        self.assertEqual(found_agent.openness, AgentOpenness.CLOSED)

    def test_agent_default_values(self):
        agent = self.agent_service.create(
            creator=self.test_user,
            id=self.test_agent_id,
            knowledge_base="Test knowledge base",
            roles=[]
        )

        self.assertEqual(agent.name, "")
        self.assertEqual(agent.openness, AgentOpenness.OPEN)

    def test_agent_name_persistence(self):
        agent = self.agent_service.create(
            creator=self.test_user,
            id=self.test_agent_id,
            name="Persistent Agent Name",
            knowledge_base="Test knowledge base",
            roles=[]
        )
        
        self.assertEqual(agent.name, "Persistent Agent Name")
        
        found_agent = self.agent_service.find(self.test_agent_id)
        self.assertIsNotNone(found_agent)
        self.assertEqual(found_agent.name, "Persistent Agent Name")
        
        updated_agent = Agent(
            id=self.test_agent_id,
            name="Updated Agent Name",
            knowledge_base="Test knowledge base",
            creator=self.test_user,
            roles=[]
        )
        
        update_result = self.agent_service.update(updated_agent)
        self.assertEqual(update_result.name, "Updated Agent Name")
        
        verify_updated = self.agent_service.find(self.test_agent_id)
        self.assertEqual(verify_updated.name, "Updated Agent Name")

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