#Requires -RunAsAdministrator
<#
.SYNOPSIS
    Installs the Togen Print Agent on a Windows host.

.DESCRIPTION
    - Copies print_agent.exe to $InstallDir (default: %ProgramFiles%\Togen\Print)
    - Enrolls the machine with the Togen server using the supplied credential
    - Creates a Scheduled Task that starts the agent at user logon and auto-restarts

    The $Enroll parameter accepts either:
      - An admin-issued enrollment token  -> agent starts ACTIVE immediately
      - The open-enroll shared secret     -> agent starts PENDING; an admin must
                                            approve it in Togen Admin -> Agents ->
                                            Print before its printers are usable.

.PARAMETER Server
    Base URL of the Togen server, e.g. https://togen.example.com

.PARAMETER Enroll
    Enrollment credential - admin token (quick-enroll) or open-enroll shared secret.
    Obtain from the Togen admin panel: Settings -> Togen Admin -> Agents -> Print.

.PARAMETER InstallDir
    Installation directory.  Defaults to %ProgramFiles%\Togen\Print.

.PARAMETER TaskName
    Scheduled Task name.  Defaults to TogenPrintAgent.

.PARAMETER LogDir
    Log file directory.  Defaults to %ProgramData%\Togen\Print\Logs.

.EXAMPLE
    .\install-print.ps1 -Server https://togen.example.com -Enroll eyJh...

.EXAMPLE
    .\install-print.ps1 -Server https://togen.example.com -Enroll tgn-enroll-abc123

.NOTES
    CODE SIGNING: print_agent.exe is unsigned in v1.
    If SmartScreen blocks the exe, run:
        Unblock-File .\print_agent.exe; Unblock-File .\install-print.ps1
    then re-run this installer.
#>
[CmdletBinding(SupportsShouldProcess)]
param(
    [Parameter(Mandatory = $true, HelpMessage = 'Base URL of the Togen server')]
    [ValidatePattern('^https?://')]
    [string]$Server,

    [Parameter(Mandatory = $true, HelpMessage = 'Enrollment credential (admin token or open-enroll secret)')]
    [string]$Enroll,

    [string]$InstallDir = (Join-Path $env:ProgramFiles 'Togen\Print'),
    [string]$TaskName   = 'TogenPrintAgent',
    [string]$LogDir     = (Join-Path $env:ProgramData 'Togen\Print\Logs')
)

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

function Write-Step { param([string]$Msg) Write-Host ">> $Msg" -ForegroundColor Cyan }
function Write-OK   { param([string]$Msg) Write-Host "   OK: $Msg" -ForegroundColor Green }
function Write-Warn { param([string]$Msg) Write-Host "   WARN: $Msg" -ForegroundColor Yellow }

# ---------------------------------------------------------------------------
# 1. Locate source exe (same directory as this script)
# ---------------------------------------------------------------------------
Write-Step 'Locating print_agent.exe'
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
$SourceExe = Join-Path $ScriptDir 'print_agent.exe'
if (-not (Test-Path $SourceExe)) {
    throw "print_agent.exe not found in $ScriptDir - extract the full ZIP next to install-print.ps1."
}
Write-OK "Found: $SourceExe"

# ---------------------------------------------------------------------------
# 2. Unblock files (suppress SmartScreen on the copied exe)
# ---------------------------------------------------------------------------
Write-Step 'Unblocking files'
Unblock-File -Path $SourceExe -ErrorAction SilentlyContinue
Unblock-File -Path $MyInvocation.MyCommand.Definition -ErrorAction SilentlyContinue
Write-OK 'Files unblocked'

# ---------------------------------------------------------------------------
# 3. Create install + log directories, copy exe
# ---------------------------------------------------------------------------
Write-Step "Installing to $InstallDir"
if ($PSCmdlet.ShouldProcess($InstallDir, 'Create directory')) {
    New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
    New-Item -ItemType Directory -Path $LogDir     -Force | Out-Null
}
$DestExe = Join-Path $InstallDir 'print_agent.exe'
if ($PSCmdlet.ShouldProcess($DestExe, 'Copy exe')) {
    Copy-Item -Path $SourceExe -Destination $DestExe -Force
    Unblock-File -Path $DestExe -ErrorAction SilentlyContinue
}
Write-OK "Installed: $DestExe"

# ---------------------------------------------------------------------------
# 4. Enroll (--enroll-only: register and exit, do not start check-in loop)
# ---------------------------------------------------------------------------
Write-Step "Enrolling with Togen server: $Server"
$LogFile  = Join-Path $LogDir 'install-enroll.log'
$proc = Start-Process `
    -FilePath $DestExe `
    -ArgumentList '--server', $Server, '--enroll', $Enroll, '--enroll-only' `
    -Wait -PassThru -NoNewWindow `
    -RedirectStandardOutput $LogFile `
    -RedirectStandardError  (Join-Path $LogDir 'install-enroll-err.log')

# Exit codes: 0 = active, 2 = pending (awaiting admin approval), anything else = error.
switch ($proc.ExitCode) {
    0 {
        Write-OK 'Enrolled and ACTIVE - printers will report once the Scheduled Task starts.'
    }
    2 {
        Write-Warn 'Enrolled as PENDING.'
        Write-Warn 'An admin must approve this machine in Togen Admin -> Agents -> Print.'
        Write-Warn 'The agent will activate automatically after approval; no reinstall needed.'
    }
    default {
        Write-Warn "Enrollment exited with code $($proc.ExitCode). Check: $LogFile"
        Write-Warn 'The Scheduled Task will still be created; re-run with a valid credential if needed.'
    }
}

# ---------------------------------------------------------------------------
# 5. Remove any existing task with the same name
# ---------------------------------------------------------------------------
Write-Step "Registering Scheduled Task: $TaskName"
Unregister-ScheduledTask -TaskName $TaskName -Confirm:$false -ErrorAction SilentlyContinue

# ---------------------------------------------------------------------------
# 6. Create Scheduled Task (at system startup, runs as SYSTEM, auto-restart)
# ---------------------------------------------------------------------------
$LogPath  = Join-Path $LogDir 'agent.log'
$ErrPath  = Join-Path $LogDir 'agent-err.log'

# cmd.exe wrapper so we can redirect stdout/stderr from a console exe.
$WrapCmd  = "cmd.exe"
$WrapArgs = "/C `"$DestExe`" --server `"$Server`" >> `"$LogPath`" 2>> `"$ErrPath`""

$Action   = New-ScheduledTaskAction -Execute $WrapCmd -Argument $WrapArgs -WorkingDirectory $InstallDir
$Trigger  = New-ScheduledTaskTrigger -AtStartup
$Settings = New-ScheduledTaskSettingsSet `
    -ExecutionTimeLimit ([TimeSpan]::Zero) `
    -RestartCount 5 `
    -RestartInterval (New-TimeSpan -Minutes 1) `
    -StartWhenAvailable `
    -MultipleInstances IgnoreNew

# Run as SYSTEM so the agent starts at boot without an interactive session.
# SYSTEM has access to local printers and can reach the Togen server over HTTPS.
$Principal = New-ScheduledTaskPrincipal -UserID "NT AUTHORITY\SYSTEM" -LogonType ServiceAccount -RunLevel Highest

if ($PSCmdlet.ShouldProcess($TaskName, 'Register Scheduled Task')) {
    Register-ScheduledTask `
        -TaskName  $TaskName `
        -Trigger   $Trigger `
        -Action    $Action `
        -Settings  $Settings `
        -Principal $Principal `
        -Force | Out-Null
}
Write-OK "Scheduled Task '$TaskName' created (triggers at startup, runs as SYSTEM)"
Write-OK "Agent logs: $LogPath"

# ---------------------------------------------------------------------------
# 7. Start the agent now (don't wait for next reboot)
# ---------------------------------------------------------------------------
Write-Step 'Starting agent now'
try {
    Start-ScheduledTask -TaskName $TaskName
    Write-OK 'Agent started via Scheduled Task.'
} catch {
    Write-Warn "Could not start the task immediately: $_"
    Write-Warn "The agent will start automatically at next system startup."
}

Write-Host ''
Write-Host 'Installation complete.' -ForegroundColor Green
Write-Host "  Server:  $Server"
Write-Host "  Task:    $TaskName  (runs at startup as SYSTEM, restarts on failure)"
Write-Host "  Logs:    $LogDir"
Write-Host ''
Write-Host 'If this machine registered as PENDING, visit the Togen admin panel' -ForegroundColor Yellow
Write-Host '  -> Settings -> Togen Admin -> Agents -> Print -> Approve this machine.' -ForegroundColor Yellow
