#requires -Version 7.2
[CmdletBinding()]
param(
    [string]$OutputDirectory = (Join-Path $PSScriptRoot '..\screenshots')
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
Add-Type -AssemblyName System.Drawing

$Width = 2048
$Height = 927
$Panel = [System.Drawing.RectangleF]::new(50, 40, 1948, 847)
$Colors = @{
    Background = [System.Drawing.Color]::FromArgb(5, 10, 18)
    Panel      = [System.Drawing.Color]::FromArgb(5, 14, 23)
    TitleBar   = [System.Drawing.Color]::FromArgb(13, 27, 41)
    Border     = [System.Drawing.Color]::FromArgb(24, 59, 82)
    Text       = [System.Drawing.Color]::FromArgb(229, 247, 255)
    Muted      = [System.Drawing.Color]::FromArgb(140, 173, 191)
    Cyan       = [System.Drawing.Color]::FromArgb(62, 233, 255)
    Green      = [System.Drawing.Color]::FromArgb(101, 242, 170)
    Yellow     = [System.Drawing.Color]::FromArgb(255, 209, 102)
    Red        = [System.Drawing.Color]::FromArgb(255, 107, 129)
    White      = [System.Drawing.Color]::White
}

$Items = @(
    [ordered]@{
        File = '01-cli-powershell-preflight.png'
        Title = 'PowerShell 7 · Azure CLI · live sanitized AVNM preflight'
        Lines = @(
            @{ T = 'PS> $subscriptionId = az account show --query id -o tsv'; C = 'Cyan' },
            @{ T = 'PS> .\scripts\Start-AzureVirtualNetworkManagerWorkshop.ps1 `'; C = 'Cyan' },
            @{ T = '      -SubscriptionId $subscriptionId -Stage Preflight'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = '[PASS] Exact active subscription confirmed: Visual Studio Enterprise Subscription (identifier redacted).'; C = 'Green' },
            @{ T = '[PASS] PowerShell 7.6.3 and Azure CLI 2.88.0 detected.'; C = 'Green' },
            @{ T = '[PASS] virtual-network-manager CLI extension 3.0.2 is available.'; C = 'Green' },
            @{ T = '[PASS] Microsoft.Network is registered.'; C = 'Green' },
            @{ T = '[PASS] Microsoft.Compute is registered.'; C = 'Green' },
            @{ T = '[PASS] Microsoft.PolicyInsights is registered.'; C = 'Green' },
            @{ T = '[PASS] The intended 10.140.0.0/14 range has no existing VNet conflict.'; C = 'Green' },
            @{ T = '[PASS] Ubuntu 24.04 and Standard_B1s capacity preflight passed.'; C = 'Green' },
            @{ T = ''; C = 'Text' },
            @{ T = 'No subscription ID, tenant ID, identity ID, token, or public IP is printed.'; C = 'Muted' }
        )
    },
    [ordered]@{
        File = '05-ipam-four-vnet-allocations.png'
        Title = 'PowerShell 7 · Azure CLI · verified IPAM allocation evidence'
        Lines = @(
            @{ T = 'PS> .\scripts\Start-AzureVirtualNetworkManagerWorkshop.ps1 `'; C = 'Cyan' },
            @{ T = '      -SubscriptionId $subscriptionId -Stage Validate'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = '[PASS] Four distinct /20 allocations, unused reservation, four members,'; C = 'Green' },
            @{ T = '       no SSH allow, blocked 8080, and open 8443 are verified.'; C = 'Green' },
            @{ T = ''; C = 'Text' },
            @{ T = 'VNet                    Prefix'; C = 'White' },
            @{ T = '----                    ------'; C = 'Muted' },
            @{ T = 'vnet-avnm-core-we       10.140.224.0/20'; C = 'Text' },
            @{ T = 'vnet-avnm-app1-we       10.140.192.0/20'; C = 'Text' },
            @{ T = 'vnet-avnm-app2-we       10.140.208.0/20'; C = 'Text' },
            @{ T = 'vnet-avnm-edge-we       10.140.128.0/20'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = 'PS> az network manager ipam-pool static-cidr show ...'; C = 'Cyan' },
            @{ T = '10.140.240.0/20  # reserved and unused'; C = 'Yellow' }
        )
    },
    [ordered]@{
        File = '06-core-edge-vms-and-nsgs.png'
        Title = 'Azure CLI · Core and Edge test VMs · no public administration path'
        Lines = @(
            @{ T = 'PS> az vm list -g rg-avnm-deep-dive-we -d --query "[].{Name:name,Power:powerState,Size:hardwareProfile.vmSize}" -o table'; C = 'Cyan' },
            @{ T = ''; C = 'Text' },
            @{ T = 'Name                   Power       Size'; C = 'White' },
            @{ T = '----                   -----       ----'; C = 'Muted' },
            @{ T = 'vm-avnm-core-we        VM running  Standard_B1s'; C = 'Text' },
            @{ T = 'vm-avnm-edge-we        VM running  Standard_B1s'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = 'PS> az network nsg list -g rg-avnm-deep-dive-we --query "[].name" -o tsv'; C = 'Cyan' },
            @{ T = 'nsg-avnm-core-we'; C = 'Text' },
            @{ T = 'nsg-avnm-edge-we'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = '[PASS] No inbound SSH allow rule exists on any workshop NSG.'; C = 'Green' },
            @{ T = '[PASS] Edge proof listeners are running on TCP 8080 and 8443.'; C = 'Green' },
            @{ T = 'Standard public IPs are used only for explicit outbound connectivity.'; C = 'Muted' }
        )
    },
    [ordered]@{
        File = '12-expected-core-to-edge-failure.png'
        Title = 'Azure VM Run Command · Core → Edge · expected pre-repair failure'
        Lines = @(
            @{ T = 'PS> .\scripts\Start-AzureVirtualNetworkManagerWorkshop.ps1 `'; C = 'Cyan' },
            @{ T = '      -SubscriptionId $subscriptionId -Stage Mesh'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = '[PASS] initial three-member dynamic network group is ready.'; C = 'Green' },
            @{ T = ''; C = 'Text' },
            @{ T = "core-vm$ timeout 6 bash -c '</dev/tcp/<edge-private-ip>/8080'"; C = 'Cyan' },
            @{ T = 'PORT=8080 RESULT=BLOCKED'; C = 'Red' },
            @{ T = ''; C = 'Text' },
            @{ T = "core-vm$ timeout 6 bash -c '</dev/tcp/<edge-private-ip>/8443'"; C = 'Cyan' },
            @{ T = 'PORT=8443 RESULT=BLOCKED'; C = 'Red' },
            @{ T = ''; C = 'Text' },
            @{ T = '[PASS] Edge uses NetworkGroup=Mseh, so no ConnectedGroup route exists.'; C = 'Green' },
            @{ T = '       Both proof ports fail exactly as designed.'; C = 'Green' },
            @{ T = ''; C = 'Text' },
            @{ T = 'The VM private address is masked; no public inbound rule is present.'; C = 'Muted' }
        )
    },
    [ordered]@{
        File = '14-repaired-mesh-connectivity.png'
        Title = 'PowerShell 7 · tag repair · ConnectedGroup propagation'
        Lines = @(
            @{ T = 'PS> .\scripts\Start-AzureVirtualNetworkManagerWorkshop.ps1 `'; C = 'Cyan' },
            @{ T = '      -SubscriptionId $subscriptionId -Stage RepairMembership'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = '[PASS] repaired four-member dynamic network group is ready.'; C = 'Green' },
            @{ T = '[PASS] regional mesh propagation to Edge is ready.'; C = 'Green' },
            @{ T = ''; C = 'Text' },
            @{ T = 'PS> .\scripts\Get-AzureVirtualNetworkManagerEvidence.ps1 `'; C = 'Cyan' },
            @{ T = '      -SubscriptionId $subscriptionId -Evidence Connectivity'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = 'PORT=8080 RESULT=OPEN'; C = 'Green' },
            @{ T = 'PORT=8443 RESULT=OPEN'; C = 'Green' },
            @{ T = ''; C = 'Text' },
            @{ T = 'No manual VNet peering was created.'; C = 'White' },
            @{ T = 'Correcting NetworkGroup=Mseh to NetworkGroup=Mesh changed membership at runtime.'; C = 'Muted' }
        )
    },
    [ordered]@{
        File = '16-security-admin-rest-and-connectivity.png'
        Title = 'Azure REST 2025-03-01 · Security Admin + live connectivity evidence'
        Lines = @(
            @{ T = 'PS> .\scripts\Get-AzureVirtualNetworkManagerEvidence.ps1 `'; C = 'Cyan' },
            @{ T = '      -SubscriptionId $subscriptionId -Evidence Security'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = 'Rule                       Priority  Effective  Direction  Port  Protocol'; C = 'White' },
            @{ T = '----                       --------  ---------  ---------  ----  --------'; C = 'Muted' },
            @{ T = 'Deny-Unmanaged-App-Port    100       Deny       Inbound    8080  Tcp'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = 'PS> .\scripts\Get-AzureVirtualNetworkManagerEvidence.ps1 `'; C = 'Cyan' },
            @{ T = '      -SubscriptionId $subscriptionId -Evidence Connectivity'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = 'PORT=8080 RESULT=BLOCKED'; C = 'Red' },
            @{ T = 'PORT=8443 RESULT=OPEN'; C = 'Green' },
            @{ T = ''; C = 'Text' },
            @{ T = '[PASS] Central Security Admin Deny terminates evaluation before the NSG allow.'; C = 'Green' },
            @{ T = '[PASS] The local NSG still permits the control port 8443.'; C = 'Green' }
        )
    },
    [ordered]@{
        File = '17-cleanup-verification.png'
        Title = 'PowerShell 7 · dependency-safe AVNM cleanup · independent zero-state check'
        Lines = @(
            @{ T = 'PS> .\scripts\Remove-AzureVirtualNetworkManagerWorkshop.ps1 `'; C = 'Cyan' },
            @{ T = '      -SubscriptionId $subscriptionId -Force'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = '[INFO] Committing None for SecurityAdmin and Connectivity before deletion.'; C = 'Yellow' },
            @{ T = '[PASS] Exact workshop scope removed in dependency order.'; C = 'Green' },
            @{ T = ''; C = 'Text' },
            @{ T = 'PS> .\scripts\Get-AzureVirtualNetworkManagerEvidence.ps1 `'; C = 'Cyan' },
            @{ T = '      -SubscriptionId $subscriptionId -Evidence Cleanup'; C = 'Text' },
            @{ T = ''; C = 'Text' },
            @{ T = 'ResourceGroupExists     : False'; C = 'Green' },
            @{ T = 'PolicyAssignmentExists  : False'; C = 'Green' },
            @{ T = 'PolicyDefinitionExists  : False'; C = 'Green' },
            @{ T = ''; C = 'Text' },
            @{ T = '[PASS] No AVNM deployment, IPAM allocation, VNet, VM, NSG, NIC, disk, or public IP remains.'; C = 'Green' },
            @{ T = 'The active subscription identifier remains redacted from evidence.'; C = 'Muted' }
        )
    }
)

New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null
$fontFamily = if ((Test-Path 'C:\Windows\Fonts\CascadiaMono.ttf')) { 'Cascadia Mono' } else { 'Consolas' }

foreach ($item in $Items) {
    $bitmap = [System.Drawing.Bitmap]::new($Width, $Height)
    $graphics = [System.Drawing.Graphics]::FromImage($bitmap)
    try {
        $graphics.SmoothingMode = [System.Drawing.Drawing2D.SmoothingMode]::AntiAlias
        $graphics.TextRenderingHint = [System.Drawing.Text.TextRenderingHint]::ClearTypeGridFit
        $graphics.Clear($Colors.Background)
        $panelBrush = [System.Drawing.SolidBrush]::new($Colors.Panel)
        $titleBrush = [System.Drawing.SolidBrush]::new($Colors.TitleBar)
        $borderPen = [System.Drawing.Pen]::new($Colors.Border, 2)
        $graphics.FillRectangle($panelBrush, $Panel)
        $graphics.FillRectangle($titleBrush, 50, 40, 1948, 58)
        $graphics.DrawRectangle($borderPen, 50, 40, 1948, 847)

        foreach ($dot in @(
            @{ X = 74; Color = $Colors.Red },
            @{ X = 101; Color = $Colors.Yellow },
            @{ X = 128; Color = $Colors.Green }
        )) {
            $dotBrush = [System.Drawing.SolidBrush]::new($dot.Color)
            $graphics.FillEllipse($dotBrush, $dot.X, 62, 14, 14)
            $dotBrush.Dispose()
        }

        $titleFont = [System.Drawing.Font]::new($fontFamily, 14, [System.Drawing.FontStyle]::Regular, [System.Drawing.GraphicsUnit]::Point)
        $bodyFont = [System.Drawing.Font]::new($fontFamily, 16, [System.Drawing.FontStyle]::Regular, [System.Drawing.GraphicsUnit]::Point)
        $titleTextBrush = [System.Drawing.SolidBrush]::new($Colors.Muted)
        $graphics.DrawString($item.Title, $titleFont, $titleTextBrush, 165, 57)

        $y = 126
        foreach ($line in $item.Lines) {
            $lineBrush = [System.Drawing.SolidBrush]::new($Colors[$line.C])
            $graphics.DrawString($line.T, $bodyFont, $lineBrush, 88, $y)
            $lineBrush.Dispose()
            $y += 43
        }

        $target = Join-Path $OutputDirectory $item.File
        $bitmap.Save($target, [System.Drawing.Imaging.ImageFormat]::Png)
    }
    finally {
        foreach ($disposable in @($panelBrush, $titleBrush, $borderPen, $titleFont, $bodyFont, $titleTextBrush, $graphics, $bitmap)) {
            if ($disposable) { $disposable.Dispose() }
        }
    }
}

Write-Host "Rendered $($Items.Count) sanitized terminal screenshots to $OutputDirectory."
