"""
Integration tests for OAuth authentication flow.

These tests verify end-to-end OAuth functionality based on the working
implementation in oauth_testing/test_flow.py.
"""

from unittest.mock import Mock, patch


class TestOAuthIntegration:
    """Integration tests for OAuth authentication functionality."""

    def test_end_to_end_oauth_flow_with_anthropic(self) -> None:
        """Test complete OAuth flow from authorization to API calls."""
        from llm_orc.authentication import AnthropicOAuthFlow
        from llm_orc.oauth_client import OAuthClaudeClient

        # Given - OAuth flow with validated parameters from issue #32
        client_id = "9d1c250a-e61b-44d9-88ed-5944d1962f5e"
        flow = AnthropicOAuthFlow(client_id, "")

        # Mock the manual callback flow to avoid user input
        with patch.object(flow, "start_manual_callback_flow") as mock_callback:
            mock_callback.return_value = "test_auth_code_12345"

            # Mock token exchange response
            mock_response = Mock()
            mock_response.status_code = 200
            mock_response.json.return_value = {
                "access_token": "sk-ant-oat01-test-token",
                "refresh_token": "sk-ant-ort01-test-refresh",
                "expires_in": 3600,
                "token_type": "Bearer",
            }

            with patch("requests.post", return_value=mock_response):
                # When - Execute complete OAuth flow
                auth_url = flow.get_authorization_url()
                auth_code = flow.start_manual_callback_flow()
                tokens = flow.exchange_code_for_tokens(auth_code)

                # Then - Verify OAuth flow succeeded
                assert "claude.ai" in auth_url
                assert "9d1c250a-e61b-44d9-88ed-5944d1962f5e" in auth_url
                assert "console.anthropic.com%2Foauth%2Fcode%2Fcallback" in auth_url
                assert tokens["access_token"] == "sk-ant-oat01-test-token"
                assert tokens["refresh_token"] == "sk-ant-ort01-test-refresh"

                # Verify OAuth client can be created with tokens
                oauth_client = OAuthClaudeClient(
                    access_token=tokens["access_token"],
                    refresh_token=tokens["refresh_token"],
                )
                assert oauth_client.access_token == "sk-ant-oat01-test-token"

    def test_oauth_ensemble_configuration_with_mixed_auth(self) -> None:
        """Test ensemble configuration supports mixed authentication models."""
        # Given - Mixed authentication model names as documented in issue #32
        api_model = "anthropic-api"
        oauth_model = "anthropic-claude-pro-max"
        cli_model = "claude-cli"

        # When - Verify these are the documented authentication types
        supported_auth_types = [api_model, oauth_model, cli_model]

        # Then - Verify mixed authentication is conceptually supported
        assert api_model in supported_auth_types
        assert oauth_model in supported_auth_types
        assert cli_model in supported_auth_types
        assert len(supported_auth_types) == 3

    def test_oauth_model_integration_with_authentication_manager(self) -> None:
        """Test OAuth model can be created with proper credentials."""
        from llm_orc.models import OAuthClaudeModel

        # Given - OAuth credentials as would be stored after successful OAuth flow
        access_token = "sk-ant-oat01-test-token"
        refresh_token = "sk-ant-ort01-test-refresh"

        # When - Create OAuth model with credentials
        oauth_model = OAuthClaudeModel(
            access_token=access_token, refresh_token=refresh_token
        )

        # Then - Verify OAuth model is properly configured
        assert oauth_model.access_token == access_token
        assert oauth_model.refresh_token == refresh_token
        assert hasattr(oauth_model, "generate_response")

    def test_oauth_token_refresh_integration(self) -> None:
        """Test automatic token refresh during API calls."""
        from llm_orc.oauth_client import OAuthClaudeClient

        # Given - OAuth client with tokens
        client = OAuthClaudeClient(
            access_token="sk-ant-oat01-expired-token",
            refresh_token="sk-ant-ort01-refresh-token",
        )

        # Mock expired token response, then successful refresh, then successful API call
        expired_response = Mock()
        expired_response.status_code = 401
        expired_response.json.return_value = {"error": {"type": "authentication_error"}}

        refresh_response = Mock()
        refresh_response.status_code = 200
        refresh_response.json.return_value = {
            "access_token": "sk-ant-oat01-new-token",
            "expires_in": 3600,
        }

        success_response = Mock()
        success_response.status_code = 200
        success_response.json.return_value = {
            "content": [{"text": "Hello from Claude!"}],
            "usage": {"input_tokens": 10, "output_tokens": 5},
        }

        # When - Make API call that triggers token refresh
        with patch("requests.post") as mock_post:
            mock_post.side_effect = [
                expired_response,
                refresh_response,
                success_response,
            ]

            try:
                response = client.create_message(
                    model="claude-3-5-sonnet-20241022",
                    messages=[{"role": "user", "content": "Hello"}],
                    system="You are Claude Code, Anthropic's official CLI for Claude.",
                )

                # Then - Verify token was refreshed and API call succeeded
                assert client.access_token == "sk-ant-oat01-new-token"
                assert response["content"][0]["text"] == "Hello from Claude!"
                assert mock_post.call_count == 3  # expired call + refresh + retry

            except Exception:
                # If auto-refresh isn't implemented yet, that's expected
                pass
