[CmdletBinding()]
param(
    [switch]$Json
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

function Get-ActivationStatus {
    $result = [ordered]@{
        LicenseStatus        = $null
        LicenseStatusText    = $null
        ProductName          = $null
        PartialProductKey    = $null
        IsActivated          = $false
        RawItemCount         = 0
        Notes                = @()
    }

    try {
        $cv = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
        $os = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop
        $lsItems = Get-CimInstance -Query "SELECT Name, Description, LicenseStatus, PartialProductKey FROM SoftwareLicensingProduct WHERE PartialProductKey IS NOT NULL" -ErrorAction Stop |
            Where-Object { $_.Name -like 'Windows*' -or $_.Description -like 'Windows*' } |
            Sort-Object -Property LicenseStatus -Descending

        $result.RawItemCount = ($lsItems | Measure-Object).Count
        $activated = $lsItems | Where-Object { $_.LicenseStatus -eq 1 } | Select-Object -First 1
        $primary = if ($activated) { $activated } else { $lsItems | Select-Object -First 1 }

        if ($primary) {
            $result.LicenseStatus = $primary.LicenseStatus
            $result.LicenseStatusText = switch ($primary.LicenseStatus) {
                0 { 'Unlicensed' }
                1 { 'Licensed' }
                2 { 'Out-Of-Box Grace Period' }
                3 { 'Out-Of-Tolerance Grace Period' }
                4 { 'Non-Genuine Grace Period' }
                5 { 'Notification' }
                6 { 'Extended Grace' }
                Default { "Unknown ($($_))" }
            }
            $result.ProductName = $primary.Name
            $result.PartialProductKey = $primary.PartialProductKey
            $result.IsActivated = [bool]($primary.LicenseStatus -eq 1)
        } else {
            $result.Notes += 'Nenhum produto Windows com PartialProductKey encontrado.'
        }

        if ($cv.InstallationType) {
            $result.Notes += "InstallationType: $($cv.InstallationType)"
        }
        if ($os.Caption) {
            $result.Notes += "Caption: $($os.Caption)"
        }
    } catch {
        $result.Notes += "Erro ao consultar ativação: $($_.Exception.Message)"
    }

    return $result
}

function Get-DefenderStatus {
    $result = [ordered]@{
        CommandAvailable          = $false
        AMRunningMode             = $null
        AntivirusEnabled          = $null
        RealTimeProtectionEnabled = $null
        AntispywareEnabled        = $null
        Notes                     = @()
    }

    $command = Get-Command -Name Get-MpComputerStatus -ErrorAction SilentlyContinue
    if (-not $command) {
        $result.Notes += 'Cmdlet Get-MpComputerStatus não está disponível (talvez a funcionalidade do Defender não esteja instalada).'
        return $result
    }

    $result.CommandAvailable = $true

    try {
        $status = Get-MpComputerStatus | Select-Object AMRunningMode,AntivirusEnabled,RealTimeProtectionEnabled,AntispywareEnabled
        if ($null -eq $status) {
            $result.Notes += 'Get-MpComputerStatus retornou $null.'
            return $result
        }

        $result.AMRunningMode = $status.AMRunningMode
        $result.AntivirusEnabled = $status.AntivirusEnabled
        $result.RealTimeProtectionEnabled = $status.RealTimeProtectionEnabled
        $result.AntispywareEnabled = $status.AntispywareEnabled
    } catch {
        $result.Notes += "Erro ao consultar Defender: $($_.Exception.Message)"
    }

    return $result
}

$payload = [ordered]@{
    Timestamp = (Get-Date).ToString('s')
    ComputerName = $env:COMPUTERNAME
    Activation = Get-ActivationStatus
    Defender   = Get-DefenderStatus
}

$failures = @()

if ($payload.Activation.IsActivated -isnot [bool]) {
    $failures += 'Activation.IsActivated não é um booleano.'
}

if ($payload.Activation.LicenseStatus -isnot [int] -and $payload.Activation.LicenseStatus -isnot [long]) {
    $failures += 'Activation.LicenseStatus não é numérico.'
}

if ($payload.Defender.CommandAvailable) {
    if ($payload.Defender.RealTimeProtectionEnabled -isnot [bool]) {
        $failures += 'Defender.RealTimeProtectionEnabled não é um booleano.'
    }
} else {
    $payload.Defender.Notes += 'Teste de Defender ignorado porque o cmdlet não está disponível.'
}

if ($Json) {
    $payload | ConvertTo-Json -Depth 6
} else {
    Write-Host "=== Diagnóstico de Ativação do Windows ==="
    $activation = $payload.Activation
    Write-Host ("IsActivated             : {0}" -f $activation.IsActivated)
    Write-Host ("LicenseStatus           : {0}" -f $activation.LicenseStatus)
    if ($activation.LicenseStatusText) {
        Write-Host ("LicenseStatusText       : {0}" -f $activation.LicenseStatusText)
    }
    if ($activation.ProductName) {
        Write-Host ("ProductName             : {0}" -f $activation.ProductName)
    }
    if ($activation.PartialProductKey) {
        Write-Host ("PartialProductKey       : {0}" -f $activation.PartialProductKey)
    }
    if ($activation.Notes.Count -gt 0) {
        Write-Host "Notas:"
        $activation.Notes | ForEach-Object { Write-Host "  - $_" }
    }

    Write-Host ""
    Write-Host "=== Diagnóstico do Windows Defender ==="
    $defender = $payload.Defender
    Write-Host ("Cmdlet disponível       : {0}" -f $defender.CommandAvailable)
    Write-Host ("RealTimeProtection      : {0}" -f $defender.RealTimeProtectionEnabled)
    Write-Host ("AntivirusEnabled        : {0}" -f $defender.AntivirusEnabled)
    Write-Host ("AntispywareEnabled      : {0}" -f $defender.AntispywareEnabled)
    Write-Host ("AMRunningMode           : {0}" -f $defender.AMRunningMode)
    if ($defender.Notes.Count -gt 0) {
        Write-Host "Notas:"
        $defender.Notes | ForEach-Object { Write-Host "  - $_" }
    }

    if ($failures.Count -gt 0) {
        Write-Host ""
        Write-Host "Falhas encontradas:"
        $failures | ForEach-Object { Write-Host "  - $_" }
    } else {
        Write-Host ""
        Write-Host "Status geral: OK"
    }
}

if ($failures.Count -gt 0) {
    exit 1
}
