<#
.SYNOPSIS
    Build the UNIVERSAL RIOJoy deployment zip (PLAN.md §8D): one archive that
    deploys on Windows 10/11 (net48 x64, ViGEmBus) AND Windows XP SP3 (net40
    x86, offline prerequisites). Two install entry points sit at the zip root:
    postinstall.bat (TeslaConsole, unattended, cleans the root after itself)
    and install.bat (standalone computers, adds shortcuts). README.txt at the
    root explains it to a human installer.

.PARAMETER VigemInstaller
    Path to the signed ViGEmBus installer to bundle. If omitted, looks in
    deploy\vendor\ViGEmBus*.exe.
.PARAMETER OutDir
    Where to write the zip (default: dist, relative to the repo root).
.PARAMETER Configuration
    Build configuration (default: Release).

.NOTES
    XP offline prerequisites are picked up from deploy\vendor\xp\ when present
    (dotNetFx40_Full_x86_x64.exe, NDP40-KB2468871-v2-x86.exe, and the
    RioGamepadXP driver once Phase 8B lands); missing ones produce warnings,
    not failures, so modern-only builds still work.
#>
param(
    [string]$VigemInstaller,
    [string]$OutDir = 'dist',
    [string]$Configuration = 'Release'
)

$ErrorActionPreference = 'Stop'
$repo    = Split-Path $PSScriptRoot -Parent        # deploy\ -> repo root
$staging = Join-Path ([IO.Path]::GetTempPath()) "riojoy-pkg-$([Guid]::NewGuid().ToString('N'))"

Write-Host '== RIOJoy deployment package ==' -ForegroundColor Cyan

# --- version stamp --------------------------------------------------------
$sha = (& git -C $repo rev-parse --short HEAD 2>$null)
if (-not $sha) { $sha = 'nogit' }
$version = "{0}-{1}" -f (Get-Date -Format 'yyyyMMdd'), $sha

# --- locate the ViGEmBus installer ----------------------------------------
if (-not $VigemInstaller) {
    $VigemInstaller = Get-ChildItem -Path (Join-Path $PSScriptRoot 'vendor') -Filter 'ViGEmBus*.exe' `
                        -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty FullName
}
if (-not $VigemInstaller -or -not (Test-Path $VigemInstaller)) {
    throw "ViGEmBus installer not found. Pass -VigemInstaller <path>, or drop ViGEmBus_*.exe into deploy\vendor\. Get it from https://github.com/nefarius/ViGEmBus/releases."
}
$sig = Get-AuthenticodeSignature $VigemInstaller
if ($sig.Status -ne 'Valid') { throw "ViGEmBus installer is not validly signed ($($sig.Status)): $VigemInstaller" }
Write-Host "ViGEmBus installer: $(Split-Path $VigemInstaller -Leaf) (signature $($sig.Status))"

try {
    # The payload lives in a 'RIOJoy' folder; postinstall.bat sits beside it at the
    # zip root (TeslaConsole runs it; it calls RIOJoy\install-rio.ps1).
    $pkgDir = Join-Path $staging 'RIOJoy'
    New-Item -ItemType Directory -Force -Path $pkgDir | Out-Null

    # 1. Publish the tray app into RIOJoy\app (net48 x64, framework-dependent — relies
    #    on the in-box .NET Framework 4.8 present on every Windows 10/11 machine).
    $appOut = Join-Path $pkgDir 'app'
    Write-Host "Publishing RioJoy.Tray ($Configuration, net48 x64 framework-dependent)..."
    & dotnet publish (Join-Path $repo 'src\RioJoy.Tray\RioJoy.Tray.csproj') `
        -c $Configuration -f net48 -p:DebugType=none `
        -o $appOut | Out-Null
    if ($LASTEXITCODE -ne 0) { throw 'dotnet publish (net48) failed.' }

    # 1a. Publish the Windows XP flavor into RIOJoy\app-xp (net40 x86,
    #     framework-dependent on the bundled .NET 4.0).
    $appXpOut = Join-Path $pkgDir 'app-xp'
    Write-Host "Publishing RioJoy.Tray ($Configuration, net40 x86 for Windows XP)..."
    & dotnet publish (Join-Path $repo 'src\RioJoy.Tray\RioJoy.Tray.csproj') `
        -c $Configuration -f net40 -p:DebugType=none `
        -o $appXpOut | Out-Null
    if ($LASTEXITCODE -ne 0) { throw 'dotnet publish (net40) failed.' }

    # 1b. Trim native SkiaSharp variants the x64 pod never uses. SkiaSharp's net48
    #     loader finds the native in either the app root or an arch subfolder (both
    #     verified), so we keep only the win-x64 libSkiaSharp.dll at the app root and
    #     drop the x64/x86/arm64 subdir copies and the macOS .dylib (~38 MB).
    $rootSkia = Join-Path $appOut 'libSkiaSharp.dll'
    if (-not (Test-Path $rootSkia)) {
        throw "Expected app\libSkiaSharp.dll (win-x64) before pruning, but it is missing."
    }
    foreach ($d in 'x64', 'x86', 'arm64') {
        $nd = Join-Path $appOut $d
        if (Test-Path $nd) { Remove-Item $nd -Recurse -Force }
    }
    Get-ChildItem $appOut -Filter '*.dylib' -ErrorAction SilentlyContinue | Remove-Item -Force
    Get-ChildItem $appOut -Filter '*.so' -ErrorAction SilentlyContinue | Remove-Item -Force

    # 2. Bundle the signed ViGEmBus installer into RIOJoy\vendor, and the XP
    #    offline prerequisites into RIOJoy\vendor\xp (warn if absent).
    $vendorOut = Join-Path $pkgDir 'vendor'
    New-Item -ItemType Directory -Force -Path $vendorOut | Out-Null
    Copy-Item $VigemInstaller $vendorOut

    $vendorXpSrc = Join-Path $PSScriptRoot 'vendor\xp'
    $vendorXpOut = Join-Path $vendorOut 'xp'
    New-Item -ItemType Directory -Force -Path $vendorXpOut | Out-Null
    $xpWanted = @(
        @{ Name = 'dotNetFx40_Full_x86_x64.exe';   What = '.NET Framework 4.0 offline installer' },
        @{ Name = 'NDP40-KB2468871-v2-x86.exe';    What = '.NET 4.0 update KB2468871 (required by Bcl.Async)' },
        @{ Name = 'RioGamepadXP.inf';              What = 'RioGamepadXP driver INF (Phase 8B)' },
        @{ Name = 'RioGamepadXP.sys';              What = 'RioGamepadXP driver binary (Phase 8B)' },
        @{ Name = 'devcon.exe';                    What = 'devcon (creates the root-enumerated driver devnode on XP)' }
    )
    foreach ($item in $xpWanted) {
        $src = Join-Path $vendorXpSrc $item.Name
        if (Test-Path $src) {
            Copy-Item $src $vendorXpOut
            Write-Host "XP vendor: $($item.Name)"
        } else {
            Write-Warning "XP vendor missing: $($item.Name) - $($item.What). XP installs will warn/skip."
        }
    }

    # 3. Install/uninstall scripts + readmes + version stamp. Payload scripts in
    #    RIOJoy\; the two entry points (postinstall.bat, install.bat) and the
    #    human README at the zip root (postinstall.bat deletes install.bat +
    #    README.txt after a cabinet deploy to keep C:\games clean).
    Copy-Item (Join-Path $PSScriptRoot 'install-rio.ps1')    $pkgDir
    Copy-Item (Join-Path $PSScriptRoot 'uninstall-rio.ps1')  $pkgDir
    Copy-Item (Join-Path $PSScriptRoot 'pre-uninstall.bat')  $pkgDir
    Copy-Item (Join-Path $PSScriptRoot 'install-core.bat')   $pkgDir
    Copy-Item (Join-Path $PSScriptRoot 'make-shortcut.vbs')  $pkgDir
    Copy-Item (Join-Path $PSScriptRoot 'README-DEPLOY.txt')  $pkgDir
    Set-Content -Path (Join-Path $pkgDir 'VERSION.txt') -Value "RIOJoy $version" -Encoding utf8
    Copy-Item (Join-Path $PSScriptRoot 'postinstall.bat')   $staging
    Copy-Item (Join-Path $PSScriptRoot 'install.bat')       $staging
    Copy-Item (Join-Path $PSScriptRoot 'README.txt')        $staging

    # 4. Zip the package contents (so it extracts straight into C:\games\RIOJOY).
    $outDirFull = if ([IO.Path]::IsPathRooted($OutDir)) { $OutDir } else { Join-Path $repo $OutDir }
    New-Item -ItemType Directory -Force -Path $outDirFull | Out-Null
    $zip = Join-Path $outDirFull "RIOJoy-$version.zip"
    if (Test-Path $zip) { Remove-Item $zip -Force }
    Write-Host "Zipping -> $zip"
    # Build entries by hand with forward-slash names: both Compress-Archive and
    # ZipFile.CreateFromDirectory write BACKSLASH separators under Windows PowerShell
    # (.NET Framework), which some extractors mishandle. Entries are relative to the
    # staging root, so the zip extracts straight into the target (C:\games\RIOJOY\...).
    Add-Type -AssemblyName System.IO.Compression
    Add-Type -AssemblyName System.IO.Compression.FileSystem
    $base = (Resolve-Path $staging).Path.TrimEnd('\') + '\'
    $fs = [System.IO.File]::Open($zip, [System.IO.FileMode]::CreateNew)
    try {
        $archive = New-Object System.IO.Compression.ZipArchive($fs, [System.IO.Compression.ZipArchiveMode]::Create)
        try {
            foreach ($file in Get-ChildItem -Path $staging -Recurse -File) {
                $entryName = $file.FullName.Substring($base.Length) -replace '\\', '/'
                [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile(
                    $archive, $file.FullName, $entryName,
                    [System.IO.Compression.CompressionLevel]::Optimal) | Out-Null
            }
        } finally { $archive.Dispose() }
    } finally { $fs.Dispose() }

    $size = '{0:N1} MB' -f ((Get-Item $zip).Length / 1MB)
    Write-Host ''
    Write-Host "Package built: $zip ($size)" -ForegroundColor Green
    Write-Host 'Deploy: extract (postinstall.bat + riojoy\), then run postinstall.bat (elevated).'
}
finally {
    if (Test-Path $staging) { Remove-Item $staging -Recurse -Force }
}
