@echo off
setlocal
set "RUSTDEV_LAUNCHER=%~f0"

if /I "%~1"=="--worker" goto :worker
if /I "%~1"=="--elevated" goto :ui

powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -Command "$id=[Security.Principal.WindowsIdentity]::GetCurrent(); $p=New-Object Security.Principal.WindowsPrincipal($id); if ($p.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { exit 0 } else { Start-Process -FilePath $env:ComSpec -ArgumentList '/d','/c',('""{0}" --elevated"' -f $env:RUSTDEV_LAUNCHER) -Verb RunAs; exit 10 }"
if %errorlevel%==10 exit /b 0
if errorlevel 1 exit /b %errorlevel%

:ui
start "" powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -Command "$lines=Get-Content -LiteralPath $env:RUSTDEV_LAUNCHER; $a='#==RUSTDEV_UI_PAYLOAD=='; $b='#==RUSTDEV_WORKER_PAYLOAD=='; $i=[Array]::IndexOf($lines,$a); $j=[Array]::IndexOf($lines,$b); if($i -lt 0 -or $j -le $i){exit 2}; $code=($lines[($i+1)..($j-1)] -join [Environment]::NewLine); & ([ScriptBlock]::Create($code))"
exit /b 0

:worker
powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command "$lines=Get-Content -LiteralPath $env:RUSTDEV_LAUNCHER; $m='#==RUSTDEV_WORKER_PAYLOAD=='; $i=[Array]::IndexOf($lines,$m); if($i -lt 0){exit 2}; $code=($lines[($i+1)..($lines.Count-1)] -join [Environment]::NewLine); & ([ScriptBlock]::Create($code))"
exit /b %errorlevel%

#==RUSTDEV_UI_PAYLOAD==
$ErrorActionPreference = "Stop"

Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationCore
Add-Type -AssemblyName WindowsBase

$LauncherPath = $env:RUSTDEV_LAUNCHER
$WorkDir = Join-Path $env:ProgramData "RustDEV"
$LogPath = Join-Path $WorkDir "provision.log"

New-Item -ItemType Directory -Force -Path $WorkDir | Out-Null
Remove-Item -LiteralPath $LogPath -Force -ErrorAction SilentlyContinue

[xml]$xaml = @"
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="LMX Assistenza Remota"
        Width="640"
        SizeToContent="Height"
        WindowStartupLocation="CenterScreen"
        ResizeMode="NoResize"
        Background="#F4F7F7"
        FontFamily="Segoe UI"
        ShowInTaskbar="True">
    <Grid>
        <Border Margin="22" Padding="28" Background="White" CornerRadius="12">
            <Border.Effect>
                <DropShadowEffect BlurRadius="18" ShadowDepth="2" Opacity="0.12"/>
            </Border.Effect>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="22"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>

                <TextBlock Grid.Row="0"
                           Text="LMX Assistenza Remota"
                           FontSize="26"
                           FontWeight="SemiBold"
                           Foreground="#17333A"/>

                <TextBlock Grid.Row="1"
                           Margin="0,5,0,0"
                           Text="Configurazione sicura del supporto remoto"
                           FontSize="13"
                           Foreground="#65757A"/>

                <ProgressBar x:Name="Progress"
                             Grid.Row="2"
                             Margin="0,18,0,0"
                             Height="6"
                             IsIndeterminate="True"/>

                <TextBlock x:Name="StatusText"
                           Grid.Row="3"
                           Margin="0,22,0,0"
                           Text="Preparazione della configurazione..."
                           TextWrapping="Wrap"
                           FontSize="18"
                           FontWeight="SemiBold"
                           Foreground="#17333A"/>

                <TextBlock x:Name="DetailText"
                           Grid.Row="4"
                           Margin="0,8,0,0"
                           Text="Attendere il completamento dell'operazione."
                           TextWrapping="Wrap"
                           FontSize="13"
                           Foreground="#65757A"/>

                <Border x:Name="ClaimBox"
                        Grid.Row="5"
                        Margin="0,20,0,0"
                        Padding="16"
                        Background="#EEF7F6"
                        BorderBrush="#CDE8E4"
                        BorderThickness="1"
                        CornerRadius="8"
                        Visibility="Collapsed">
                    <StackPanel>
                        <TextBlock Text="Codice autorizzazione"
                                   FontSize="12"
                                   FontWeight="SemiBold"
                                   Foreground="#52716F"/>
                        <TextBlock x:Name="ClaimText"
                                   Margin="0,6,0,0"
                                   TextWrapping="Wrap"
                                   FontFamily="Consolas"
                                   FontSize="15"
                                   Foreground="#17333A"/>
                    </StackPanel>
                </Border>

                <Grid Grid.Row="6" Margin="0,20,0,0">
                    <Border x:Name="ErrorBox"
                            Padding="14"
                            Background="#FFF4F3"
                            BorderBrush="#F0C9C4"
                            BorderThickness="1"
                            CornerRadius="8"
                            Visibility="Collapsed">
                        <TextBlock x:Name="ErrorText"
                                   TextWrapping="Wrap"
                                   FontSize="12"
                                   Foreground="#8A3027"/>
                    </Border>

                    <Button x:Name="CloseButton"
                            Width="96"
                            Height="32"
                            HorizontalAlignment="Right"
                            Content="Chiudi"
                            Visibility="Collapsed"/>
                </Grid>
            </Grid>
        </Border>
    </Grid>
</Window>
"@

$reader = New-Object System.Xml.XmlNodeReader $xaml
$window = [Windows.Markup.XamlReader]::Load($reader)

$progress = $window.FindName("Progress")
$statusText = $window.FindName("StatusText")
$detailText = $window.FindName("DetailText")
$claimBox = $window.FindName("ClaimBox")
$claimText = $window.FindName("ClaimText")
$errorBox = $window.FindName("ErrorBox")
$errorText = $window.FindName("ErrorText")
$closeButton = $window.FindName("CloseButton")

$script:AllowClose = $false
$script:SuccessAt = $null
$script:LastLog = ""

$window.Add_Closing({
    param($sender, $e)
    if (-not $script:AllowClose) {
        $e.Cancel = $true
    }
})

$closeButton.Add_Click({
    $script:AllowClose = $true
    $window.Close()
})

$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $env:ComSpec
$psi.Arguments = ('/d /c ""{0}" --worker"' -f $LauncherPath)
$psi.UseShellExecute = $false
$psi.CreateNoWindow = $true
$worker = [System.Diagnostics.Process]::Start($psi)

function Update-FromLog {
    if (-not (Test-Path -LiteralPath $LogPath)) {
        return
    }

    $lines = @(Get-Content -LiteralPath $LogPath -ErrorAction SilentlyContinue)
    if ($lines.Count -eq 0) {
        return
    }

    $joined = $lines -join "`n"
    if ($joined -eq $script:LastLog) {
        return
    }
    $script:LastLog = $joined

    foreach ($line in $lines) {
        if ($line -match 'Claim ID:\s*([0-9a-fA-F-]{36})') {
            $claimText.Text = $matches[1]
            $claimBox.Visibility = "Visible"
        }
    }

    if ($joined -match "RustDesk gia' installato: riprovisioning") {
        $statusText.Text = "Aggiornamento della configurazione..."
        $detailText.Text = "Verifica del componente di assistenza remota gia' installato."
    }
    if ($joined -match 'Download RustDesk') {
        $statusText.Text = "Download del componente remoto..."
        $detailText.Text = "Verifica e preparazione del pacchetto di installazione."
    }
    if ($joined -match 'Installazione silenziosa MSI') {
        $statusText.Text = "Installazione in corso..."
        $detailText.Text = "Installazione del componente di assistenza remota."
    }
    if ($joined -match 'Applicazione configurazione RustDEV') {
        $statusText.Text = "Configurazione del supporto remoto..."
        $detailText.Text = "Applicazione delle impostazioni LMX."
    }
    if ($joined -match 'ID RustDesk recuperato') {
        $statusText.Text = "Registrazione del dispositivo..."
        $detailText.Text = "Preparazione della richiesta di autorizzazione."
    }
    if ($joined -match 'Richiesta bootstrap creata') {
        $statusText.Text = "In attesa di autorizzazione..."
        $detailText.Text = "La richiesta e' stata inviata a LMX."
    }
    if ($joined -match 'Bootstrap autorizzato') {
        $statusText.Text = "Autorizzazione ricevuta."
        $detailText.Text = "Completamento della registrazione del dispositivo."
    }
    if ($joined -match 'Enrollment RustDEV completato') {
        $statusText.Text = "Finalizzazione..."
        $detailText.Text = "La configurazione e' quasi completata."
    }
    if ($joined -match 'ERRORE:\s*(.+)') {
        $statusText.Text = "Configurazione non completata."
        $detailText.Text = "Si e' verificato un errore durante la configurazione."
        $errorText.Text = $matches[1] + "`nDettagli tecnici: " + $LogPath
        $errorBox.Visibility = "Visible"
    }
}

$timer = New-Object Windows.Threading.DispatcherTimer
$timer.Interval = [TimeSpan]::FromMilliseconds(350)
$timer.Add_Tick({
    Update-FromLog

    if ($worker.HasExited) {
        if ($worker.ExitCode -eq 0) {
            if ($null -eq $script:SuccessAt) {
                $progress.IsIndeterminate = $false
                $progress.Value = 100
                $claimBox.Visibility = "Collapsed"
                $errorBox.Visibility = "Collapsed"
                $statusText.Text = "Configurazione completata."
                $detailText.Text = "LMX Assistenza Remota e' pronta all'uso."
                $script:SuccessAt = [DateTime]::UtcNow
            }
            elseif (([DateTime]::UtcNow - $script:SuccessAt).TotalSeconds -ge 2) {
                $timer.Stop()
                $script:AllowClose = $true
                $window.Close()
            }
        }
        else {
            $timer.Stop()
            $progress.IsIndeterminate = $false
            $progress.Value = 0
            if ($errorBox.Visibility -ne "Visible") {
                $statusText.Text = "Configurazione non completata."
                $detailText.Text = "Il processo di configurazione si e' interrotto."
                $errorText.Text = "Consultare il log tecnico: " + $LogPath
                $errorBox.Visibility = "Visible"
            }
            $closeButton.Visibility = "Visible"
            $script:AllowClose = $true
        }
    }
})

$window.Add_ContentRendered({
    $timer.Start()
})

[void]$window.ShowDialog()

if (-not $worker.HasExited) {
    try {
        $worker.Kill()
    }
    catch {
    }
}
$worker.Dispose()

#==RUSTDEV_WORKER_PAYLOAD==
$ErrorActionPreference = "Stop"

# Disabilita QuickEdit solo per la console corrente. In questo modo una
# selezione accidentale del testo non puo' sospendere visivamente la console
# durante il provisioning. Nessuna impostazione globale di Windows viene
# modificata; la console viene distrutta alla chiusura del launcher.
try {
    if (-not ("RustDev.ConsoleMode" -as [type])) {
        Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
namespace RustDev {
    public static class ConsoleMode {
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr GetStdHandle(int nStdHandle);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetConsoleMode(IntPtr hConsoleHandle, out uint lpMode);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
    }
}
"@
    }

    $stdInputHandle = [RustDev.ConsoleMode]::GetStdHandle(-10)
    [uint32]$consoleMode = 0
    if ([RustDev.ConsoleMode]::GetConsoleMode($stdInputHandle, [ref]$consoleMode)) {
        $ENABLE_QUICK_EDIT_MODE = [uint32]0x0040
        $ENABLE_EXTENDED_FLAGS = [uint32]0x0080
        $consoleMode = ($consoleMode -bor $ENABLE_EXTENDED_FLAGS) -band (-bnot $ENABLE_QUICK_EDIT_MODE)
        [void][RustDev.ConsoleMode]::SetConsoleMode($stdInputHandle, $consoleMode)
    }
}
catch {
    # La disabilitazione di QuickEdit e' una protezione UI; non deve bloccare
    # il provisioning se l'host console non espone le API classiche.
}

# RustDEV - provisioning automatico Windows
# Installa/configura RustDesk OSS 1.4.9 e registra automaticamente
# l'endpoint nel backend RustDEV tramite bootstrap + enrollment HTTPS.

$RustDeskVersion = "1.4.9"
$Server = "repositoryn.synology.me"
$PublicKey = "412pDbaqaZs3pZWgoHjoX2oscoYKcQrosiGRNxX6BWs="
$MsiUrl = "https://github.com/rustdesk/rustdesk/releases/download/1.4.9/rustdesk-1.4.9-x86_64.msi"
$MsiSha256 = "c87d2f4cef2a5acd6003b6507dcfbf5d5168a256db082cd90b54d35193224aaa"

$EnrollmentBaseUrl = "https://assistenza.lmxnet.it"
$BootstrapPollSeconds = 3
$BootstrapTimeoutSeconds = 900

$WorkDir = Join-Path $env:ProgramData "RustDEV"
$MsiPath = Join-Path $WorkDir "rustdesk-$RustDeskVersion-x86_64.msi"
$LogPath = Join-Path $WorkDir "provision.log"
$ResultPath = Join-Path $WorkDir "provision-result.txt"

function Write-Log {
    param([string]$Message)
    $line = "{0}  {1}" -f (Get-Date -Format "yyyy-MM-dd HH:mm:ss"), $Message
    Add-Content -Path $LogPath -Value $line
}

function Fail {
    param([string]$Message)
    Write-Log "ERRORE: $Message"
    exit 1
}

function Invoke-RustDeskOption {
    param(
        [string]$Name,
        [string]$Value
    )
    & $script:RustDeskExe --option $Name $Value | Out-Null
    Start-Sleep -Milliseconds 500
}

function New-RandomBase64Url {
    param([int]$ByteCount)

    $bytes = New-Object byte[] $ByteCount
    $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
    try {
        $rng.GetBytes($bytes)
        return [Convert]::ToBase64String($bytes).TrimEnd("=").Replace("+", "-").Replace("/", "_")
    }
    finally {
        [Array]::Clear($bytes, 0, $bytes.Length)
        $rng.Dispose()
    }
}

function Get-Sha256Hex {
    param([string]$Value)

    $bytes = [Text.Encoding]::UTF8.GetBytes($Value)
    $sha = [System.Security.Cryptography.SHA256]::Create()
    try {
        $hash = $sha.ComputeHash($bytes)
        return ([BitConverter]::ToString($hash)).Replace("-", "").ToLowerInvariant()
    }
    finally {
        [Array]::Clear($bytes, 0, $bytes.Length)
        if ($null -ne $hash) {
            [Array]::Clear($hash, 0, $hash.Length)
        }
        $sha.Dispose()
    }
}

function Invoke-RustDevJson {
    param(
        [ValidateSet("GET", "POST")]
        [string]$Method,
        [string]$Uri,
        [object]$Body = $null
    )

    $params = @{
        Uri = $Uri
        Method = $Method
        UseBasicParsing = $true
        TimeoutSec = 30
    }

    $json = $null
    if ($null -ne $Body) {
        $json = $Body | ConvertTo-Json -Compress -Depth 4
        $params["ContentType"] = "application/json"
        $params["Body"] = $json
    }

    try {
        $response = Invoke-WebRequest @params
    }
    finally {
        $json = $null
        $params.Remove("Body") | Out-Null
    }

    $data = $null
    if (-not [string]::IsNullOrWhiteSpace($response.Content)) {
        $data = $response.Content | ConvertFrom-Json
    }

    return [PSCustomObject]@{
        StatusCode = [int]$response.StatusCode
        Data = $data
    }
}


New-Item -ItemType Directory -Force -Path $WorkDir | Out-Null
Set-Content -Path $LogPath -Value "RustDEV - provisioning Windows"

Clear-Host
Write-Host "RustDEV"
Write-Host ""
Write-Host "Configurazione del supporto remoto in corso..."
Write-Host "Non chiudere questa finestra."
Write-Host ""

Write-Log "Avvio provisioning."
Write-Log "Computer: $env:COMPUTERNAME"

$existingExe = Join-Path $env:ProgramFiles "RustDesk\rustdesk.exe"

if (Test-Path $existingExe) {
    $script:RustDeskExe = $existingExe
    Write-Log "RustDesk gia' installato: riprovisioning."
}
else {
    try {
        [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
        Write-Log "Download RustDesk $RustDeskVersion."
        Invoke-WebRequest -Uri $MsiUrl -OutFile $MsiPath -UseBasicParsing
    }
    catch {
        Fail "Download MSI non riuscito: $($_.Exception.Message)"
    }

    $actualHash = (Get-FileHash -Path $MsiPath -Algorithm SHA256).Hash.ToLowerInvariant()
    if ($actualHash -ne $MsiSha256) {
        Fail "Checksum SHA256 MSI non valido."
    }
    Write-Log "Checksum MSI verificato."

    Write-Log "Installazione silenziosa MSI."
    $msiArgs = @(
        "/i", "`"$MsiPath`"",
        "/qn",
        "/norestart",
        "CREATESTARTMENUSHORTCUTS=Y",
        "CREATEDESKTOPSHORTCUTS=N",
        "INSTALLPRINTER=N",
        "/l*v", "`"$WorkDir\rustdesk-msi.log`""
    )
    $proc = Start-Process -FilePath "msiexec.exe" -ArgumentList $msiArgs -Wait -PassThru
    if ($proc.ExitCode -notin 0, 3010) {
        Fail "Installazione MSI fallita. Exit code: $($proc.ExitCode)"
    }

    $script:RustDeskExe = Join-Path $env:ProgramFiles "RustDesk\rustdesk.exe"
    $deadline = (Get-Date).AddSeconds(30)
    while (-not (Test-Path $script:RustDeskExe) -and (Get-Date) -lt $deadline) {
        Start-Sleep -Seconds 1
    }
    if (-not (Test-Path $script:RustDeskExe)) {
        Fail "rustdesk.exe non trovato dopo l'installazione."
    }
    Write-Log "RustDesk installato."
}

$service = Get-Service -Name "RustDesk" -ErrorAction SilentlyContinue
if (-not $service) {
    Fail "Servizio RustDesk non trovato dopo l'installazione."
}
if ($service.Status -ne "Running") {
    Start-Service -Name "RustDesk"
    Start-Sleep -Seconds 3
}
Write-Log "Servizio RustDesk attivo."

Write-Log "Applicazione configurazione RustDEV."
Invoke-RustDeskOption "custom-rendezvous-server" $Server
Invoke-RustDeskOption "key" $PublicKey
Invoke-RustDeskOption "approve-mode" "password"
Invoke-RustDeskOption "verification-method" "use-permanent-password"

$serverCheck = (& $script:RustDeskExe --option custom-rendezvous-server | Out-String).Trim()
$keyCheck = (& $script:RustDeskExe --option key | Out-String).Trim()
$approveCheck = (& $script:RustDeskExe --option approve-mode | Out-String).Trim()
$verificationCheck = (& $script:RustDeskExe --option verification-method | Out-String).Trim()

if ($serverCheck -ne $Server) { Fail "Verifica ID Server fallita." }
if ($keyCheck -ne $PublicKey) { Fail "Verifica chiave pubblica fallita." }
if ($approveCheck -ne "password") { Fail "Verifica approve-mode fallita." }
if ($verificationCheck -ne "use-permanent-password") { Fail "Verifica verification-method fallita." }

Write-Log "Configurazione RustDEV verificata."

Restart-Service -Name "RustDesk" -Force
Start-Sleep -Seconds 5
Write-Log "Servizio RustDesk riavviato."

# Manteniamo la sequenza gia' validata nel PoC: la password permanente
# viene impostata subito dopo la configurazione/riavvio del servizio.
$password = New-RandomBase64Url -ByteCount 18

& $script:RustDeskExe --password $password | Out-Null
Start-Sleep -Seconds 2
Write-Log "Password permanente per-dispositivo impostata."

$id = ""
$deadline = (Get-Date).AddSeconds(30)
while ([string]::IsNullOrWhiteSpace($id) -and (Get-Date) -lt $deadline) {
    $id = (& $script:RustDeskExe --get-id | Out-String).Trim()
    if ([string]::IsNullOrWhiteSpace($id)) {
        Start-Sleep -Seconds 2
    }
}
if ([string]::IsNullOrWhiteSpace($id)) {
    Fail "Recupero ID RustDesk non riuscito."
}
Write-Log "ID RustDesk recuperato."

# Il token nasce sul client, resta solo in memoria e durante il bootstrap
# viene inviato al backend esclusivamente come SHA-256.
$token = New-RandomBase64Url -ByteCount 32
$tokenHash = Get-Sha256Hex -Value $token

try {
    $bootstrapResponse = Invoke-RustDevJson -Method "POST" -Uri "$EnrollmentBaseUrl/bootstrap" -Body @{
        hostname = $env:COMPUTERNAME
        token_hash = $tokenHash
    }
}
catch {
    $token = $null
    $tokenHash = $null
    Fail "Richiesta bootstrap HTTPS non riuscita."
}
$tokenHash = $null

if ($bootstrapResponse.StatusCode -notin 200, 201) {
    $token = $null
    Fail "Il backend ha rifiutato la richiesta bootstrap."
}

$claimId = [string]$bootstrapResponse.Data.claim_id
$bootstrapStatus = [string]$bootstrapResponse.Data.status
if ([string]::IsNullOrWhiteSpace($claimId)) {
    $token = $null
    Fail "Risposta bootstrap priva di claim_id."
}

Write-Log "Richiesta bootstrap creata."
Write-Log "Claim ID: $claimId"
Write-Host ""
Write-Host "Richiesta RustDEV inviata."
Write-Host "Claim ID: $claimId"

if ($bootstrapStatus -eq "expired") {
    $token = $null
    Fail "La richiesta bootstrap risulta gia' scaduta."
}

if ($bootstrapStatus -ne "approved") {
    Write-Host "In attesa di autorizzazione..."
    $bootstrapDeadline = (Get-Date).AddSeconds($BootstrapTimeoutSeconds)

    do {
        Start-Sleep -Seconds $BootstrapPollSeconds

        try {
            $statusResponse = Invoke-RustDevJson -Method "GET" -Uri "$EnrollmentBaseUrl/bootstrap/$claimId"
        }
        catch {
            $token = $null
            Fail "Verifica stato bootstrap HTTPS non riuscita."
        }

        if ($statusResponse.StatusCode -ne 200) {
            $token = $null
            Fail "Verifica stato bootstrap rifiutata dal backend."
        }

        $bootstrapStatus = [string]$statusResponse.Data.status

        if ($bootstrapStatus -eq "expired") {
            $token = $null
            Fail "Richiesta bootstrap scaduta prima dell'autorizzazione."
        }

        if ($bootstrapStatus -notin "pending", "approved") {
            $token = $null
            Fail "Stato bootstrap non valido."
        }
    }
    while ($bootstrapStatus -ne "approved" -and (Get-Date) -lt $bootstrapDeadline)

    if ($bootstrapStatus -ne "approved") {
        $token = $null
        Fail "Timeout in attesa dell'autorizzazione RustDEV."
    }
}

Write-Log "Bootstrap autorizzato."

try {
    $enrollResponse = Invoke-RustDevJson -Method "POST" -Uri "$EnrollmentBaseUrl/enroll" -Body @{
        token = $token
        hostname = $env:COMPUTERNAME
        rustdesk_id = $id
        password = $password
    }
}
catch {
    $token = $null
    $password = $null
    Fail "Enrollment HTTPS non riuscito."
}
finally {
    $token = $null
    $password = $null
}

if ($enrollResponse.StatusCode -ne 201 -or [string]$enrollResponse.Data.status -ne "registered") {
    Fail "Il backend ha rifiutato l'enrollment del dispositivo."
}

$deviceId = [string]$enrollResponse.Data.device_id
$deviceStatus = [string]$enrollResponse.Data.device_status
if ([string]::IsNullOrWhiteSpace($deviceId)) {
    Fail "Risposta enrollment priva di device_id."
}

Write-Log "Enrollment RustDEV completato."
Write-Log "Provisioning completato."

$result = @"
RUSTDEV - provisioning completato

Computer: $env:COMPUTERNAME
RustDesk ID: $id
Device ID: $deviceId
Stato dispositivo: $deviceStatus
ID Server: $Server

La password unattended e il token di enrollment non sono salvati in questo file.
"@

Set-Content -Path $ResultPath -Value $result -Encoding UTF8

Write-Host ""
Write-Host "Configurazione completata."
Start-Sleep -Seconds 2
