"""Integration-style tests for the discovery orchestrator."""

from __future__ import annotations

import pytest

from azure_discovery.adt_types import (
    AzureDiscoveryRequest,
    AzureDiscoveryResponse,
    DiscoveryMergeMetrics,
    ResourceNode,
    ResourceRelationship,
    VisualizationOptions,
    VisualizationResponse,
)
from azure_discovery.orchestrator import run_discovery


@pytest.mark.asyncio
async def test_run_discovery_enriches_response(monkeypatch: pytest.MonkeyPatch) -> None:
    request = AzureDiscoveryRequest(tenant_id="tenant-1")
    base_response = AzureDiscoveryResponse(
        tenant_id="tenant-1",
        discovered_subscriptions=["sub-a"],
        nodes=[
            ResourceNode(
                id="vm-a",
                name="vm-a",
                type="Microsoft.Compute/virtualMachines",
                subscription_id="sub-a",
            )
        ],
        relationships=[],
        total_resources=1,
    )

    monkeypatch.setattr(
        "azure_discovery.orchestrator.build_environment_config", lambda env: object()
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.get_credential", lambda req, cfg: object()
    )

    async def fake_enumerate(
        req: AzureDiscoveryRequest, credential=None
    ) -> AzureDiscoveryResponse:
        assert req is request
        return base_response

    def fake_render_visualization(
        response: AzureDiscoveryResponse,
        options: VisualizationOptions,
    ) -> VisualizationResponse:
        assert response is base_response
        assert options == request.visualization
        return VisualizationResponse(
            html_path="artifacts/graphs/test.html",
            nodes=len(response.nodes),
            relationships=len(response.relationships),
        )

    emitted: dict[str, AzureDiscoveryResponse] = {}

    def fake_emit_console_summary(response: AzureDiscoveryResponse) -> None:
        emitted["response"] = response

    monkeypatch.setattr(
        "azure_discovery.orchestrator.enumerate_azure_resources", fake_enumerate
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.render_visualization", fake_render_visualization
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.emit_console_summary", fake_emit_console_summary
    )

    enriched_response = await run_discovery(request)

    assert enriched_response.html_report_path == "artifacts/graphs/test.html"
    assert enriched_response is not base_response
    assert emitted["response"] is enriched_response


@pytest.mark.asyncio
async def test_run_discovery_includes_metrics_when_enabled(monkeypatch: pytest.MonkeyPatch) -> None:
    request = AzureDiscoveryRequest(tenant_id="tenant-1", include_entra=True, include_metrics=True)

    base_response = AzureDiscoveryResponse(
        tenant_id="tenant-1",
        discovered_subscriptions=["sub-a"],
        nodes=[],
        relationships=[],
        total_resources=0,
    )

    entra_nodes = [
        ResourceNode(
            id="graph://user/u1",
            name="User",
            type="Microsoft.Graph/User",
            subscription_id="Tenant",
            tags={"graph_id": "u1"},
        )
    ]
    entra_relationships = [
        ResourceRelationship(
            source_id="graph://user/u1",
            target_id="graph://user/u1",
            relation_type="self",
            weight=1.0,
        )
    ]

    monkeypatch.setattr(
        "azure_discovery.orchestrator.build_environment_config", lambda env: object()
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.get_credential", lambda req, cfg: object()
    )

    async def fake_enumerate_azure(req: AzureDiscoveryRequest, credential=None) -> AzureDiscoveryResponse:
        return base_response

    async def fake_enumerate_entra(req: AzureDiscoveryRequest, credential=None):
        return entra_nodes, entra_relationships

    def fake_render_visualization(response: AzureDiscoveryResponse, options: VisualizationOptions):
        return VisualizationResponse(html_path="x.html", nodes=0, relationships=0)

    monkeypatch.setattr(
        "azure_discovery.orchestrator.enumerate_azure_resources", fake_enumerate_azure
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.enumerate_entra_resources", fake_enumerate_entra
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.render_visualization", fake_render_visualization
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.emit_console_summary", lambda resp: None
    )

    out = await run_discovery(request)

    assert out.metrics is not None
    assert out.metrics.merge.deduped_relationships == 0
    phase_names = [p.name for p in out.metrics.phases]
    assert "azure.arm" in phase_names
    assert "entra.graph" in phase_names
    assert "report.render_html" in phase_names


@pytest.mark.asyncio
async def test_run_discovery_materializes_missing_endpoints(monkeypatch: pytest.MonkeyPatch) -> None:
    request = AzureDiscoveryRequest(
        tenant_id="tenant-1",
        include_entra=True,
        include_metrics=True,
        materialize_missing_endpoints=True,
    )

    base_response = AzureDiscoveryResponse(
        tenant_id="tenant-1",
        discovered_subscriptions=["sub-a"],
        nodes=[],
        relationships=[],
        total_resources=0,
    )

    # Relationship references endpoints that aren't present as nodes.
    entra_nodes = []
    entra_relationships = [
        ResourceRelationship(
            source_id="graph://user/u1",
            target_id="graph://user/u2",
            relation_type="member",
            weight=1.0,
        )
    ]

    monkeypatch.setattr(
        "azure_discovery.orchestrator.build_environment_config", lambda env: object()
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.get_credential", lambda req, cfg: object()
    )

    async def fake_enumerate_azure(req: AzureDiscoveryRequest, credential=None) -> AzureDiscoveryResponse:
        return base_response

    async def fake_enumerate_entra(req: AzureDiscoveryRequest, credential=None):
        return entra_nodes, entra_relationships

    def fake_render_visualization(response: AzureDiscoveryResponse, options: VisualizationOptions):
        return VisualizationResponse(html_path="x.html", nodes=0, relationships=0)

    monkeypatch.setattr(
        "azure_discovery.orchestrator.enumerate_azure_resources", fake_enumerate_azure
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.enumerate_entra_resources", fake_enumerate_entra
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.render_visualization", fake_render_visualization
    )
    monkeypatch.setattr(
        "azure_discovery.orchestrator.emit_console_summary", lambda resp: None
    )

    out = await run_discovery(request)

    assert out.metrics is not None
    assert out.metrics.merge.dropped_dangling_relationships == 0
    assert len(out.relationships) == 1
    assert len(out.nodes) == 2
