<#
.SYNOPSIS
    Nexus IT Agent - Agente de monitoreo para Windows
.DESCRIPTION
    Recopila información del equipo y la envía a Nexus IT cada 15 minutos.
    No requiere instalación. Se ejecuta como tarea programada.
.NOTES
    Versión: 1.0
    Empresa: Evolucionamos
#>

# ============ CONFIGURACIÓN ============
$NexusURL   = "https://ana.evolucionamos.com/api/agente/heartbeat"
$AgentToken = "##TOKEN##"  # Se reemplaza al generar desde Nexus
$Intervalo  = 15           # Minutos entre envíos
$Version    = "1.0"
# ========================================

# Ignorar errores de certificado SSL si es necesario
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
Add-Type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAll : ICertificatePolicy {
    public bool CheckValidationResult(ServicePoint sp, X509Certificate cert, WebRequest req, int problem) { return true; }
}
"@ -ErrorAction SilentlyContinue
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAll -ErrorAction SilentlyContinue

function Get-SystemInfo {
    $cs = Get-CimInstance Win32_ComputerSystem -ErrorAction SilentlyContinue
    $os = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue
    $cpu = Get-CimInstance Win32_Processor -ErrorAction SilentlyContinue | Select-Object -First 1
    $bios = Get-CimInstance Win32_BIOS -ErrorAction SilentlyContinue
    $disk = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'" -ErrorAction SilentlyContinue
    
    # Red - adaptador activo
    $net = Get-CimInstance Win32_NetworkAdapterConfiguration -Filter "IPEnabled=True" -ErrorAction SilentlyContinue | Select-Object -First 1
    
    # RAM
    $ramTotalGB = [math]::Round($cs.TotalPhysicalMemory / 1GB, 1)
    $ramLibreGB = [math]::Round($os.FreePhysicalMemory / 1MB, 1)
    $ramUsadaGB = [math]::Round($ramTotalGB - $ramLibreGB, 1)
    $ramUsoPct  = [math]::Round(($ramUsadaGB / $ramTotalGB) * 100, 1)
    
    # Disco
    $discoTotalGB = [math]::Round($disk.Size / 1GB, 1)
    $discoLibreGB = [math]::Round($disk.FreeSpace / 1GB, 1)
    $discoUsoPct  = [math]::Round((($discoTotalGB - $discoLibreGB) / $discoTotalGB) * 100, 1)
    
    # CPU
    $cpuUso = (Get-CimInstance Win32_Processor -ErrorAction SilentlyContinue | Measure-Object -Property LoadPercentage -Average).Average
    if ($null -eq $cpuUso) { $cpuUso = 0 }
    
    # Uptime
    $uptime = (Get-Date) - $os.LastBootUpTime
    $uptimeSeconds = [int]$uptime.TotalSeconds
    
    # Procesos
    $procesos = (Get-Process -ErrorAction SilentlyContinue).Count
    
    # Antivirus
    $antivirus = "No detectado"
    try {
        $av = Get-CimInstance -Namespace "root\SecurityCenter2" -ClassName AntiVirusProduct -ErrorAction SilentlyContinue
        if ($av) { $antivirus = ($av | Select-Object -First 1).displayName }
    } catch {}
    
    # Dominio
    $dominio = if ($cs.PartOfDomain) { $cs.Domain } else { "WORKGROUP" }
    
    # Último usuario
    $ultimoUsuario = $cs.UserName
    
    # Tipo de equipo
    $tipo = switch ($cs.PCSystemType) {
        1 { "desktop" }
        2 { "laptop" }
        default { "desktop" }
    }
    # Si es portátil por chassis
    $chassis = (Get-CimInstance Win32_SystemEnclosure -ErrorAction SilentlyContinue).ChassisTypes
    if ($chassis -and ($chassis -contains 9 -or $chassis -contains 10 -or $chassis -contains 14)) { $tipo = "laptop" }
    
    return @{
        agent_token    = $AgentToken
        agent_version  = $Version
        hostname       = $env:COMPUTERNAME
        tipo           = $tipo
        manufacturer   = $cs.Manufacturer
        modelo         = $cs.Model
        serial         = $bios.SerialNumber
        ip             = if ($net.IPAddress) { ($net.IPAddress | Where-Object { $_ -match '^\d+\.\d+\.\d+\.\d+$' } | Select-Object -First 1) } else { "" }
        mac            = $net.MACAddress
        so             = "$($os.Caption) $($os.Version)"
        procesador     = $cpu.Name
        ram_total_gb   = $ramTotalGB
        ram_usada_gb   = $ramUsadaGB
        ram_uso        = $ramUsoPct
        disco_total_gb = $discoTotalGB
        disco_libre_gb = $discoLibreGB
        disco_uso      = $discoUsoPct
        cpu_uso        = [math]::Round($cpuUso, 1)
        uptime_seconds = $uptimeSeconds
        procesos_activos = $procesos
        antivirus      = $antivirus
        dominio        = $dominio
        ultimo_usuario = $ultimoUsuario
    }
}

function Get-InstalledSoftware {
    $software = @()
    $paths = @(
        "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
        "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
    )
    foreach ($path in $paths) {
        Get-ItemProperty $path -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName } | ForEach-Object {
            $software += @{
                nombre  = $_.DisplayName
                version = $_.DisplayVersion
                editor  = $_.Publisher
            }
        }
    }
    # Dedup and sort
    $software = $software | Sort-Object { $_['nombre'] } -Unique
    return $software
}

function Send-Heartbeat {
    try {
        $info = Get-SystemInfo
        $info['software'] = Get-InstalledSoftware
        
        $json = $info | ConvertTo-Json -Depth 3 -Compress
        
        $response = Invoke-RestMethod -Uri $NexusURL -Method POST -Body $json -ContentType "application/json; charset=utf-8" -TimeoutSec 30 -ErrorAction Stop
        
        $ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        if ($response.success) {
            Write-Host "[$ts] OK - Activo ID: $($response.data.activo_id) - Alertas: $($response.data.alertas)"
        } else {
            Write-Host "[$ts] ERROR - $($response.error)"
        }
    } catch {
        $ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        Write-Host "[$ts] ERROR de conexión: $($_.Exception.Message)"
    }
}

# ============ EJECUCIÓN ============
# Si se ejecuta con -Install, registra la tarea programada
if ($args -contains "-Install") {
    $scriptPath = $MyInvocation.MyCommand.Path
    $taskName = "NexusIT-Agent"
    
    # Eliminar tarea existente
    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue
    
    $action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$scriptPath`""
    $trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes $Intervalo) -RepetitionDuration (New-TimeSpan -Days 9999)
    $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -RunOnlyIfNetworkAvailable
    $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest
    
    Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Settings $settings -Principal $principal -Description "Agente de monitoreo Nexus IT" -Force
    
    Write-Host ""
    Write-Host "=== Nexus IT Agent instalado ===" -ForegroundColor Green
    Write-Host "Tarea: $taskName"
    Write-Host "Intervalo: cada $Intervalo minutos"
    Write-Host "Script: $scriptPath"
    Write-Host ""
    Write-Host "Para desinstalar: Unregister-ScheduledTask -TaskName '$taskName' -Confirm:`$false"
    Write-Host ""
    
    # Ejecutar inmediatamente
    Send-Heartbeat
    exit
}

# Si se ejecuta con -Uninstall
if ($args -contains "-Uninstall") {
    Unregister-ScheduledTask -TaskName "NexusIT-Agent" -Confirm:$false -ErrorAction SilentlyContinue
    Write-Host "Nexus IT Agent desinstalado." -ForegroundColor Yellow
    exit
}

# Si se ejecuta con -Test
if ($args -contains "-Test") {
    Write-Host "=== Test Nexus IT Agent ===" -ForegroundColor Cyan
    $info = Get-SystemInfo
    $info.GetEnumerator() | Sort-Object Name | ForEach-Object { Write-Host "  $($_.Key): $($_.Value)" }
    Write-Host ""
    Write-Host "Software instalado: $((Get-InstalledSoftware).Count) programas"
    Write-Host ""
    Write-Host "Enviando heartbeat..."
    Send-Heartbeat
    exit
}

# Ejecución normal (desde tarea programada)
Send-Heartbeat