# Build a public-safe Ninja Nexus source snapshot for development laptops.
param(
    [string]$OutputRoot = "",
    [string]$DownloadBaseUrl = "https://nexus.ninjakernen.info/downloads"
)

$ErrorActionPreference = "Stop"

$repoRoot = Split-Path -Parent (Split-Path -Parent $PSScriptRoot)
$monorepoRoot = Split-Path -Parent $repoRoot
$versionFile = Join-Path $repoRoot "source\nexus-shell\NexusShell\config\version.poc.json"
if (-not (Test-Path -LiteralPath $versionFile)) {
    throw "Version file not found: $versionFile"
}

$clientVersion = Get-Content -LiteralPath $versionFile -Raw | ConvertFrom-Json
$commit = (git -C $monorepoRoot rev-parse HEAD).Trim()
$shortCommit = (git -C $monorepoRoot rev-parse --short HEAD).Trim()
$branch = (git -C $monorepoRoot rev-parse --abbrev-ref HEAD).Trim()
$generatedAt = (Get-Date).ToUniversalTime().ToString("o")

$secretPattern = "-----BEGIN (RSA |DSA |EC |OPENSSH )?PRIVATE KEY-----|AKIA[0-9A-Z]{16}|ASIA[0-9A-Z]{16}|gh[pousr]_[A-Za-z0-9_]{30,}|sk_live_[0-9A-Za-z]{20,}|xox[baprs]-[0-9A-Za-z-]{20,}|AIza[0-9A-Za-z_-]{35}"
$secretScan = git -C $monorepoRoot grep -I -n -E -- $secretPattern HEAD -- "Ninja Nexus" 2>$null
if ($LASTEXITCODE -eq 0 -and $secretScan) {
    throw "Potential secret-like material found in tracked files. Refusing to build public dev pack.`n$secretScan"
}
if ($LASTEXITCODE -gt 1) {
    throw "git grep failed while scanning for secrets."
}

if (-not $OutputRoot) {
    $OutputRoot = Join-Path $repoRoot "dist\nexus-dev-pack"
}
$outputDir = Join-Path $OutputRoot "upload\downloads\dev-pack"
New-Item -ItemType Directory -Path $outputDir -Force | Out-Null

$zipName = "ninja-nexus-dev-pack.zip"
$zipPath = Join-Path $outputDir $zipName
$manifestPath = Join-Path $outputDir "dev-pack.json"
$shaPath = Join-Path $outputDir "sha256.txt"

$tempZip = Join-Path $env:TEMP ("ninja-nexus-dev-pack-" + [Guid]::NewGuid().ToString("N") + ".zip")
if (Test-Path -LiteralPath $tempZip) {
    Remove-Item -LiteralPath $tempZip -Force
}

git -C $monorepoRoot archive `
    --format=zip `
    --output=$tempZip `
    --prefix="Ninja Nexus/" `
    HEAD:"Ninja Nexus"
if ($LASTEXITCODE -ne 0) {
    throw "git archive failed."
}

Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem

$manifestForZip = [ordered]@{
    product       = "Ninja Nexus"
    artifactType  = "dev-pack"
    generatedAt   = $generatedAt
    sourceBranch  = $branch
    sourceCommit  = $commit
    sourcePath     = "Ninja Nexus"
    shellVersion   = [string]$clientVersion.version
    shellBuild     = [int]$clientVersion.build
    includes       = @(
        "Tracked source files",
        "Documentation and evidence files committed to git",
        "Deployment scripts and website source",
        "Installer, shell, identity API, contracts and tests"
    )
    excludes       = @(
        ".git and git metadata",
        "Untracked local files such as .cursor",
        "Ignored build outputs such as bin, obj, dist, .next, out and node_modules",
        "Local runtime logs, caches and installed POC data",
        "Untracked environment files or private credentials"
    )
    notes          = @(
        "This is a public-safe development snapshot, not a raw filesystem dump.",
        "Install dependencies on the target laptop with dotnet restore and npm ci where needed."
    )
}

$readme = @"
# Ninja Nexus Dev Pack

This ZIP is a public-safe development snapshot of the tracked `Ninja Nexus` project tree.

## Included

- Source, docs, tests, deployment scripts and website source tracked in git.
- Source commit: `$commit`
- Source branch: `$branch`
- Shell build: $($clientVersion.build) / $($clientVersion.version)

## Excluded

- `.git`, untracked local files, `.cursor`, `node_modules`, `.next`, `out`, `bin`, `obj`, `dist`, runtime logs, caches and local POC install data.

## Getting started on a laptop

1. Extract the ZIP.
2. Open the `Ninja Nexus` folder in Codex.
3. Run `dotnet restore` for .NET projects as needed.
4. In `apps/nexus-web`, run `npm ci` before building the website.

"@

$zip = [System.IO.Compression.ZipFile]::Open($tempZip, [System.IO.Compression.ZipArchiveMode]::Update)
try {
    foreach ($entryName in @("Ninja Nexus/DEV-PACK.md", "Ninja Nexus/dev-pack-manifest.json")) {
        $existing = $zip.GetEntry($entryName)
        if ($existing) {
            $existing.Delete()
        }
    }

    $readmeEntry = $zip.CreateEntry("Ninja Nexus/DEV-PACK.md")
    $writer = New-Object System.IO.StreamWriter($readmeEntry.Open(), [System.Text.Encoding]::UTF8)
    try { $writer.Write($readme) } finally { $writer.Dispose() }

    $manifestEntry = $zip.CreateEntry("Ninja Nexus/dev-pack-manifest.json")
    $writer = New-Object System.IO.StreamWriter($manifestEntry.Open(), [System.Text.Encoding]::UTF8)
    try { $writer.Write(($manifestForZip | ConvertTo-Json -Depth 8)) } finally { $writer.Dispose() }
} finally {
    $zip.Dispose()
}

Move-Item -LiteralPath $tempZip -Destination $zipPath -Force
$hash = (Get-FileHash -LiteralPath $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
$size = (Get-Item -LiteralPath $zipPath).Length

$downloadUrl = "$($DownloadBaseUrl.TrimEnd('/'))/dev-pack/$zipName"
$publicManifest = [ordered]@{
    product       = "Ninja Nexus"
    artifactType  = "dev-pack"
    name          = "Ninja Nexus Dev Pack"
    generatedAt   = $generatedAt
    sourceBranch  = $branch
    sourceCommit  = $commit
    sourceCommitShort = $shortCommit
    shellVersion  = [string]$clientVersion.version
    shellBuild    = [int]$clientVersion.build
    fileName      = $zipName
    downloadUrl   = $downloadUrl
    sha256        = $hash
    sizeBytes     = [long]$size
    manifestUrl   = "$($DownloadBaseUrl.TrimEnd('/'))/dev-pack/dev-pack.json"
    sha256Url     = "$($DownloadBaseUrl.TrimEnd('/'))/dev-pack/sha256.txt"
    safety        = "git archive of tracked project files; excludes .git, untracked files and ignored build/runtime artifacts"
}

[System.IO.File]::WriteAllText($manifestPath, ($publicManifest | ConvertTo-Json -Depth 8), (New-Object System.Text.UTF8Encoding $false))
[System.IO.File]::WriteAllText($shaPath, "$hash  $zipName`n", (New-Object System.Text.UTF8Encoding $false))

$publicManifest | Format-List
return $publicManifest
