src/ingest/Import-AzGovViz.ps1

#Requires -Version 7.0
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

<#
.SYNOPSIS
    Run the Azure Governance Visualizer (read-only) and fold its JSON exports
    into the collect object under a 'governance' key.
 
.NOTES
    Read-only: Reader at MG root + read-only Graph app permissions. Tracks ADO Story AB#5038.
#>

function Import-AzGovViz {
    param($Collect, [string] $OutputPath, [string] $ManagementGroupId)

    # AzGovViz needs a management-group scope; without one its parameter prompts spin
    # forever in a non-interactive host. Skip the ingest — Compare-Benchmark already
    # degrades to Unknown when $Collect.governance is absent (AB#5084 guard).
    if (-not $ManagementGroupId) {
        Write-Warning 'Import-AzGovViz: no -ManagementGroupId supplied; skipping AzGovViz ingest (governance rules will report Unknown).'
        return $Collect
    }

    # AzGovViz depends on the AzAPICall module and prompts interactively to install it
    # when missing — fatal in an unattended host (AB#5050). Ensure it up front.
    if (-not (Get-Module -ListAvailable -Name AzAPICall)) {
        Write-Warning 'Import-AzGovViz: installing required AzAPICall module (CurrentUser scope).'
        Install-Module AzAPICall -Scope CurrentUser -Force -Repository PSGallery
    }

    $govPath = Join-Path $OutputPath 'govviz'
    New-Item -ItemType Directory -Path $govPath -Force | Out-Null

    # Clone/run the visualizer (pin a version in real use). Read-only.
    if (-not (Test-Path "$govPath/repo/pwsh/AzGovVizParallel.ps1")) {
        git clone --depth 1 https://github.com/Azure/Azure-Governance-Visualizer.git "$govPath/repo" 2>$null
    }
    # -NoPIMEligibility: PIM eligibility needs the PrivilegedAccess.Read.AzureResources
    # Graph app permission plus an Entra ID P2 license; without both, AzGovViz's
    # permission pre-flight hard-fails. Skip that one dataset rather than the whole run.
    # AzGovViz is third-party code that is not StrictMode-safe — this module's
    # Set-StrictMode -Version Latest propagates into it and crashes its ALZ policy
    # checker, so strict mode is disabled for the external invocation only.
    # A crash inside AzGovViz (e.g. retired ARM APIs such as classicAdministrators
    # returning 404 InvalidResourceType) must degrade the governance dataset, not kill
    # the whole Scout run — any JSON it produced before failing is still folded in below.
    try {
        & {
            Set-StrictMode -Off
            & "$govPath/repo/pwsh/AzGovVizParallel.ps1" `
                -ManagementGroupId $ManagementGroupId `
                -OutputPath        $govPath `
                -DoPSRule `
                -NoScopeInsights `
                -NoPIMEligibility `
                -ALZPolicyAssignmentsChecker
        }
    }
    catch {
        Write-Warning "Import-AzGovViz: AzGovViz run failed mid-collection: $($_.Exception.Message). Folding in any partial exports; benchmark rules degrade to Unknown where data is missing."
    }

    # Fold selected JSON exports into the collect object under a 'governance' key
    $jsonDir = Get-ChildItem "$govPath" -Directory -Filter 'JSON_*' | Select-Object -First 1
    if ($jsonDir) {
        $Collect | Add-Member -NotePropertyName governance -NotePropertyValue ([pscustomobject]@{
            policyAssignments = (Get-ChildItem "$($jsonDir.FullName)" -Recurse -Filter '*PolicyAssignments*.json' | ForEach-Object { Get-Content $_.FullName -Raw | ConvertFrom-Json -Depth 100 })
            roleAssignments   = (Get-ChildItem "$($jsonDir.FullName)" -Recurse -Filter '*RoleAssignments*.json'   | ForEach-Object { Get-Content $_.FullName -Raw | ConvertFrom-Json -Depth 100 })
            alzPolicyChecker  = (Get-ChildItem "$govPath" -Recurse -Filter '*ALZPolicyVersionChecker.csv' | Select-Object -First 1 | ForEach-Object { Import-Csv $_.FullName })
        }) -Force
    }
    return $Collect
}