<#
.SYNOPSIS
    Daily VMware Cluster metadata report for PowerBI trending and capacity planning.

.DESCRIPTION
    Collects cluster-level metadata from vCenter including DRS/HA configuration,
    aggregate compute capacity, and effective resource availability.
    Exports a timestamped CSV and inserts into SQL each run.
    Append daily runs to build a historical dataset for PowerBI trend analysis.

.NOTES
    Run the following DDL once to create the destination table:

        DROP TABLE IF EXISTS [dbo].[VMware_Trends_Cluster]

        CREATE TABLE [dbo].[VMware_Trends_Cluster] (
            [ReportDate]          DATETIME2      NOT NULL,
            [ClusterName]         NVARCHAR(255)  NOT NULL,
            [Datacenter]          NVARCHAR(100)  NULL,
            [DrsEnabled]          BIT            NOT NULL,
            [DrsMode]             NVARCHAR(50)   NULL,
            [HaEnabled]           BIT            NOT NULL,
            [HostCount]           INT            NULL,
            [EffectiveHostCount]  INT            NULL,
            [TotalCpuCores]       INT            NULL,
            [TotalCpuMhz]         INT            NULL,
            [EffectiveCpuMhz]     INT            NULL,
            [TotalMemoryGB]       DECIMAL(10,2)  NULL,
            [EffectiveMemoryGB]   DECIMAL(10,2)  NULL,
            [UsedMemoryGB]        DECIMAL(10,2)  NULL,
            [VMCount]             INT            NULL
        )

    TotalCpuMhz, EffectiveCpuMhz, TotalMemoryGB, and EffectiveMemoryGB come from
    vCenter's cluster summary (real-time aggregate).
    UsedMemoryGB is summed from each host's current MemoryUsageGB.
    TotalCpuCores is summed from each host's hardware CpuInfo.
#>
[CmdletBinding()]
param(
)

Connect-ITDvCenter -Credential $Secret:ndgov_svcitdvmvcro

#region --- Setup ---------------------------------------------------------------
[string] $OutputPath     = 'C:\temp\VM_Trends\'
[string] $ServerInstance = 'itdintsql22p1.nd.gov\INTSQL22P1'
[string] $Database       = 'ITD-Systems-Automation'
[string] $Table          = 'VMware_Trends_Cluster'
[System.Management.Automation.PSCredential] $SqlCredential = $Secret:sql_itdpsu1

$RunDate   = Get-Date
$DateStamp = $RunDate.ToString('yyyyMMdd')
$Timestamp = $RunDate.ToString('yyyy-MM-dd')

if (-not (Test-Path -Path $OutputPath)) {
    New-Item -ItemType Directory -Path $OutputPath | Out-Null
}

Start-Transcript -Path (Join-Path $OutputPath "ClusterMetadataReport_$DateStamp.log") -Append

#endregion

#region --- Build Cluster -> Datacenter Lookup ---------------------------------

Write-Verbose 'Building cluster-to-datacenter map...'
$ClusterDatacenterMap = @{}

Get-Datacenter | ForEach-Object {
    $DatacenterName = $_.Name
    Get-Cluster -Location $_ | ForEach-Object {
        $ClusterDatacenterMap[$_.Name] = $DatacenterName
    }
}

#endregion

#region --- Collect Cluster Data -----------------------------------------------

Write-Verbose 'Gathering clusters...'
$AllClusters = Get-Cluster

Write-Verbose "Processing $($AllClusters.Count) clusters..."

$Results = foreach ($Cluster in $AllClusters) {

    $Summary = $Cluster.ExtensionData.Summary  # reuse for all summary fields

    #--- Aggregate host-level stats that vCenter summary does not expose
    $ClusterHosts  = Get-VMHost -Location $Cluster
    $TotalCpuCores = ($ClusterHosts | ForEach-Object {
        $_.ExtensionData.Hardware.CpuInfo.NumCpuCores
    } | Measure-Object -Sum).Sum
    $UsedMemoryGB  = [Math]::Round(
        ($ClusterHosts | Measure-Object -Property MemoryUsageGB -Sum).Sum, 2
    )
    $VMCount = ($ClusterHosts | ForEach-Object {
        ($_.ExtensionData.Vm | Measure-Object).Count
    } | Measure-Object -Sum).Sum

    #--- Capacity from cluster summary
    $TotalCpuMhz     = $Summary.TotalCpu                                            # MHz
    $EffectiveCpuMhz = $Summary.EffectiveCpu                                        # MHz
    $TotalMemoryGB   = [Math]::Round($Summary.TotalMemory / 1GB, 2)                 # bytes -> GB
    $EffectiveMemGB  = [Math]::Round($Summary.EffectiveMemory / 1KB, 2)             # MB -> GB

    [PSCustomObject]@{
        ReportDate         = $Timestamp
        ClusterName        = $Cluster.Name
        Datacenter         = $ClusterDatacenterMap[$Cluster.Name]
        DrsEnabled         = $Cluster.DrsEnabled
        DrsMode            = $Cluster.DrsAutomationLevel
        HaEnabled          = $Cluster.HAEnabled
        HostCount          = $Summary.NumHosts
        EffectiveHostCount = $Summary.NumEffectiveHosts
        TotalCpuCores      = [int]$TotalCpuCores
        TotalCpuMhz        = $TotalCpuMhz
        EffectiveCpuMhz    = $EffectiveCpuMhz
        TotalMemoryGB      = $TotalMemoryGB
        EffectiveMemoryGB  = $EffectiveMemGB
        UsedMemoryGB       = $UsedMemoryGB
        VMCount            = [int]$VMCount
    }
}

#endregion

#region --- Export CSV ---------------------------------------------------------

$OutputFile = Join-Path $OutputPath "ClusterMetadata_$DateStamp.csv"
$Results | Export-Csv -Path $OutputFile -NoTypeInformation
Write-Verbose "Exported $($Results.Count) cluster records to: $OutputFile"

#endregion

#region --- SQL Insert ---------------------------------------------------------

$DataTable = [System.Data.DataTable]::new()

$ColDefs = [ordered]@{
    ReportDate         = [datetime]
    ClusterName        = [string]
    Datacenter         = [string]
    DrsEnabled         = [bool]
    DrsMode            = [string]
    HaEnabled          = [bool]
    HostCount          = [int]
    EffectiveHostCount = [int]
    TotalCpuCores      = [int]
    TotalCpuMhz        = [int]
    EffectiveCpuMhz    = [int]
    TotalMemoryGB      = [decimal]
    EffectiveMemoryGB  = [decimal]
    UsedMemoryGB       = [decimal]
    VMCount            = [int]
}

foreach ($Col in $ColDefs.GetEnumerator()) {
    $Column = [System.Data.DataColumn]::new($Col.Key, $Col.Value)
    $Column.AllowDBNull = $true
    [void]$DataTable.Columns.Add($Column)
}

foreach ($Row in $Results) {
    $DataRow = $DataTable.NewRow()
    foreach ($Col in $ColDefs.Keys) {
        $Val = $Row.$Col
        $DataRow[$Col] = if ($null -ne $Val) { $Val } else { [DBNull]::Value }
    }
    [void]$DataTable.Rows.Add($DataRow)
}

$SqlParams = @{
    ServerInstance = $ServerInstance
    DatabaseName   = $Database
    SchemaName     = 'dbo'
    TableName      = $Table
    Credential     = $SqlCredential
    InputData      = $DataTable
}
Write-SqlTableData @SqlParams

Write-Verbose "Inserted $($DataTable.Rows.Count) cluster records into [$Database].[dbo].[$Table]"

#endregion

Disconnect-ITDvCenter 

#region --- Cleanup -------------------------------------------------------------
Stop-Transcript

#endregion
