"""Tests for Fabric HTTP client."""

from unittest.mock import MagicMock, Mock, patch

import pytest
import requests


@pytest.mark.unit
class TestFabricClient:
    """Test suite for FabricClient class."""

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_client_initialization(self, mock_credential_class, mock_fabric_config):
        """Test basic client initialization."""
        from ms_fabric_mcp_server.client.http_client import FabricClient

        client = FabricClient(mock_fabric_config)

        assert client.config == mock_fabric_config
        mock_credential_class.assert_called_once()

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_client_setup_session(self, mock_credential_class, mock_fabric_config):
        """Test that HTTP session is configured with retry strategy."""
        from ms_fabric_mcp_server.client.http_client import FabricClient

        client = FabricClient(mock_fabric_config)

        assert client._session is not None
        assert isinstance(client._session, requests.Session)

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_get_auth_token(
        self, mock_credential_class, mock_fabric_config, mock_azure_credential
    ):
        """Test authentication token retrieval."""
        from ms_fabric_mcp_server.client.http_client import FabricClient

        mock_credential_class.return_value = mock_azure_credential
        client = FabricClient(mock_fabric_config)

        token = client.get_auth_token()

        assert token == "mock_access_token_12345"
        mock_azure_credential.get_token.assert_called_once()

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_make_api_request_success(
        self,
        mock_credential_class,
        mock_fabric_config,
        mock_azure_credential,
        mock_requests_response,
    ):
        """Test successful API request."""
        from ms_fabric_mcp_server.client.http_client import FabricClient

        mock_credential_class.return_value = mock_azure_credential
        client = FabricClient(mock_fabric_config)

        # Mock session.request
        response = mock_requests_response(200, {"value": []})
        client._session.request = Mock(return_value=response)

        result = client.make_api_request("GET", "workspaces")

        assert result.status_code == 200
        client._session.request.assert_called_once()

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_make_api_request_with_payload(
        self,
        mock_credential_class,
        mock_fabric_config,
        mock_azure_credential,
        mock_requests_response,
    ):
        """Test API request with JSON payload."""
        from ms_fabric_mcp_server.client.http_client import FabricClient

        mock_credential_class.return_value = mock_azure_credential
        client = FabricClient(mock_fabric_config)

        response = mock_requests_response(201, {"id": "new-item"})
        client._session.request = Mock(return_value=response)

        payload = {"displayName": "Test Item"}
        result = client.make_api_request("POST", "items", payload=payload)

        assert result.status_code == 201
        call_args = client._session.request.call_args
        assert call_args.kwargs["json"] == payload

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_handle_api_error_404(
        self,
        mock_credential_class,
        mock_fabric_config,
        mock_azure_credential,
        mock_requests_response,
    ):
        """Test handling 404 errors."""
        from ms_fabric_mcp_server.client.exceptions import FabricAPIError
        from ms_fabric_mcp_server.client.http_client import FabricClient

        mock_credential_class.return_value = mock_azure_credential
        client = FabricClient(mock_fabric_config)

        response = mock_requests_response(404, None)
        response.text = "Not found"
        client._session.request = Mock(return_value=response)

        with pytest.raises(FabricAPIError):
            client.make_api_request("GET", "workspaces/nonexistent")

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_handle_rate_limit_error(
        self, mock_credential_class, mock_fabric_config, mock_azure_credential
    ):
        """Test handling rate limit (429) errors."""
        from ms_fabric_mcp_server.client.exceptions import FabricRateLimitError
        from ms_fabric_mcp_server.client.http_client import FabricClient

        mock_credential_class.return_value = mock_azure_credential
        client = FabricClient(mock_fabric_config)

        # Create 429 response
        response = Mock()
        response.status_code = 429
        response.ok = False
        response.headers = {"Retry-After": "60"}
        client._session.request = Mock(return_value=response)

        with pytest.raises(FabricRateLimitError):
            client.make_api_request("GET", "workspaces")

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_handle_connection_error(
        self, mock_credential_class, mock_fabric_config, mock_azure_credential
    ):
        """Test handling connection errors."""
        from ms_fabric_mcp_server.client.exceptions import \
            FabricConnectionError
        from ms_fabric_mcp_server.client.http_client import FabricClient

        mock_credential_class.return_value = mock_azure_credential
        client = FabricClient(mock_fabric_config)

        # Simulate connection error
        client._session.request = Mock(
            side_effect=requests.exceptions.ConnectionError("Network error")
        )

        with pytest.raises(FabricConnectionError):
            client.make_api_request("GET", "workspaces")

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_handle_timeout_error(
        self, mock_credential_class, mock_fabric_config, mock_azure_credential
    ):
        """Test handling timeout errors."""
        from ms_fabric_mcp_server.client.exceptions import \
            FabricConnectionError
        from ms_fabric_mcp_server.client.http_client import FabricClient

        mock_credential_class.return_value = mock_azure_credential
        client = FabricClient(mock_fabric_config)

        # Simulate timeout
        client._session.request = Mock(
            side_effect=requests.exceptions.Timeout("Request timeout")
        )

        with pytest.raises(FabricConnectionError):
            client.make_api_request("GET", "workspaces")

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_url_construction_relative(
        self,
        mock_credential_class,
        mock_fabric_config,
        mock_azure_credential,
        mock_requests_response,
    ):
        """Test URL construction for relative endpoints."""
        from ms_fabric_mcp_server.client.http_client import FabricClient

        mock_credential_class.return_value = mock_azure_credential
        client = FabricClient(mock_fabric_config)

        response = mock_requests_response(200, {})
        client._session.request = Mock(return_value=response)

        client.make_api_request("GET", "workspaces")

        call_args = client._session.request.call_args
        url = call_args.kwargs["url"]
        assert url.startswith(mock_fabric_config.BASE_URL)
        assert "workspaces" in url

    @patch("ms_fabric_mcp_server.client.http_client.DefaultAzureCredential")
    def test_url_construction_absolute(
        self,
        mock_credential_class,
        mock_fabric_config,
        mock_azure_credential,
        mock_requests_response,
    ):
        """Test URL construction for absolute URLs."""
        from ms_fabric_mcp_server.client.http_client import FabricClient

        mock_credential_class.return_value = mock_azure_credential
        client = FabricClient(mock_fabric_config)

        response = mock_requests_response(200, {})
        client._session.request = Mock(return_value=response)

        absolute_url = "https://custom.api.com/resource"
        client.make_api_request("GET", absolute_url)

        call_args = client._session.request.call_args
        assert call_args.kwargs["url"] == absolute_url


@pytest.mark.unit
class TestFabricClientExports:
    """Test Fabric client exports."""

    def test_client_exported_from_fabric_module(self):
        """Test that FabricClient is exported from fabric module."""
        from ms_fabric_mcp_server import FabricClient

        assert FabricClient is not None
