[CmdletBinding()]
param(
    [Parameter(Mandatory)]
    [ValidatePattern('^[0-9a-fA-F-]{36}$')]
    [string]$SubscriptionId,

    [switch]$CapturePrivateProfileProof
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
. (Join-Path $PSScriptRoot 'AvdWorkshop.Common.ps1')

$paths = Get-AvdWorkshopPaths -ScriptRoot $PSScriptRoot
Initialize-AvdWorkshopDirectory -Paths $paths
$state = Read-AvdWorkshopState -Path $paths.StatePath
if ([string]$state.SubscriptionId -ne $SubscriptionId) { throw 'The subscription does not match the private workshop state.' }

Invoke-AvdAzCli -Arguments @('account','set','--subscription',$SubscriptionId) -Quiet | Out-Null
$group = Invoke-AvdAzJson -Arguments @('group','show','--name',$state.ResourceGroup) -Quiet
if ([string]$group.tags.workshop -ne 'azure-virtual-desktop-deep-dive' -or [string]$group.tags.'workshop-session' -ne [string]$state.SessionId) {
    throw 'The workshop resource-group ownership tags do not match the private state.'
}

$hostResponse = Invoke-AvdAzRestJson -Method GET -Uri "https://management.azure.com$($state.HostPoolId)/sessionHosts?api-version=$($state.AvdApiVersion)" -Quiet
$hosts = @($hostResponse.value)
$availableCount = @($hosts | Where-Object { $_.properties.status -eq 'Available' }).Count
$drainCount = @($hosts | Where-Object { -not [bool]$_.properties.allowNewSession }).Count

$powerStates = @($state.VmNames | ForEach-Object {
    Get-AvdVmPowerState -ResourceGroup $state.ResourceGroup -Name ([string]$_)
})
$runningCount = @($powerStates | Where-Object { $_ -eq 'VM running' }).Count
$deallocatedCount = @($powerStates | Where-Object { $_ -eq 'VM deallocated' }).Count

$trustedLaunchCount = 0
$publicIpCount = 0
$amaSucceededCount = 0
$dcrAssociationCount = 0
$fslogixConfigurationCount = 0
for ($index = 0; $index -lt [int]$state.HostCount; $index++) {
    $vmName = [string]$state.VmNames[$index]
    $vm = Invoke-AvdAzJson -Arguments @('vm','show','--resource-group',$state.ResourceGroup,'--name',$vmName) -Quiet
    $nic = Invoke-AvdAzJson -Arguments @('network','nic','show','--resource-group',$state.ResourceGroup,'--name',[string]$state.NicNames[$index]) -Quiet
    if ([string]$vm.securityProfile.securityType -eq 'TrustedLaunch' -and [bool]$vm.securityProfile.uefiSettings.secureBootEnabled -and [bool]$vm.securityProfile.uefiSettings.vTpmEnabled) { $trustedLaunchCount++ }
    $ipConfiguration = $nic.ipConfigurations[0]
    if ($ipConfiguration.PSObject.Properties.Name -contains 'publicIPAddress' -and $ipConfiguration.publicIPAddress) { $publicIpCount++ }

    $ama = Invoke-AvdAzJson -Arguments @('vm','extension','show','--resource-group',$state.ResourceGroup,'--vm-name',$vmName,'--name','AzureMonitorWindowsAgent') -AllowFailure -Quiet
    if ($ama -and [string]$ama.provisioningState -eq 'Succeeded') { $amaSucceededCount++ }
    $associationUri = "https://management.azure.com$($vm.id)/providers/Microsoft.Insights/dataCollectionRuleAssociations/avd-sessionhosts?api-version=$($state.MonitorApiVersion)"
    if (Invoke-AvdAzRestJson -Method GET -Uri $associationUri -AllowFailure -Quiet) { $dcrAssociationCount++ }

    $privateConfigPath = Join-Path $paths.RuntimeRoot ("{0}-fslogix-config.json" -f $vmName)
    if (Test-Path -LiteralPath $privateConfigPath) { $fslogixConfigurationCount++ }
}

$storage = Invoke-AvdAzJson -Arguments @('storage','account','show','--resource-group',$state.ResourceGroup,'--name',$state.StorageAccount) -Quiet
$entraKerberosEnabled = ([string]$storage.azureFilesIdentityBasedAuthentication.directoryServiceOptions -eq 'AADKERB')
$defaultSharePermission = [string]$storage.azureFilesIdentityBasedAuthentication.defaultSharePermission
$pe = Invoke-AvdAzJson -Arguments @('network','private-endpoint','show','--resource-group',$state.ResourceGroup,'--name',$state.PrivateEndpointName) -Quiet
$privateEndpointApproved = ([string]$pe.privateLinkServiceConnections[0].privateLinkServiceConnectionState.status -eq 'Approved')
$dnsZone = Invoke-AvdAzJson -Arguments @('network','private-dns','zone','show','--resource-group',$state.ResourceGroup,'--name',$state.PrivateDnsZone) -Quiet
$dnsLink = Invoke-AvdAzJson -Arguments @('network','private-dns','link','vnet','show','--resource-group',$state.ResourceGroup,'--zone-name',$state.PrivateDnsZone,'--name',$state.PrivateDnsLinkName) -Quiet

$scaling = Invoke-AvdAzRestJson -Method GET -Uri "https://management.azure.com$($state.ScalingPlanId)?api-version=$($state.AvdApiVersion)" -Quiet
$schedule = @($scaling.properties.schedules)[0]

$law = Invoke-AvdAzJson -Arguments @('monitor','log-analytics','workspace','show','--resource-group',$state.ResourceGroup,'--workspace-name',$state.LogAnalyticsName) -Quiet
$heartbeatRows = @(Invoke-AvdLogQuery -WorkspaceId ([string]$law.customerId) -Query 'Heartbeat | where TimeGenerated > ago(24h) | summarize Hosts=dcount(Computer)' -AllowFailure)
$avdRegistrationRows = @(Invoke-AvdLogQuery -WorkspaceId ([string]$law.customerId) -Query 'WVDHostRegistrations | where TimeGenerated > ago(24h) | summarize Records=count()' -AllowFailure)
$fslogixRows = @(Invoke-AvdLogQuery -WorkspaceId ([string]$law.customerId) -Query "Event | where TimeGenerated > ago(24h) | where Source == 'AVDWorkshop' or EventLog has 'FSLogix' | summarize Records=count()" -AllowFailure)
$autoscaleRows = @(Invoke-AvdLogQuery -WorkspaceId ([string]$law.customerId) -Query 'WVDAutoscaleEvaluationPooled | where TimeGenerated > ago(24h) | summarize Records=count()' -AllowFailure)

$profileVhdxCount = $null
if ($CapturePrivateProfileProof) {
    if ([string]$state.ProfilePersistenceStatus -ne 'Verified-HostSwitch') {
        throw 'Private profile proof can only be captured after a real interactive host-switch test updates the private state.'
    }
    $profileVhdxCount = [int]$state.ProfileVhdxCount
}

$monitoringDataState = if ($heartbeatRows.Count -gt 0) { 'QuerySucceeded' } else { 'NoDataYet' }
$evidence = [ordered]@{
    Workshop = 'Azure Virtual Desktop Deep Dive'
    EvidenceGeneratedUtc = [DateTime]::UtcNow.ToString('o')
    Region = 'West Europe'
    Configuration = [ordered]@{
        HostPoolType = 'Pooled'
        LoadBalancing = 'Depth-first'
        SessionHostCount = [int]$state.HostCount
        VmSize = [string]$state.VmSize
        OperatingSystem = 'Windows 11 Enterprise multi-session 24H2'
        EntraJoin = $true
        TrustedLaunch = $true
        NatGatewayOutbound = $true
    }
    SessionHosts = [ordered]@{
        RegisteredCount = $hosts.Count
        AvailableCount = $availableCount
        DrainedCount = $drainCount
        TrustedLaunchCount = $trustedLaunchCount
        PublicIpCount = $publicIpCount
        RunningCount = $runningCount
        DeallocatedCount = $deallocatedCount
    }
    Fslogix = [ordered]@{
        ConfiguredHostCount = $fslogixConfigurationCount
        VhdFormat = 'VHDX'
        DynamicDisks = $true
        DeleteLocalProfileWhenContainerApplies = $true
        CloudKerberosTicketRetrieval = $true
        LoadCredentialKeyFromProfile = $true
        CreatorOwnerAcl = $true
        ProfilePersistenceStatus = [string]$state.ProfilePersistenceStatus
        ProfileVhdxCount = $profileVhdxCount
        InteractiveEvidencePublished = ([string]$state.ProfilePersistenceStatus -eq 'Verified-HostSwitch')
    }
    AzureFiles = [ordered]@{
        Sku = 'Standard_LRS'
        EntraKerberosEnabled = $entraKerberosEnabled
        DefaultSharePermission = $defaultSharePermission
        PrivateEndpointApproved = $privateEndpointApproved
        PrivateDnsZonePresent = [bool]$dnsZone
        PrivateDnsVnetLinkPresent = [bool]$dnsLink
        PublicNetworkAccess = [string]$storage.publicNetworkAccess
    }
    Autoscale = [ordered]@{
        ScalingPlanAssigned = (@($scaling.properties.hostPoolReferences | Where-Object scalingPlanEnabled).Count -eq 1)
        ProductionMinimumHostsPercent = [int]$schedule.rampDownMinimumHostsPct
        RampDownLoadBalancing = [string]$schedule.rampDownLoadBalancingAlgorithm
        TestStatus = [string]$state.ScalingTestStatus
        ExactlyOneUnusedHostDeallocated = ([string]$state.ScalingTestStatus -eq 'Passed-OneRunning-OneDeallocated')
        ProductionScheduleRestored = ([string]$schedule.name -eq 'production-week')
    }
    Monitoring = [ordered]@{
        AmaSucceededHostCount = $amaSucceededCount
        DcrAssociationCount = $dcrAssociationCount
        HeartbeatQuery = $monitoringDataState
        HostRegistrationQuery = if ($avdRegistrationRows.Count -gt 0) { 'QuerySucceeded' } else { 'NoDataYet' }
        FslogixEventQuery = if ($fslogixRows.Count -gt 0) { 'QuerySucceeded' } else { 'NoDataOrInteractiveTestSkipped' }
        AutoscaleQuery = if ($autoscaleRows.Count -gt 0) { 'QuerySucceeded' } else { 'NoDataYet' }
        AvdDiagnosticsConfigured = $true
    }
    Identity = [ordered]@{
        TemporaryCloudUserCreated = [bool]$state.TestUserCreated
        EligibleLicenseAssigned = [bool]$state.AssignedLicenseSkuId
        UsageLocation = if ([bool]$state.TestUserCreated) { 'DE' } else { 'NotApplicable' }
        ConditionalAccessModified = $false
        TenantMfaDisabled = $false
    }
    Safety = [ordered]@{
        RuntimeSecretsPublished = $false
        UserPrincipalNamesPublished = $false
        IdentifiersPublished = $false
        IpAddressesPublished = $false
        ProfileFileNamesPublished = $false
        SimulatedSessionEvidencePublished = $false
    }
}

$evidencePath = Join-Path $paths.EvidenceRoot 'workshop-evidence.json'
[System.IO.File]::WriteAllText($evidencePath, ($evidence | ConvertTo-Json -Depth 30), [System.Text.UTF8Encoding]::new($false))
Assert-AvdSanitizedFile -Path $evidencePath

$sanitizationText = @'
SANITIZATION: PASSED
The public evidence contains no user principal names, passwords, tenant or subscription identifiers, object identifiers, registration tokens, IP addresses, or identity-bearing profile filenames.
No VHDX, connection, session, or host-switch result is published unless a real interactive test produced it.
'@
$sanitizationPath = Join-Path $paths.EvidenceRoot 'sanitization-report.txt'
[System.IO.File]::WriteAllText($sanitizationPath, $sanitizationText.Trim() + [Environment]::NewLine, [System.Text.UTF8Encoding]::new($false))
Assert-AvdSanitizedFile -Path $sanitizationPath

Write-Host "Sanitized evidence written to $evidencePath" -ForegroundColor Green
