#requires -Version 7.2
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
param(
    [Parameter(Mandatory)]
    [ValidatePattern('^[0-9a-fA-F-]{36}$')]
    [string]$SubscriptionId,

    [ValidatePattern('^rg-machine-configuration-deep-dive-we$')]
    [string]$ResourceGroupName = 'rg-machine-configuration-deep-dive-we',

    [switch]$Execute
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$root = Split-Path -Parent $PSScriptRoot
$privateRoot = Join-Path $root '.private'
$contextPath = Join-Path $privateRoot 'runtime-context.json'
$manifestPath = Join-Path $privateRoot 'policy-manifest.json'
$policyApi = '2025-11-01'

function Invoke-Az {
    param([string[]]$Arguments, [switch]$AllowFailure)
    $effectiveArguments = @($Arguments) + '--only-show-errors'
    $previousPythonWarnings = $env:PYTHONWARNINGS
    $env:PYTHONWARNINGS = 'ignore'
    try { $output = & az @effectiveArguments 2>&1 }
    finally { $env:PYTHONWARNINGS = $previousPythonWarnings }
    $code = $LASTEXITCODE
    if ($code -ne 0 -and -not $AllowFailure) { throw ($output -join "`n") }
    [pscustomobject]@{ ExitCode = $code; Text = ($output -join "`n").Trim() }
}

$active = (Invoke-Az @('account', 'show', '--query', '{id:id,state:state,name:name}', '-o', 'json')).Text | ConvertFrom-Json
if ($active.id -ne $SubscriptionId -or $active.state -ne 'Enabled') { throw 'The active Azure CLI subscription does not match the exact supplied subscription.' }

$exists = (Invoke-Az @('group', 'exists', '-n', $ResourceGroupName, '-o', 'tsv')).Text.Trim()
$resourceNames = if ($exists -eq 'true') { (Invoke-Az @('resource', 'list', '-g', $ResourceGroupName, '--query', '[].{Name:name,Type:type}', '-o', 'table')).Text } else { 'Resource group already absent.' }
Write-Host "Exact cleanup target: $ResourceGroupName"
Write-Host $resourceNames

if (-not $Execute) {
    Write-Host 'Preview only. Re-run with -Execute to perform the exact-scope cleanup.'
    return
}

if (-not $PSCmdlet.ShouldProcess($ResourceGroupName, 'Delete the exact workshop policy artifacts and resource group')) { return }

$context = if (Test-Path -LiteralPath $contextPath) { Get-Content -Raw -LiteralPath $contextPath | ConvertFrom-Json } else { $null }
$manifest = if (Test-Path -LiteralPath $manifestPath) { Get-Content -Raw -LiteralPath $manifestPath | ConvertFrom-Json } else { $null }
$enforcePrincipalId = (Invoke-Az @('policy', 'assignment', 'show', '--name', 'mc-workshop-enforce', '--scope', "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName", '--query', 'identity.principalId', '-o', 'tsv') -AllowFailure).Text.Trim()
$discoveredInitiativeIds = (Invoke-Az @('policy', 'set-definition', 'list', '--query', "[?contains(displayName, 'Azure Workshopz Machine Configuration')].name", '-o', 'tsv') -AllowFailure).Text -split "`r?`n" | Where-Object { $_ }
$discoveredDefinitionIds = (Invoke-Az @('policy', 'definition', 'list', '--query', "[?contains(displayName, 'Azure Workshopz Windows')].name", '-o', 'tsv') -AllowFailure).Text -split "`r?`n" | Where-Object { $_ }

if ($exists -eq 'true') {
    $remediations = (Invoke-Az @('rest', '--method', 'get', '--url', "https://management.azure.com/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.PolicyInsights/remediations?api-version=2024-10-01", '--query', "value[?starts_with(name, 'mc-remediate-')].id", '-o', 'tsv') -AllowFailure).Text -split "`r?`n" | Where-Object { $_ }
    foreach ($id in $remediations) { Invoke-Az @('rest', '--method', 'delete', '--url', "https://management.azure.com$id`?api-version=2024-10-01") -AllowFailure | Out-Null }
}

foreach ($name in @('mc-workshop-audit', 'mc-workshop-enforce')) {
    $id = "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Authorization/policyAssignments/$name"
    Invoke-Az @('rest', '--method', 'delete', '--url', "https://management.azure.com$id`?api-version=$policyApi") -AllowFailure | Out-Null
}

if ($exists -eq 'true') {
    foreach ($vm in @('vm-mc-ws2022-we', 'vm-mc-ws2025-we')) {
        $vmId = "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName/providers/Microsoft.Compute/virtualMachines/$vm"
        $assignments = (Invoke-Az @('rest', '--method', 'get', '--url', "https://management.azure.com$vmId/providers/Microsoft.GuestConfiguration/guestConfigurationAssignments?api-version=2024-04-05", '--query', "value[?starts_with(name, 'WorkshopWindowsBaseline')].name", '-o', 'tsv') -AllowFailure).Text -split "`r?`n" | Where-Object { $_ }
        foreach ($assignment in $assignments) {
            Invoke-Az @('rest', '--method', 'delete', '--url', "https://management.azure.com$vmId/providers/Microsoft.GuestConfiguration/guestConfigurationAssignments/$assignment`?api-version=2024-04-05") -AllowFailure | Out-Null
        }
    }
}

if ($context) {
    $contextEnforcePrincipalId = if ($context.PSObject.Properties.Name -contains 'EnforceAssignmentPrincipalId') {
        $context.EnforceAssignmentPrincipalId
    }
    else {
        $null
    }
    foreach ($principalId in @($context.ManagedIdentityPrincipalId, $contextEnforcePrincipalId, $enforcePrincipalId) | Where-Object { $_ } | Select-Object -Unique) {
        $roleAssignmentIds = (Invoke-Az @('role', 'assignment', 'list', '--assignee-object-id', $principalId, '--query', '[].id', '-o', 'tsv') -AllowFailure).Text -split "`r?`n" | Where-Object { $_ -like "*/resourceGroups/$ResourceGroupName/*" }
        foreach ($roleAssignmentId in $roleAssignmentIds) {
            Invoke-Az @('role', 'assignment', 'delete', '--ids', $roleAssignmentId) -AllowFailure | Out-Null
        }
    }
}

$contextInitiativeIds = if ($context) { @($context.AuditInitiativeId, $context.EnforceInitiativeId) } else { @() }
foreach ($initiativeId in @($contextInitiativeIds) + @($discoveredInitiativeIds) | Where-Object { $_ } | Select-Object -Unique) {
    Invoke-Az @('rest', '--method', 'delete', '--url', "https://management.azure.com/subscriptions/$SubscriptionId/providers/Microsoft.Authorization/policySetDefinitions/$initiativeId`?api-version=$policyApi") -AllowFailure | Out-Null
}

$manifestDefinitionIds = if ($manifest) { @(@($manifest.Audit) + @($manifest.Enforce) | ForEach-Object PolicyId) } else { @() }
foreach ($definitionId in @($manifestDefinitionIds) + @($discoveredDefinitionIds) | Where-Object { $_ } | Select-Object -Unique) {
    Invoke-Az @('rest', '--method', 'delete', '--url', "https://management.azure.com/subscriptions/$SubscriptionId/providers/Microsoft.Authorization/policyDefinitions/$definitionId`?api-version=$policyApi") -AllowFailure | Out-Null
}

if ($exists -eq 'true') {
    Invoke-Az @('group', 'delete', '-n', $ResourceGroupName, '--yes', '--no-wait') | Out-Null
    $deadline = (Get-Date).AddMinutes(30)
    do {
        Start-Sleep -Seconds 20
        $exists = (Invoke-Az @('group', 'exists', '-n', $ResourceGroupName, '-o', 'tsv')).Text.Trim()
        if ($exists -eq 'false') { break }
        if ((Get-Date) -ge $deadline) { throw 'Timed out waiting for the exact workshop resource group to be deleted.' }
    } while ($true)
}

$remainingAssignments = (Invoke-Az @('policy', 'assignment', 'list', '--scope', "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName", '--query', "[?name=='mc-workshop-audit' || name=='mc-workshop-enforce'] | length(@)", '-o', 'tsv') -AllowFailure).Text
Write-Host "Cleanup complete. ResourceGroupExists=$exists; RemainingWorkshopAssignments=$remainingAssignments"
