Public/Invoke-ModernMailHybridReport.ps1

function Invoke-ModernMailHybridReport {
        <#
    .SYNOPSIS
        ModernMail Hybrid Report / Exchange Hybrid Report / Microsoft365 Hybrid Report
    .DESCRIPTION
        Generates a comprehensive Exchange Hybrid report for Microsoft 365 environments.
        The report includes user statistics, shared mailbox details, directory sync status, and license information.
        Outputs a styled HTML file with interactive charts and summary statistics.
    .PARAMETER OutPath
        The output path for the generated HTML report.
        Can be a directory (FileName: 'ExchangeHybridReport.html') or a full file path.
    .EXAMPLE
        Invoke-ModernMailHybridReport -OutPath "C:\Reports"
        Invoke-ModernMailHybridReport -OutPath "C:\Reports\ExchangeHybridReport.html"
    .LINK
        https://exchangepermissions.alweys.ch/modernmailtools/Invoke-ModernMailHybridReport
    .INPUTS
        None
    .OUTPUTS
    .NOTES
    #>


    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$OutPath
    )

    # Connect-ExchangeServer.ps1

    # Connect-Exchange Online
    $session = Get-ConnectionInformation
    If (!$session) {
        Connect-ExchangeOnline -ShowBanner:$false
        $session = Get-ConnectionInformation
    }
    Write-Debug $session.UserPrincipalName
    $userPrincipalName = $session.UserPrincipalName
    ## Organization | $organisationName
    Write-Debug $session.TenantID
    $tenantID = $session.TenantID

    $users = Get-User
    #$usersGrouped = $users | Group RecipientType
    $usersGrouped = $users | Group-Object RecipientTypeDetails
    #$usersGrouped[0].Name
    #$usersGrouped[0].Count

    #Total Users
    $usersCount = $users.Count

    #$users | Group IsDirSynced
    $isDirSyncedCount = ($users | Where-Object {$_.IsDirSynced}).count

    $sharedMailboxes = $users | Where-Object {$_.RecipientTypeDetails -eq "SharedMailbox"}
    $sharedMailboxCount = $sharedMailboxes.count

    # ToBeQuestioned
    $sharedMailboxEnabled = $sharedMailboxes | Where-Object {$_.AccountDisabled -eq $false}
    $sharedMailboxEnabledCount = $sharedMailboxEnabled.count

    #$users | Group AccountDisabled
    $sharedMailboxDisabled = $sharedMailboxes | Where-Object {$_.AccountDisabled -eq $true}
    $sharedMailboxDisabledCount = $sharedMailboxDisabled.count

    # ToBeQuestioned (Litigation Hold Enabled?)
    #$users | Group SKUAssigned
    $sharedMailboxLicensed = ($sharedMailboxes | Where-Object {$_.SKUAssigned -ne $true})
    $sharedMailboxLicensedCount = $sharedMailboxLicensed.count

    #$users | select -First 1 *hold*

    function Build-HybridReport {
        param(
            [Parameter(Mandatory=$false)]
            [string]$OutputPath
        )

        # Path to the HTML template
        $templatePath = "$PSScriptRoot\..\Private\HybridReportTemplate.html"

        # Read the HTML template
        $htmlTemplate = Get-Content -Path $templatePath -Raw

        # Generate dynamic rows for grouped data
        $dynamicRows = ""
        $chartLabels = @()
        $chartData = @()
        foreach ($group in $usersGrouped) {
            $dynamicRows += @"
                <tr class="border-b border-gray-300">
                    <td class="px-4 py-2 border-b border-r">$($group.Name)</td>
                    <td class="px-4 py-2 border-b">$($group.Count)</td>
                </tr>
"@

            $chartLabels += "'$($group.Name)'"
            $chartData += $group.Count
        }

        # Convert arrays to JavaScript-compatible strings
        $chartLabelsString = "[" + ($chartLabels -join ", ") + "]"
        $chartDataString = "[" + ($chartData -join ", ") + "]"

        # Generate header details
        $reportName = "Exchange Hybrid Report"
        $date = Get-Date
        #$organizationName = "Your Organization Name" # Replace with actual organization name

        $headerContent = @"
    <div class="header bg-orange-500 text-white p-6 rounded-lg shadow-md">
        <h1 class="text-3xl font-bold">$reportName</h1>
        <!--<p class="text-lg">Organization: $organizationName</p>-->
        <p class="text-lg mt-4">Tenant ID: $tenantID</p>
        <p class="text-lg">Generated by: $userPrincipalName</p>
        <p class="text-lg">Generated on: $date</p>
        <div class="mt-4">
            <a href="https://alweys.ch" target="_blank" class="bg-blue-500 hover:bg-blue-700 text-white text-xs font-semibold py-1 px-2 rounded">
                Website (alweys.ch)
            </a>
            <a href="https://www.linkedin.com/in/stefanwey" target="_blank" class="bg-blue-500 hover:bg-blue-700 text-white text-xs font-semibold py-1 px-2 rounded ml-2">
                LinkedIn (Stefan Wey)
            </a>
        </div>
    </div>
    <div class="stats-container grid grid-cols-2 gap-4 mt-4">
        <div class="stat-box bg-white p-4 rounded-lg shadow-md">
            <h3 class="text-lg font-semibold">Total Users</h3>
            <p class="text-2xl font-bold text-orange-500">$usersCount</p>
        </div>
        <div class="stat-box bg-white p-4 rounded-lg shadow-md">
            <h3 class="text-lg font-semibold">Shared Mailboxes</h3>
            <p class="text-2xl font-bold text-orange-500">$sharedMailboxCount</p>
        </div>
        <div class="stat-box bg-white p-4 rounded-lg shadow-md">
            <h3 class="text-lg font-semibold">Directory Synced Users</h3>
            <p class="text-2xl font-bold text-orange-500">$isDirSyncedCount</p>
        </div>
        <div class="stat-box bg-white p-4 rounded-lg shadow-md">
            <h3 class="text-lg font-semibold">Enabled Shared Mailboxes</h3>
            <p class="text-2xl font-bold text-orange-500">$sharedMailboxEnabledCount</p>
        </div>
        <div class="stat-box bg-white p-4 rounded-lg shadow-md">
            <h3 class="text-lg font-semibold">Disabled Shared Mailboxes</h3>
            <p class="text-2xl font-bold text-orange-500">$sharedMailboxDisabledCount</p>
        </div>
        <div class="stat-box bg-white p-4 rounded-lg shadow-md">
            <h3 class="text-lg font-semibold">Licensed Shared Mailboxes</h3>
            <p class="text-2xl font-bold text-orange-500">$sharedMailboxLicensedCount</p>
        </div>
    </div>
"@


        # Replace placeholders in the template
        $htmlContent = $htmlTemplate -replace "{{HeaderContent}}", $headerContent
        $htmlContent = $htmlContent -replace "{{DynamicRows}}", $dynamicRows
        $htmlContent = $htmlContent -replace "{{ChartLabels}}", $chartLabelsString
        $htmlContent = $htmlContent -replace "{{ChartData}}", $chartDataString

        # Generate the Path
        if (Test-Path $OutPath -PathType Container) {
            # If $OutPath is a directory, append the default file name
            $OutputPath = Join-Path -Path $OutPath -ChildPath "ExchangeHybridReport.html"
        } else {
            # If $OutPath is a file, use it directly
            $OutputPath = $OutPath
        }

        # Output HTML report
        #$html | Out-File -FilePath $OutputPath -Encoding UTF8
        $htmlContent | Out-File -FilePath $OutputPath -Encoding UTF8
        Write-output "HTML report generated at $OutputPath"

        # Open the report in the default browser
        Start-Process $OutputPath
    }

    Build-HybridReport -OutputPath $OutPath
}