<#
.SYNOPSIS
  Pomar Rack - Windows diagnostics (RACK-105). Reports the real machine state so the dev can analyse it.

.DESCRIPTION
  Gathers: OS + environment, the VST3 plugin locations, the NKS/preset discovery roots (mirroring
  DiscoveryRoots.cpp) with existence + file counts, runs a library refresh and captures topo-refresh's
  own summary, then inspects the resulting TopoLibrary (index sizes + entry counts). Writes everything to
  a single text file you can copy + paste back.

  Run via Diagnose.cmd (double-click), or:
    powershell -ExecutionPolicy Bypass -File .\Diagnose.ps1
#>
[CmdletBinding()]
param(
  [string] $RefreshExe = "",
  [string] $LibraryRoot = (Join-Path $env:USERPROFILE "TopoLibrary"),
  [string] $OutFile = (Join-Path $env:USERPROFILE "topo-diagnostics.txt"),
  [switch] $NoRefresh   # skip running topo-refresh; just report current state
)
$ErrorActionPreference = "Continue"

if (-not $RefreshExe) {
  $RefreshExe = @("$PSScriptRoot\topo-refresh.exe") | Where-Object { Test-Path $_ } | Select-Object -First 1
  if (-not $RefreshExe) { $RefreshExe = "topo-refresh" } # PATH
}

$lines = New-Object System.Collections.Generic.List[string]
function W($s)       { $lines.Add([string]$s) | Out-Null }
function Section($t) { W ""; W ("=" * 70); W $t; W ("=" * 70) }
function CountFiles($dir, $patterns) {
  if (-not (Test-Path $dir)) { return -1 }
  try { return @(Get-ChildItem -Path $dir -Recurse -File -Include $patterns -ErrorAction SilentlyContinue).Count }
  catch { return -1 }
}

Section "TOPO RACK DIAGNOSTICS"
W ("generated      : " + (Get-Date -Format s))
try { W ("OS             : " + (Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).Caption) } catch {}
W ("OS version     : " + [Environment]::OSVersion.Version)
W ("PowerShell     : " + $PSVersionTable.PSVersion)
W ("script dir     : " + $PSScriptRoot)
$appExe = Join-Path $PSScriptRoot "Pomar Rack.exe"
W ("Pomar Rack.exe  : " + $(if (Test-Path $appExe)     { "{0} bytes" -f (Get-Item $appExe).Length }     else { "NOT next to script" }))
W ("topo-refresh   : " + $RefreshExe + "  " + $(if (Test-Path $RefreshExe) { "[{0} bytes]" -f (Get-Item $RefreshExe).Length } else { "[NOT FOUND]" }))

Section "ENVIRONMENT"
foreach ($v in 'USERPROFILE','PUBLIC','ProgramData','APPDATA','LOCALAPPDATA','CommonProgramFiles','ProgramFiles') {
  W ("{0,-19}= {1}" -f $v, [Environment]::GetEnvironmentVariable($v))
}

Section "VST3 PLUGIN LOCATIONS"
$vst3dirs = @((Join-Path $env:CommonProgramFiles "VST3"))
if (${env:CommonProgramFiles(x86)}) { $vst3dirs += (Join-Path ${env:CommonProgramFiles(x86)} "VST3") }
foreach ($d in $vst3dirs) {
  $n = CountFiles $d @('*.vst3')
  W ($(if ($n -ge 0) { "[EXISTS]  {0}   ({1} .vst3)" -f $d,$n } else { "[missing] {0}" -f $d }))
}

Section "NKS / PRESET DISCOVERY ROOTS  (mirrors DiscoveryRoots.cpp Windows table)"
$roots = @(
  (Join-Path $env:USERPROFILE "Documents\Native Instruments"),
  (Join-Path $env:PUBLIC      "Documents\Native Instruments"),
  (Join-Path $env:ProgramData "Native Instruments"),
  (Join-Path $env:ProgramData "Arturia"),
  (Join-Path $env:APPDATA     "Arturia"),
  (Join-Path $env:USERPROFILE "Documents\u-he"),
  (Join-Path $env:ProgramData "u-he")
)
foreach ($d in $roots) {
  $n = CountFiles $d @('*.nksf','*.nksfx')
  W ($(if ($n -ge 0) { "[EXISTS]  {0}   ({1} nks files)" -f $d,$n } else { "[missing] {0}" -f $d }))
}

Section "ASSET / ART ROOTS  (where card art is imported from)"
$artRoots = @(
  (Join-Path $env:PUBLIC      "NI Resources\image"),
  (Join-Path $env:USERPROFILE "Documents\Native Instruments\NI Resources\image"),
  (Join-Path $env:ProgramData "Arturia"),
  (Join-Path $env:APPDATA     "Arturia")
)
foreach ($d in $artRoots) {
  $n = CountFiles $d @('*.png','*.jpg','*.jpeg')
  W ($(if ($n -ge 0) { "[EXISTS]  {0}   ({1} images)" -f $d,$n } else { "[missing] {0}" -f $d }))
}

Section "VENDOR ART LAYOUT  (directory sample - shows how art is structured on Windows)"
function SampleTree($root, $depth, $max) {
  if (-not (Test-Path $root)) { W ("(missing) " + $root); return }
  W ("under " + $root + " :")
  $items = Get-ChildItem -Path $root -Recurse -Depth $depth -Directory -ErrorAction SilentlyContinue | Select-Object -First $max
  foreach ($it in $items) { W ("  " + $it.FullName.Substring($root.Length)) }
  if (-not $items) { W "  (no subdirectories)" }
}
SampleTree (Join-Path $env:ProgramData "Arturia") 2 25
SampleTree (Join-Path $env:USERPROFILE "Documents\Native Instruments\NI Resources\image") 2 25

if (-not $NoRefresh) {
  Section "RUNNING topo-refresh  (scans your VST3s - may take a minute)"
  if (Test-Path $RefreshExe) {
    W ("> " + $RefreshExe + ' "' + $LibraryRoot + '"')
    $out = & $RefreshExe $LibraryRoot 2>&1
    foreach ($o in $out) { W ("  " + $o) }
    W ("exit code      : " + $LASTEXITCODE)
  } else { W "topo-refresh.exe not found next to this script - skipped." }
}

Section "LIBRARY STATE  ($LibraryRoot)"
if (Test-Path $LibraryRoot) {
  W "[EXISTS]"
  foreach ($rel in 'index\browser-index.json','index\plugin-index.json','registry\plugins.json') {
    $f = Join-Path $LibraryRoot $rel
    if (Test-Path $f) {
      $size = (Get-Item $f).Length
      $count = "?"
      try {
        $j = Get-Content $f -Raw | ConvertFrom-Json
        if ($j -is [array]) { $count = $j.Count } elseif ($j.cards) { $count = $j.cards.Count }
        elseif ($j.plugins) { $count = $j.plugins.Count } else { $count = "n/a" }
      } catch { $count = "(parse error)" }
      W ("  {0,-28} {1,9} bytes   {2} entries" -f $rel, $size, $count)
    } else { W ("  {0,-28} MISSING" -f $rel) }
  }
  W ("  assets\plugins\*.png         {0} images" -f (CountFiles (Join-Path $LibraryRoot "assets\plugins") @('*.png')))
  $mani = Join-Path $LibraryRoot "assets\manifest.json"
  if (Test-Path $mani) { W ("  assets\manifest.json         {0,9} bytes" -f (Get-Item $mani).Length) } else { W "  assets\manifest.json         MISSING" }
  W ("  presets\*.json               {0} files"  -f (CountFiles (Join-Path $LibraryRoot "presets") @('*.json')))
} else {
  W "[MISSING] - the library was not created. See the refresh output above for the error / exit code."
}

Section "END"
$lines | Set-Content -Path $OutFile -Encoding UTF8
$lines | ForEach-Object { Write-Host $_ }
Write-Host ""
Write-Host "Diagnostics written to: $OutFile" -ForegroundColor Green
Write-Host "Open it, copy everything, and paste it back to the dev for analysis." -ForegroundColor Green
