import asyncio
import unittest
from unittest.mock import Mock, patch
from fastapi import Request
from analogai.foundation.extensions.authentication.authentication_factory import AuthenticationFactory
from analogai.foundation.modules.user.user import User
from analogai.foundation.extensions.authentication.models import TokenPayload

class TestAuthenticationWorkflow(unittest.TestCase):
    def setUp(self):
        self.user_service = Mock()
        self.user = User(id="user-123", name="Test User", email="test@example.com")

    @patch("analogai.foundation.extensions.authentication.authentication_factory.create_repository_strategy")
    @patch("analogai.foundation.extensions.authentication.authentication_factory.Auth0JWTService")
    def test_authentication_dependency_returns_user(self, auth0_cls, repository_selector):
        repository_selector.return_value.get_user_repository.return_value = self.user_service
        jwt_service = auth0_cls.return_value
        jwt_service.authenticate_user.return_value = self.user

        factory = AuthenticationFactory()
        dependency = factory.create_authentication_dependency()

        request = Mock(spec=Request)
        request.headers = {"Authorization": "Bearer auth-token"}

        result_user = asyncio.run(dependency(request))

        jwt_service.authenticate_user.assert_called_once_with("auth-token")
        self.assertIs(result_user, self.user)

    @patch("analogai.foundation.extensions.authentication.authentication_factory.create_repository_strategy")
    @patch("analogai.foundation.extensions.authentication.authentication_factory.Auth0JWTService")
    def test_token_extraction_dependency_returns_payload(self, auth0_cls, repository_selector):
        repository_selector.return_value.get_user_repository.return_value = self.user_service
        expected_payload = TokenPayload(
            token="raw-token",
            email="payload@example.com",
            user_id="payload-user",
            name="Payload User",
            provider="auth0",
        )
        jwt_service = auth0_cls.return_value
        jwt_service.extract_payload.return_value = expected_payload

        factory = AuthenticationFactory()
        dependency = factory.create_token_extraction_dependency()

        request = Mock(spec=Request)
        request.headers = {"Authorization": "Bearer raw-token"}

        payload = asyncio.run(dependency(request))

        jwt_service.extract_payload.assert_called_once_with("raw-token")
        self.assertEqual(payload, expected_payload)

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

