"""Tests for Azure Resource Graph enumerator logic."""

from __future__ import annotations

from typing import Any

import pytest

from azure_discovery.adt_types import (
    AzureDiscoveryRequest,
    AzureDiscoveryResponse,
    AzureEnvironment,
    AzureEnvironmentConfig,
    DiscoveryFilter,
)
from azure_discovery.enumerators.azure_resources import (
    _build_query,
    _to_node,
    enumerate_azure_resources,
)


def test_build_query_applies_filters() -> None:
    discovery_request = AzureDiscoveryRequest(
        tenant_id="00000000-0000-0000-0000-000000000000",
        filter=DiscoveryFilter(
            include_types=["Microsoft.Compute/virtualMachines", "Microsoft.Sql/servers"],
            exclude_types=["Microsoft.Storage/storageAccounts"],
            resource_groups=["Prod-Core"],
            required_tags={"environment": "prod"},
        ),
    )

    query = _build_query(discovery_request)

    assert query.startswith("resources")
    assert "tolower(type) == 'microsoft.compute/virtualmachines'" in query
    assert "tolower(type) != 'microsoft.storage/storageaccounts'" in query
    assert "tolower(resourceGroup) == 'prod-core'" in query
    assert "tags['environment'] =~ 'prod'" in query
    assert query.endswith(
        "| project id, name, type, location, resourceGroup, subscriptionId, tags, properties"
    )


def test_to_node_extracts_dependencies() -> None:
    payload = {
        "id": "/subscriptions/s1/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/vm1",
        "name": "vm1",
        "type": "Microsoft.Compute/virtualMachines",
        "location": "eastus",
        "subscriptionId": "s1",
        "resourceGroup": "rg",
        "tags": {"env": "prod"},
        "properties": {
            "dependencies": [
                {"resourceId": "/subscriptions/s1/resourceGroups/rg/providers/Microsoft.Network/networkInterfaces/nic1"},
                {"resourceId": "/subscriptions/s1/resourceGroups/rg/providers/Microsoft.Compute/disks/osdisk1"},
            ]
        },
    }

    node = _to_node(payload)

    assert node.id == payload["id"]
    assert node.dependencies == [
        "/subscriptions/s1/resourceGroups/rg/providers/Microsoft.Network/networkInterfaces/nic1",
        "/subscriptions/s1/resourceGroups/rg/providers/Microsoft.Compute/disks/osdisk1",
    ]


@pytest.mark.asyncio
async def test_enumerate_azure_resources_normalizes_results(monkeypatch: pytest.MonkeyPatch) -> None:
    discovery_request = AzureDiscoveryRequest(
        tenant_id="tenant-1234",
        subscriptions=None,
    )
    environment_config = AzureEnvironmentConfig(
        name=AzureEnvironment.AZURE_PUBLIC,
        authority_host="https://login.microsoftonline.com",
        resource_manager="https://management.azure.com",
        graph_endpoint="https://graph.microsoft.com",
        storage_suffix="core.windows.net",
    )

    def fake_build_environment_config(environment: AzureEnvironment) -> AzureEnvironmentConfig:
        assert environment == AzureEnvironment.AZURE_PUBLIC
        return environment_config

    def fake_get_credential(*_: Any, **__: Any) -> str:
        return "credential"

    async def fake_ensure_subscription_ids(
        request: AzureDiscoveryRequest, credential: Any, base_url: str | None = None
    ) -> list[str]:
        assert credential == "credential"
        assert request.tenant_id == "tenant-1234"
        assert base_url == environment_config.resource_manager
        return ["sub-a"]

    async def fake_query_resource_graph(
        credential: Any,
        query: str,
        subscriptions: list[str],
        batch_size: int,
        base_url: str | None = None,
        scale_controls: Any = None,
    ) -> list[dict[str, Any]]:
        assert credential == "credential"
        assert subscriptions == ["sub-a"]
        assert batch_size == discovery_request.max_batch_size
        assert base_url == environment_config.resource_manager
        assert query.startswith("resources")
        return [
            {
                "id": "vm-a",
                "name": "vm-a",
                "type": "Microsoft.Compute/virtualMachines",
                "subscriptionId": "sub-a",
                "properties": {"dependencies": [{"resourceId": "nic-b"}]},
            },
            {
                "id": "nic-b",
                "name": "nic-b",
                "type": "Microsoft.Network/networkInterfaces",
                "subscriptionId": "sub-a",
            },
        ]

    monkeypatch.setattr(
        "azure_discovery.enumerators.azure_resources.build_environment_config",
        fake_build_environment_config,
    )
    monkeypatch.setattr(
        "azure_discovery.enumerators.azure_resources.get_credential",
        fake_get_credential,
    )
    monkeypatch.setattr(
        "azure_discovery.enumerators.azure_resources.ensure_subscription_ids",
        fake_ensure_subscription_ids,
    )
    monkeypatch.setattr(
        "azure_discovery.enumerators.azure_resources.query_resource_graph",
        fake_query_resource_graph,
    )

    response = await enumerate_azure_resources(discovery_request)

    assert isinstance(response, AzureDiscoveryResponse)
    assert response.discovered_subscriptions == ["sub-a"]
    assert response.total_resources == 2
    assert len(response.relationships) == 1
    assert response.relationships[0].source_id == "vm-a"
    assert response.relationships[0].target_id == "nic-b"
