$ErrorActionPreference = "Stop"

$root = Resolve-Path (Join-Path $PSScriptRoot "..")
$downloads = Join-Path $root "public\downloads"
$buildRoot = Join-Path $root "dist\download-build"
$extensionZip = Join-Path $downloads "mazexchain-wallet-extension.zip"
$programZip = Join-Path $downloads "mazexchain-node-program.zip"
$chainZip = Join-Path $downloads "mazexchain-chain-data.zip"
$whitepaperZhPdf = Join-Path $downloads "mazexchain-whitepaper-zh.pdf"
$whitepaperEnPdf = Join-Path $downloads "mazexchain-whitepaper-en.pdf"

function Reset-Dir($path) {
  if (Test-Path $path) {
    Remove-Item -LiteralPath $path -Recurse -Force
  }
  New-Item -ItemType Directory -Force -Path $path | Out-Null
}

function Copy-IfExists($source, $destination) {
  if (Test-Path $source) {
    Copy-Item -LiteralPath $source -Destination $destination -Recurse -Force
  }
}

function New-Zip($sourceGlob, $destination) {
  if (Test-Path $destination) {
    Remove-Item -LiteralPath $destination -Force
  }
  Compress-Archive -Path $sourceGlob -DestinationPath $destination -Force
}

function File-Entry($path, $label) {
  $item = Get-Item -LiteralPath $path
  $hash = Get-FileHash -LiteralPath $path -Algorithm SHA256
  return [ordered]@{
    label = $label
    file = "/downloads/$($item.Name)"
    bytes = $item.Length
    sha256 = $hash.Hash.ToLowerInvariant()
    updated_at = $item.LastWriteTimeUtc.ToString("o")
  }
}

New-Item -ItemType Directory -Force -Path $downloads | Out-Null
Reset-Dir $buildRoot

$extensionDir = Join-Path $root "extension"
if (!(Test-Path $extensionDir)) {
  throw "Extension directory not found: $extensionDir"
}
New-Zip (Join-Path $extensionDir "*") $extensionZip

$programStage = Join-Path $buildRoot "mazexchain-node-program"
Reset-Dir $programStage
foreach ($dir in @("src", "public", "tools", "extension")) {
  Copy-IfExists (Join-Path $root $dir) (Join-Path $programStage $dir)
}
foreach ($dir in @("cli", "config", "docs", "genesis", "tests")) {
  Copy-IfExists (Join-Path $root $dir) (Join-Path $programStage $dir)
}
foreach ($file in @("package.json", "package-lock.json", "README.md", "PROJECT_SCOPE.md", "PROJECT_STATUS.md", "PROJECT_CONTEXT.md", "PROJECT_READING_RULES.md", "CHANGELOG.md")) {
  Copy-IfExists (Join-Path $root $file) (Join-Path $programStage $file)
}
$nestedDownloads = Join-Path $programStage "public\downloads"
if (Test-Path $nestedDownloads) {
  Remove-Item -LiteralPath $nestedDownloads -Recurse -Force
}
@"
MazeXChain Node Program

Requirements:
- Node.js 20 or newer

Start:
1. npm install
2. npm start
3. Open http://localhost:3000

This package excludes private vault data, local private challenge material, node_modules, and local runtime data.
"@ | Set-Content -LiteralPath (Join-Path $programStage "INSTALL.txt") -Encoding UTF8
New-Zip (Join-Path $programStage "*") $programZip

$chainStage = Join-Path $buildRoot "mazexchain-chain-data"
Reset-Dir $chainStage
$chainPublic = Join-Path $root "data\mazexchain"
if (Test-Path $chainPublic) {
  New-Item -ItemType Directory -Force -Path (Join-Path $chainStage "data") | Out-Null
  Copy-Item -LiteralPath $chainPublic -Destination (Join-Path $chainStage "data\mazexchain") -Recurse -Force
}
Copy-IfExists (Join-Path $root "data\mazex_base1_state.json") (Join-Path $chainStage "mazex_base1_state.json")
@"
MazeXChain Public Chain Data

This package contains public replay and synchronization material only.
It excludes private vault files, current private Step material, hidden generator state, and future challenge secrets.
"@ | Set-Content -LiteralPath (Join-Path $chainStage "README.txt") -Encoding UTF8
New-Zip (Join-Path $chainStage "*") $chainZip

Copy-IfExists (Join-Path $root "public\MazeX_Whitepaper_ZH_V0.1.pdf") $whitepaperZhPdf
Copy-IfExists (Join-Path $root "public\MazeX_Whitepaper_V0.1.pdf") $whitepaperEnPdf

$manifest = [ordered]@{
  generated_at = (Get-Date).ToUniversalTime().ToString("o")
  downloads = @(
    File-Entry $extensionZip "Wallet Extension"
    File-Entry $programZip "Node Program"
    File-Entry $chainZip "Public Chain Data"
    File-Entry $whitepaperZhPdf "Technical Whitepaper Chinese PDF"
    File-Entry $whitepaperEnPdf "Technical Whitepaper English PDF"
  )
}

$manifestJson = $manifest | ConvertTo-Json -Depth 6
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText((Join-Path $downloads "manifest.json"), $manifestJson, $utf8NoBom)
Write-Output "Created downloads in $downloads"
