import unittest
from unittest.mock import Mock
from analogai.foundation.modules.user.user import User
from analogai.foundation.modules.agent.agent import Agent, Role
from analogai.foundation.modules.agent.agent_service import AgentService
from analogai.foundation.extensions.authorization.core.services import AuthorizationService
from analogai.foundation.extensions.authorization.core.enums.operation import AuthorizationOperation

class TestAuthorizationService(unittest.TestCase):
    def setUp(self):
        self.agent_service = Mock(spec=AgentService)
        self.authorization_service = AuthorizationService(self.agent_service)
        self.user1 = User(id="user-1", name="User 1", email="user1@example.com")
        self.user2 = User(id="user-2", name="User 2", email="user2@example.com")
        self.user3 = User(id="user-3", name="User 3", email="user3@example.com")
        self.role1 = Role(user=self.user1, authority=1.0)
        self.role2 = Role(user=self.user2, authority=0.5)
        self.agent1 = Agent(id="agent-1", knowledge_base="kb", creator=self.user1, roles=[self.role1, self.role2])
        self.agent2 = Agent(id="agent-2", knowledge_base="kb", creator=self.user2, roles=[self.role2])
        self.agent_no_roles = Agent(id="agent-3", knowledge_base="kb", creator=self.user1, roles=[])

    def test_authorize_user_for_agent_success(self):
        self.assertTrue(self.authorization_service.authorize_user_for_agent(self.user1, self.agent1))

    def test_authorize_user_for_agent_chat_access(self):
        self.assertTrue(self.authorization_service.authorize_user_for_agent(self.user3, self.agent1))

    def test_authorize_user_for_agent_no_access(self):
        self.assertFalse(
            self.authorization_service.authorize_user_for_agent(
                self.user3,
                self.agent1,
                AuthorizationOperation.EDIT,
            )
        )

    def test_authorize_user_for_agent_no_roles(self):
        self.assertFalse(
            self.authorization_service.authorize_user_for_agent(
                self.user1,
                self.agent_no_roles,
                AuthorizationOperation.EDIT,
            )
        )

    def test_authorize_user_for_agent_none_user(self):
        self.assertFalse(self.authorization_service.authorize_user_for_agent(None, self.agent1))

    def test_authorize_user_for_agent_none_agent(self):
        self.assertFalse(self.authorization_service.authorize_user_for_agent(self.user1, None))

    def test_find_and_authorize_agent_success(self):
        self.agent_service.find.return_value = self.agent1
        result = self.authorization_service.find_and_authorize_agent(self.user1, "agent-1")
        self.assertEqual(result, self.agent1)

    def test_find_and_authorize_agent_chat_access(self):
        self.agent_service.find.return_value = self.agent2
        result = self.authorization_service.find_and_authorize_agent(self.user1, "agent-2")
        self.assertEqual(result, self.agent2)

    def test_find_and_authorize_agent_not_found(self):
        self.agent_service.find.return_value = None
        with self.assertRaises(ValueError):
            self.authorization_service.find_and_authorize_agent(self.user1, "missing")

    def test_find_and_authorize_agent_unauthorized(self):
        self.agent_service.find.return_value = self.agent2
        with self.assertRaises(ValueError):
            self.authorization_service.find_and_authorize_agent(
                self.user1,
                "agent-2",
                AuthorizationOperation.EDIT,
            )

    def test_find_and_authorize_agent_none_user(self):
        with self.assertRaises(ValueError):
            self.authorization_service.find_and_authorize_agent(None, "agent-1")

    def test_check_user_access_with_role(self):
        self.assertTrue(
            self.authorization_service._check_user_access_to_agent(
                self.user1,
                self.agent1,
                AuthorizationOperation.EDIT,
            )
        )

    def test_check_user_access_without_role(self):
        self.assertFalse(
            self.authorization_service._check_user_access_to_agent(
                self.user3,
                self.agent1,
                AuthorizationOperation.EDIT,
            )
        )

    def test_check_user_access_chat(self):
        self.assertTrue(
            self.authorization_service._check_user_access_to_agent(
                self.user3,
                self.agent1,
                AuthorizationOperation.CHAT,
            )
        )

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

