"""Tests for Azure client helpers."""

import os
from unittest.mock import MagicMock, patch

import pytest

from azure_discovery.adt_types import AzureDiscoveryRequest, AzureEnvironment
from azure_discovery.adt_types.errors import AzureClientError
from azure_discovery.utils.azure_clients import (
    _is_headless,
    build_environment_config,
    get_credential,
)


class TestBuildEnvironmentConfig:
    """Tests for build_environment_config."""

    def test_azure_public(self) -> None:
        config = build_environment_config(AzureEnvironment.AZURE_PUBLIC)
        assert config.name == AzureEnvironment.AZURE_PUBLIC
        assert "management.azure.com" in config.resource_manager
        assert "graph.microsoft.com" in config.graph_endpoint

    def test_azure_gov(self) -> None:
        config = build_environment_config(AzureEnvironment.AZURE_GOV)
        assert config.name == AzureEnvironment.AZURE_GOV
        assert "usgovcloudapi" in config.resource_manager or "gov" in config.graph_endpoint.lower()

    def test_azure_china(self) -> None:
        config = build_environment_config(AzureEnvironment.AZURE_CHINA)
        assert config.name == AzureEnvironment.AZURE_CHINA
        assert "chinacloudapi" in config.resource_manager or "china" in config.graph_endpoint.lower()

    def test_azure_germany(self) -> None:
        config = build_environment_config(AzureEnvironment.AZURE_GERMANY)
        assert config.name == AzureEnvironment.AZURE_GERMANY

    def test_azure_stack(self) -> None:
        config = build_environment_config(AzureEnvironment.AZURE_STACK)
        assert config.name == AzureEnvironment.AZURE_STACK
        assert "azurestack" in config.resource_manager.lower()

    def test_unsupported_environment_raises(self) -> None:
        with pytest.raises(AzureClientError, match="Unsupported environment"):
            build_environment_config("unsupported")  # type: ignore[arg-type]


class TestGetCredential:
    """Tests for get_credential."""

    def test_returns_chained_credential(self) -> None:
        request = AzureDiscoveryRequest(tenant_id="t1")
        config = build_environment_config(AzureEnvironment.AZURE_PUBLIC)
        cred = get_credential(request, config)
        assert cred is not None
        assert "ChainedTokenCredential" in type(cred).__name__

    @patch("azure_discovery.utils.azure_clients.AzureCliCredential")
    def test_prefer_cli_credentials_adds_cli_to_chain(
        self, mock_cli_cred: MagicMock
    ) -> None:
        """With prefer_cli_credentials=True, AzureCliCredential is included in the chain."""
        mock_cli_cred.return_value = MagicMock()
        request = AzureDiscoveryRequest(tenant_id="t1", prefer_cli_credentials=True)
        config = build_environment_config(AzureEnvironment.AZURE_PUBLIC)
        cred = get_credential(request, config)
        assert cred is not None
        mock_cli_cred.assert_called_once()


class TestIsHeadless:
    """Tests for _is_headless."""

    def test_wsl_returns_true(self) -> None:
        with patch.dict("os.environ", {"WSL_DISTRO_NAME": "Ubuntu"}, clear=False):
            assert _is_headless() is True

    def test_posix_no_display_returns_true(self) -> None:
        with patch.dict("os.environ", {}, clear=True), patch("os.name", "posix"):
            # No DISPLAY
            assert _is_headless() is True

    def test_posix_with_display_returns_false(self) -> None:
        # Simulate non-WSL Linux with DISPLAY (patch so WSL is not set, DISPLAY is).
        real_get = os.environ.get

        def mock_get(k: str, d: str | None = None) -> str | None:
            if k == "WSL_DISTRO_NAME":
                return None
            if k == "DISPLAY":
                return ":0"
            return real_get(k, d)

        with patch("azure_discovery.utils.azure_clients.os.environ.get", side_effect=mock_get), patch(
            "azure_discovery.utils.azure_clients.os.name", "posix"
        ):
            assert _is_headless() is False

    def test_wsl_with_display_still_headless(self) -> None:
        with patch.dict(
            "os.environ", {"WSL_DISTRO_NAME": "Ubuntu", "DISPLAY": ":0"}, clear=False
        ):
            assert _is_headless() is True
