"""Unit tests for TenantService."""

from datetime import datetime, timezone
from pathlib import Path
from unittest.mock import MagicMock, patch
from uuid import UUID

import httpx
import pytest

from teams_phone.exceptions import (
    AuthenticationError,
    ConfigurationError,
    NotFoundError,
)
from teams_phone.infrastructure import CacheManager, ConfigManager
from teams_phone.models import (
    AuthMethod,
    CachedToken,
    ConnectionTestResult,
    TenantProfile,
)
from teams_phone.services import AuthService, TenantService


def create_test_profile(name: str = "test-tenant") -> TenantProfile:
    """Create a TenantProfile for testing."""
    return TenantProfile(
        name=name,
        tenant_id=UUID("12345678-1234-1234-1234-123456789012"),
        client_id=UUID("87654321-4321-4321-4321-210987654321"),
        display_name=f"Test Tenant {name}",
        auth_method=AuthMethod.CERTIFICATE,
        cert_path="~/.certs/test.pem",
    )


class TestTenantServiceInit:
    """Tests for TenantService initialization."""

    @pytest.mark.unit
    def test_accepts_dependencies(self, tmp_path: Path) -> None:
        """TenantService accepts ConfigManager and AuthService."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)

        service = TenantService(config_manager, auth_service)

        assert service.config_manager is config_manager
        assert service.auth_service is auth_service

    @pytest.mark.unit
    def test_stores_managers(self, tmp_path: Path) -> None:
        """TenantService stores config and auth as instance attributes."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)

        service = TenantService(config_manager, auth_service)

        assert hasattr(service, "config_manager")
        assert hasattr(service, "auth_service")


class TestListTenants:
    """Tests for list_tenants method."""

    @pytest.mark.unit
    def test_returns_empty_list_when_no_tenants(self, tmp_path: Path) -> None:
        """list_tenants returns empty list when no tenants configured."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        result = service.list_tenants()

        assert result == []

    @pytest.mark.unit
    def test_returns_all_tenants(self, tmp_path: Path) -> None:
        """list_tenants returns all configured tenants."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        profile1 = create_test_profile("tenant-a")
        profile2 = create_test_profile("tenant-b")
        config_manager.set_tenant("tenant-a", profile1)
        config_manager.set_tenant("tenant-b", profile2)

        result = service.list_tenants()

        assert len(result) == 2
        names = [t.name for t in result]
        assert "tenant-a" in names
        assert "tenant-b" in names

    @pytest.mark.unit
    def test_returns_tenants_sorted_by_name(self, tmp_path: Path) -> None:
        """list_tenants returns tenants sorted alphabetically by name."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        # Add tenants in non-alphabetical order
        profile_c = create_test_profile("charlie")
        profile_a = create_test_profile("alpha")
        profile_b = create_test_profile("bravo")
        config_manager.set_tenant("charlie", profile_c)
        config_manager.set_tenant("alpha", profile_a)
        config_manager.set_tenant("bravo", profile_b)

        result = service.list_tenants()

        assert [t.name for t in result] == ["alpha", "bravo", "charlie"]


class TestGetCurrentTenant:
    """Tests for get_current_tenant method."""

    @pytest.mark.unit
    def test_returns_default_tenant(self, tmp_path: Path) -> None:
        """get_current_tenant returns the default tenant profile."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("my-tenant")
        config_manager.set_tenant("my-tenant", profile)
        config_manager.set_default_tenant("my-tenant")

        result = service.get_current_tenant()

        assert result.name == "my-tenant"
        assert result.tenant_id == profile.tenant_id

    @pytest.mark.unit
    def test_raises_configuration_error_when_no_default(self, tmp_path: Path) -> None:
        """get_current_tenant raises ConfigurationError when no default set."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        with pytest.raises(ConfigurationError) as exc_info:
            service.get_current_tenant()

        assert "No default tenant configured" in str(exc_info.value)
        assert exc_info.value.remediation is not None
        assert "teams-phone tenants switch" in exc_info.value.remediation

    @pytest.mark.unit
    def test_raises_configuration_error_when_tenants_exist_but_no_default(
        self, tmp_path: Path
    ) -> None:
        """get_current_tenant raises error even if tenants exist but no default."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        # Add tenant but don't set as default
        profile = create_test_profile("my-tenant")
        config_manager.set_tenant("my-tenant", profile)

        with pytest.raises(ConfigurationError) as exc_info:
            service.get_current_tenant()

        assert "No default tenant configured" in str(exc_info.value)


class TestAddTenant:
    """Tests for add_tenant method."""

    @pytest.mark.unit
    def test_adds_tenant_profile(self, tmp_path: Path) -> None:
        """add_tenant saves the tenant profile via ConfigManager."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("new-tenant")

        result = service.add_tenant(profile)

        assert result is profile
        stored = config_manager.get_tenant("new-tenant")
        assert stored.name == "new-tenant"
        assert stored.tenant_id == profile.tenant_id

    @pytest.mark.unit
    def test_auto_sets_first_tenant_as_default(self, tmp_path: Path) -> None:
        """add_tenant auto-sets the first tenant as default."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("first-tenant")

        service.add_tenant(profile)

        default = config_manager.get_default_tenant()
        assert default == "first-tenant"

    @pytest.mark.unit
    def test_does_not_change_default_for_subsequent_tenants(
        self, tmp_path: Path
    ) -> None:
        """add_tenant does not change default when adding second tenant."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        profile1 = create_test_profile("first")
        profile2 = create_test_profile("second")

        service.add_tenant(profile1)
        service.add_tenant(profile2)

        default = config_manager.get_default_tenant()
        assert default == "first"

    @pytest.mark.unit
    def test_returns_added_profile(self, tmp_path: Path) -> None:
        """add_tenant returns the added TenantProfile."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("test")

        result = service.add_tenant(profile)

        assert result.name == "test"
        assert result.tenant_id == profile.tenant_id
        assert result.client_id == profile.client_id


class TestRemoveTenant:
    """Tests for remove_tenant method."""

    @pytest.mark.unit
    def test_removes_existing_tenant(self, tmp_path: Path) -> None:
        """remove_tenant removes an existing tenant profile."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("to-remove")
        config_manager.set_tenant("to-remove", profile)

        service.remove_tenant("to-remove")

        with pytest.raises(NotFoundError):
            config_manager.get_tenant("to-remove")

    @pytest.mark.unit
    def test_raises_not_found_for_missing_tenant(self, tmp_path: Path) -> None:
        """remove_tenant raises NotFoundError for non-existent tenant."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        with pytest.raises(NotFoundError) as exc_info:
            service.remove_tenant("nonexistent")

        assert "nonexistent" in str(exc_info.value)
        assert exc_info.value.remediation is not None

    @pytest.mark.unit
    def test_clears_default_when_removing_default_tenant(self, tmp_path: Path) -> None:
        """remove_tenant clears default_tenant when removing the default."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        cache_manager = CacheManager(token_dir=str(tmp_path / "tokens"))
        auth_service = AuthService(config_manager, cache_manager)
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("default-tenant")
        config_manager.set_tenant("default-tenant", profile)
        config_manager.set_default_tenant("default-tenant")

        service.remove_tenant("default-tenant")

        default = config_manager.get_default_tenant()
        assert default is None

    @pytest.mark.unit
    def test_checks_auth_status_before_removal(self, tmp_path: Path) -> None:
        """remove_tenant checks if tenant is authenticated before removal."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.is_authenticated.return_value = True
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("auth-tenant")
        config_manager.set_tenant("auth-tenant", profile)

        service.remove_tenant("auth-tenant")

        auth_service.is_authenticated.assert_called_once_with("auth-tenant")

    @pytest.mark.unit
    def test_removes_even_if_authenticated(self, tmp_path: Path) -> None:
        """remove_tenant proceeds with removal even if tenant is authenticated."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.is_authenticated.return_value = True
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("auth-tenant")
        config_manager.set_tenant("auth-tenant", profile)

        service.remove_tenant("auth-tenant")

        with pytest.raises(NotFoundError):
            config_manager.get_tenant("auth-tenant")


class TestSwitchTenant:
    """Tests for switch_tenant method."""

    @pytest.mark.unit
    def test_switch_to_valid_tenant_updates_default(self, tmp_path: Path) -> None:
        """switch_tenant updates the default tenant to the specified tenant."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.is_authenticated.return_value = True
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("target-tenant")
        config_manager.set_tenant("target-tenant", profile)

        result = service.switch_tenant("target-tenant")

        assert result.name == "target-tenant"
        assert config_manager.get_default_tenant() == "target-tenant"

    @pytest.mark.unit
    def test_switch_to_nonexistent_tenant_raises_not_found(
        self, tmp_path: Path
    ) -> None:
        """switch_tenant raises NotFoundError for non-existent tenant."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        service = TenantService(config_manager, auth_service)

        with pytest.raises(NotFoundError) as exc_info:
            service.switch_tenant("nonexistent")

        assert "nonexistent" in str(exc_info.value)
        assert exc_info.value.remediation is not None

    @pytest.mark.unit
    def test_auto_login_triggers_when_not_authenticated(self, tmp_path: Path) -> None:
        """switch_tenant triggers login when not authenticated and auto_login=True."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.is_authenticated.return_value = False
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("needs-auth")
        config_manager.set_tenant("needs-auth", profile)

        service.switch_tenant("needs-auth")

        auth_service.login.assert_called_once_with("needs-auth")

    @pytest.mark.unit
    def test_auto_login_failure_propagates_exception(self, tmp_path: Path) -> None:
        """switch_tenant propagates AuthenticationError without changing default."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.is_authenticated.return_value = False
        auth_service.login.side_effect = AuthenticationError(
            "Login failed", remediation="Check credentials"
        )
        service = TenantService(config_manager, auth_service)

        # Set up existing default
        existing = create_test_profile("existing")
        config_manager.set_tenant("existing", existing)
        config_manager.set_default_tenant("existing")

        # Set up target tenant
        target = create_test_profile("target")
        config_manager.set_tenant("target", target)

        with pytest.raises(AuthenticationError) as exc_info:
            service.switch_tenant("target")

        assert "Login failed" in str(exc_info.value)
        # Default should NOT have changed
        assert config_manager.get_default_tenant() == "existing"

    @pytest.mark.unit
    def test_skips_login_when_already_authenticated(self, tmp_path: Path) -> None:
        """switch_tenant skips login when already authenticated."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.is_authenticated.return_value = True
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("already-authed")
        config_manager.set_tenant("already-authed", profile)

        service.switch_tenant("already-authed")

        auth_service.is_authenticated.assert_called_once_with("already-authed")
        auth_service.login.assert_not_called()

    @pytest.mark.unit
    def test_auto_login_false_skips_login(self, tmp_path: Path) -> None:
        """switch_tenant with auto_login=False skips login even when not authed."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.is_authenticated.return_value = False
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("no-auto-login")
        config_manager.set_tenant("no-auto-login", profile)

        result = service.switch_tenant("no-auto-login", auto_login=False)

        auth_service.login.assert_not_called()
        assert result.name == "no-auto-login"
        assert config_manager.get_default_tenant() == "no-auto-login"

    @pytest.mark.unit
    def test_returns_tenant_profile(self, tmp_path: Path) -> None:
        """switch_tenant returns the TenantProfile for the switched tenant."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.is_authenticated.return_value = True
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("return-test")
        config_manager.set_tenant("return-test", profile)

        result = service.switch_tenant("return-test")

        assert result.name == "return-test"
        assert result.tenant_id == profile.tenant_id
        assert result.client_id == profile.client_id

    @pytest.mark.unit
    def test_switch_to_current_tenant_is_idempotent(self, tmp_path: Path) -> None:
        """switch_tenant to already-current tenant still validates and updates."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.is_authenticated.return_value = True
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("current")
        config_manager.set_tenant("current", profile)
        config_manager.set_default_tenant("current")

        result = service.switch_tenant("current")

        assert result.name == "current"
        assert config_manager.get_default_tenant() == "current"
        auth_service.is_authenticated.assert_called_once_with("current")


def create_mock_token(scopes: list[str] | None = None) -> CachedToken:
    """Create a mock CachedToken for testing."""
    return CachedToken(
        access_token="mock-access-token",
        expires_at=datetime.now(timezone.utc),
        tenant_id="12345678-1234-1234-1234-123456789012",
        scopes=scopes or ["https://graph.microsoft.com/.default"],
    )


class TestTestConnection:
    """Tests for test_connection method."""

    @pytest.mark.unit
    def test_successful_connection_returns_success_true(self, tmp_path: Path) -> None:
        """test_connection returns success=True with latency on success."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.login.return_value = create_mock_token()
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("test-tenant")
        config_manager.set_tenant("test-tenant", profile)

        mock_response = MagicMock()
        mock_response.raise_for_status = MagicMock()

        with patch("httpx.Client") as mock_client_class:
            mock_client = MagicMock()
            mock_client.__enter__ = MagicMock(return_value=mock_client)
            mock_client.__exit__ = MagicMock(return_value=False)
            mock_client.get.return_value = mock_response
            mock_client_class.return_value = mock_client

            result = service.test_connection("test-tenant")

        assert isinstance(result, ConnectionTestResult)
        assert result.success is True
        assert result.tenant_name == "test-tenant"
        assert result.latency_ms is not None
        assert result.latency_ms >= 0
        assert result.error_message is None

    @pytest.mark.unit
    def test_successful_connection_includes_permissions(self, tmp_path: Path) -> None:
        """test_connection returns scopes as permissions on success."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        expected_scopes = ["https://graph.microsoft.com/.default", "User.Read.All"]
        auth_service.login.return_value = create_mock_token(scopes=expected_scopes)
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("test-tenant")
        config_manager.set_tenant("test-tenant", profile)

        mock_response = MagicMock()
        mock_response.raise_for_status = MagicMock()

        with patch("httpx.Client") as mock_client_class:
            mock_client = MagicMock()
            mock_client.__enter__ = MagicMock(return_value=mock_client)
            mock_client.__exit__ = MagicMock(return_value=False)
            mock_client.get.return_value = mock_response
            mock_client_class.return_value = mock_client

            result = service.test_connection("test-tenant")

        assert result.permissions == expected_scopes

    @pytest.mark.unit
    def test_auth_failure_returns_success_false(self, tmp_path: Path) -> None:
        """test_connection returns success=False with error message on auth failure."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.login.side_effect = AuthenticationError(
            "Invalid client secret", remediation="Check client secret"
        )
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("bad-auth-tenant")
        config_manager.set_tenant("bad-auth-tenant", profile)

        result = service.test_connection("bad-auth-tenant")

        assert result.success is False
        assert result.tenant_name == "bad-auth-tenant"
        assert result.error_message is not None
        assert "Invalid client secret" in result.error_message

    @pytest.mark.unit
    def test_tenant_not_found_returns_success_false(self, tmp_path: Path) -> None:
        """test_connection returns success=False for non-existent tenant."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        service = TenantService(config_manager, auth_service)

        result = service.test_connection("nonexistent")

        assert result.success is False
        assert result.tenant_name == "nonexistent"
        assert result.error_message is not None
        assert "nonexistent" in result.error_message

    @pytest.mark.unit
    def test_network_error_returns_success_false(self, tmp_path: Path) -> None:
        """test_connection returns success=False with error on network failure."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.login.return_value = create_mock_token()
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("network-fail-tenant")
        config_manager.set_tenant("network-fail-tenant", profile)

        with patch("httpx.Client") as mock_client_class:
            mock_client = MagicMock()
            mock_client.__enter__ = MagicMock(return_value=mock_client)
            mock_client.__exit__ = MagicMock(return_value=False)
            mock_client.get.side_effect = httpx.ConnectError("Connection refused")
            mock_client_class.return_value = mock_client

            result = service.test_connection("network-fail-tenant")

        assert result.success is False
        assert result.tenant_name == "network-fail-tenant"
        assert result.error_message is not None
        assert "Connection refused" in result.error_message

    @pytest.mark.unit
    def test_http_error_returns_success_false(self, tmp_path: Path) -> None:
        """test_connection returns success=False on HTTP error response."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.login.return_value = create_mock_token()
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("http-error-tenant")
        config_manager.set_tenant("http-error-tenant", profile)

        mock_response = MagicMock()
        mock_request = MagicMock()
        mock_response.raise_for_status.side_effect = httpx.HTTPStatusError(
            "Forbidden", request=mock_request, response=mock_response
        )

        with patch("httpx.Client") as mock_client_class:
            mock_client = MagicMock()
            mock_client.__enter__ = MagicMock(return_value=mock_client)
            mock_client.__exit__ = MagicMock(return_value=False)
            mock_client.get.return_value = mock_response
            mock_client_class.return_value = mock_client

            result = service.test_connection("http-error-tenant")

        assert result.success is False
        assert result.tenant_name == "http-error-tenant"
        assert result.error_message is not None

    @pytest.mark.unit
    def test_latency_is_positive_on_success(self, tmp_path: Path) -> None:
        """test_connection returns positive latency on successful connection."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.login.return_value = create_mock_token()
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("latency-test")
        config_manager.set_tenant("latency-test", profile)

        mock_response = MagicMock()
        mock_response.raise_for_status = MagicMock()

        with patch("httpx.Client") as mock_client_class:
            mock_client = MagicMock()
            mock_client.__enter__ = MagicMock(return_value=mock_client)
            mock_client.__exit__ = MagicMock(return_value=False)
            mock_client.get.return_value = mock_response
            mock_client_class.return_value = mock_client

            result = service.test_connection("latency-test")

        # Latency should be non-negative (0 is acceptable for very fast operations)
        assert result.latency_ms is not None
        assert result.latency_ms >= 0

    @pytest.mark.unit
    def test_never_raises_exception(self, tmp_path: Path) -> None:
        """test_connection never raises - all errors returned in result."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        # Simulate an unexpected exception
        auth_service.login.side_effect = RuntimeError("Unexpected error")
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("error-tenant")
        config_manager.set_tenant("error-tenant", profile)

        # Should not raise
        result = service.test_connection("error-tenant")

        assert result.success is False
        assert result.error_message is not None
        assert "Unexpected error" in result.error_message

    @pytest.mark.unit
    def test_calls_login_with_force_true(self, tmp_path: Path) -> None:
        """test_connection calls login with force=True for fresh token."""
        config_manager = ConfigManager(config_path=str(tmp_path / "config.toml"))
        auth_service = MagicMock(spec=AuthService)
        auth_service.login.return_value = create_mock_token()
        service = TenantService(config_manager, auth_service)

        profile = create_test_profile("force-login-tenant")
        config_manager.set_tenant("force-login-tenant", profile)

        mock_response = MagicMock()
        mock_response.raise_for_status = MagicMock()

        with patch("httpx.Client") as mock_client_class:
            mock_client = MagicMock()
            mock_client.__enter__ = MagicMock(return_value=mock_client)
            mock_client.__exit__ = MagicMock(return_value=False)
            mock_client.get.return_value = mock_response
            mock_client_class.return_value = mock_client

            service.test_connection("force-login-tenant")

        auth_service.login.assert_called_once_with("force-login-tenant", force=True)
