functions/System/Drift/New-SecurityDriftReport.ps1

function New-SecurityDriftReport {
    <#
    .SYNOPSIS
    Creates and exports security drift detection report.
    
    .DESCRIPTION
    Compiles drift findings from all detection functions into a structured report.
    Exports as CSV with summary metadata and detailed findings.
    
    .PARAMETER DriftFindings
    PSCustomObject array of drift findings from Get-*Drift functions.
    
    .PARAMETER OutputDirectory
    Output directory for CSV report (default: logs/).
    
    .EXAMPLE
    $findings = @()
    $findings += Get-AccountPoliciesDrift
    $findings += Get-NetworkSecurityDrift
    $report = New-SecurityDriftReport -DriftFindings $findings
    
    .NOTES
    DEPENDENCIES: Write-Log (Core)
    APPLIES TO: All Windows Servers
    #>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [PSCustomObject[]]$DriftFindings = @(),
        [string]$OutputDirectory = "$(Split-Path (Split-Path $PSScriptRoot -Parent) -Parent)\logs"
    )

    # DEPENDS ON: Write-Log (Core)
    # DEPENDS ON: Get-Date (native), Export-Csv (native), New-Item (native)
    $ErrorActionPreference = 'Stop'

    try {
        # Ensure output directory exists
        if (-not (Test-Path $OutputDirectory)) {
            if ($PSCmdlet.ShouldProcess($OutputDirectory, "Create output directory")) {
                New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null
                Write-Log -Message "Created output directory: $OutputDirectory" -Level Info `
                    -Caller $MyInvocation.MyCommand.Name
            }
        }

        # Generate report filename with timestamp
        $reportDate = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
        $reportFile = Join-Path $OutputDirectory "Drift_Detection_$reportDate.csv"

        # Determine overall status and severity
        if ($DriftFindings.Count -eq 0) {
            $status = "COMPLIANT"
        }
        else {
            $status = "NON-COMPLIANT"
        }
        $criticalCount = @($DriftFindings | Where-Object Severity -eq "CRITICAL").Count
        $highCount = @($DriftFindings | Where-Object Severity -eq "HIGH").Count
        $mediumCount = @($DriftFindings | Where-Object Severity -eq "MEDIUM").Count
        if ($criticalCount -gt 0) {
            $overallSeverity = "CRITICAL"
        }
        elseif ($highCount -gt 0) {
            $overallSeverity = "HIGH"
        }
        else {
            $overallSeverity = "MEDIUM"
        }

        # Create summary object
        $summary = [PSCustomObject]@{
            'Scan_Date' = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
            'Hostname' = $env:COMPUTERNAME
            'Status' = $status
            'Total_Drifts' = $DriftFindings.Count
            'Critical_Count' = $criticalCount
            'High_Count' = $highCount
            'Medium_Count' = $mediumCount
            'Overall_Severity' = $overallSeverity
        }

        # Export summary
        if ($PSCmdlet.ShouldProcess($reportFile, "Export drift report")) {
            $summary | Export-Csv -Path $reportFile -NoTypeInformation -Force
            Write-Log -Message "Drift report exported: $reportFile (Status: $status, Drifts: $($DriftFindings.Count))" `
                -Level Info -Caller $MyInvocation.MyCommand.Name

            # Append detailed findings
            if ($DriftFindings.Count -gt 0) {
                $DriftFindings | Export-Csv -Path $reportFile -NoTypeInformation -Append -Force
            }
        }

        return [PSCustomObject]@{
            ReportPath = $reportFile
            Status = $status
            DriftCount = $DriftFindings.Count
            Severity = $overallSeverity
        }
    }
    catch {
        Write-Log -Message "Error creating drift report: $_" -Level Error -Caller $MyInvocation.MyCommand.Name
        throw
    }
}