#requires -Version 7.2
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'High')]
param(
    [Parameter(Mandatory)][ValidatePattern('^[0-9a-fA-F-]{36}$')][string]$SubscriptionId,
    [ValidatePattern('^rg-avnm-deep-dive-we$')][string]$ResourceGroupName = 'rg-avnm-deep-dive-we',
    [ValidateSet('westeurope')][string]$Location = 'westeurope',
    [switch]$Force
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$Manager = 'avnm-governance-we'
$Connectivity = 'cc-avnm-regional-mesh-we'
$Security = 'sac-avnm-central-we'
$Group = 'ng-avnm-mesh-we'
$RootPool = 'ipam-avnm-root'
$ChildPool = 'ipam-avnm-westeurope'
$Reservation = 'reserved-platform-services'
$Assignment = 'avnm-mesh-dynamic-membership'
$Definition = 'avnm-add-tagged-vnets-to-mesh'
$script:AzCliPath = (Get-Command az -CommandType Application -ErrorAction Stop | Select-Object -First 1).Source

function Az([string[]]$Arguments, [switch]$AllowFailure) {
    $output = & $script:AzCliPath @Arguments 2>&1
    $code = $LASTEXITCODE
    if ($code -ne 0 -and -not $AllowFailure) { throw (($output -join "`n") -replace [regex]::Escape($SubscriptionId), '<subscription-redacted>') }
    return [pscustomobject]@{ ExitCode = $code; Output = ($output -join "`n") }
}

$activeId = (& $script:AzCliPath account show --query id -o tsv).Trim()
if ($activeId -ne $SubscriptionId) { throw 'Safety stop: the active subscription does not match the exact supplied subscription.' }
if ((& $script:AzCliPath group exists -n $ResourceGroupName -o tsv).Trim() -ne 'true') { Write-Host '[PASS] Workshop resource group is already absent.'; return }
$workshopTag = (& $script:AzCliPath group show -n $ResourceGroupName --query tags.Workshop -o tsv).Trim()
if ($workshopTag -ne 'AVNM-DeepDive') { throw 'Safety stop: the resource group lacks the expected AVNM workshop tag.' }
$resourceTypes = & $script:AzCliPath resource list -g $ResourceGroupName --query '[].type' -o tsv
Write-Host '[INFO] Exact cleanup scope by resource type:'
$resourceTypes | Group-Object | Sort-Object Name | ForEach-Object { Write-Host ("  {0,-60} {1,3}" -f $_.Name, $_.Count) }
if (-not $Force -and -not $PSCmdlet.ShouldProcess($ResourceGroupName, 'Undeploy Network Manager configurations and delete exact workshop scope')) { return }

Write-Host '[INFO] Committing None for SecurityAdmin and Connectivity before deletion.'
Az @('network', 'manager', 'post-commit', '-g', $ResourceGroupName, '-n', $Manager, '--commit-type', 'SecurityAdmin', '--target-locations', $Location, '--only-show-errors', '-o', 'none') -AllowFailure | Out-Null
Az @('network', 'manager', 'post-commit', '-g', $ResourceGroupName, '-n', $Manager, '--commit-type', 'Connectivity', '--target-locations', $Location, '--only-show-errors', '-o', 'none') -AllowFailure | Out-Null

$deadline = (Get-Date).AddMinutes(30)
do {
    $status = Az @('network', 'manager', 'list-deploy-status', '-g', $ResourceGroupName, '--network-manager-name', $Manager, '--deployment-types', 'Connectivity', 'SecurityAdmin', '--regions', $Location, '-o', 'json') -AllowFailure
    if ($status.ExitCode -ne 0 -or $status.Output -notmatch '(?i)Committing|Pending') { break }
    if ((Get-Date) -ge $deadline) { throw 'Timed out waiting for the None configuration deployment.' }
    Start-Sleep -Seconds 30
} while ($true)

$scope = "/subscriptions/$SubscriptionId/resourceGroups/$ResourceGroupName"
Az @('policy', 'assignment', 'delete', '-n', $Assignment, '--scope', $scope, '-o', 'none') -AllowFailure | Out-Null
Az @('policy', 'definition', 'delete', '-n', $Definition, '--subscription', $SubscriptionId, '-o', 'none') -AllowFailure | Out-Null

Az @('network', 'manager', 'security-admin-config', 'rule-collection', 'rule', 'delete', '-g', $ResourceGroupName, '-n', $Manager, '--configuration-name', $Security, '--rule-collection-name', 'rc-avnm-mesh-we', '--rule-name', 'Deny-Unmanaged-App-Port', '--yes', '-o', 'none') -AllowFailure | Out-Null
Az @('network', 'manager', 'security-admin-config', 'rule-collection', 'delete', '-g', $ResourceGroupName, '-n', $Manager, '--configuration-name', $Security, '--rule-collection-name', 'rc-avnm-mesh-we', '--yes', '-o', 'none') -AllowFailure | Out-Null
Az @('network', 'manager', 'security-admin-config', 'delete', '-g', $ResourceGroupName, '-n', $Manager, '--configuration-name', $Security, '--yes', '-o', 'none') -AllowFailure | Out-Null
Az @('network', 'manager', 'connect-config', 'delete', '-g', $ResourceGroupName, '--network-manager-name', $Manager, '--configuration-name', $Connectivity, '--yes', '-o', 'none') -AllowFailure | Out-Null
Az @('network', 'manager', 'group', 'delete', '-g', $ResourceGroupName, '--network-manager-name', $Manager, '-n', $Group, '--yes', '-o', 'none') -AllowFailure | Out-Null

foreach ($vm in @('vm-avnm-core-we', 'vm-avnm-edge-we')) { Az @('vm', 'delete', '-g', $ResourceGroupName, '-n', $vm, '--yes', '-o', 'none') -AllowFailure | Out-Null }
foreach ($nic in @('nic-avnm-core-we', 'nic-avnm-edge-we')) { Az @('network', 'nic', 'delete', '-g', $ResourceGroupName, '-n', $nic, '-o', 'none') -AllowFailure | Out-Null }
foreach ($pip in @('pip-avnm-core-we', 'pip-avnm-edge-we')) { Az @('network', 'public-ip', 'delete', '-g', $ResourceGroupName, '-n', $pip, '-o', 'none') -AllowFailure | Out-Null }
foreach ($vnet in @('vnet-avnm-core-we', 'vnet-avnm-app1-we', 'vnet-avnm-app2-we', 'vnet-avnm-edge-we')) { Az @('network', 'vnet', 'delete', '-g', $ResourceGroupName, '-n', $vnet, '-o', 'none') -AllowFailure | Out-Null }
foreach ($nsg in @('nsg-avnm-core-we', 'nsg-avnm-app1-we', 'nsg-avnm-app2-we', 'nsg-avnm-edge-we')) { Az @('network', 'nsg', 'delete', '-g', $ResourceGroupName, '-n', $nsg, '-o', 'none') -AllowFailure | Out-Null }

Az @('network', 'manager', 'ipam-pool', 'static-cidr', 'delete', '-g', $ResourceGroupName, '--manager-name', $Manager, '--pool-name', $ChildPool, '-n', $Reservation, '--yes', '-o', 'none') -AllowFailure | Out-Null
Az @('network', 'manager', 'ipam-pool', 'delete', '-g', $ResourceGroupName, '--manager-name', $Manager, '-n', $ChildPool, '--yes', '-o', 'none') -AllowFailure | Out-Null
Az @('network', 'manager', 'ipam-pool', 'delete', '-g', $ResourceGroupName, '--manager-name', $Manager, '-n', $RootPool, '--yes', '-o', 'none') -AllowFailure | Out-Null
Az @('network', 'manager', 'delete', '-g', $ResourceGroupName, '-n', $Manager, '--yes', '-o', 'none') -AllowFailure | Out-Null

Az @('group', 'delete', '-n', $ResourceGroupName, '--yes', '--no-wait') | Out-Null
& $script:AzCliPath group wait -n $ResourceGroupName --deleted --interval 15 --timeout 1800
if ($LASTEXITCODE -ne 0) { throw 'The resource group deletion did not complete within 30 minutes.' }
Write-Host '[PASS] The exact workshop resource group, policy, deployments, IPAM allocations, VNets, VMs, NICs, NSGs, disks, and public IPs are gone.'
