# Build aresCMS system upgrade ZIP + manifest (mirrors CreateCmsUpdate.php exclusions)
# Usage: powershell -ExecutionPolicy Bypass -File scripts\build-system-upgrade.ps1

param(
    [string]$Release = '1.0.2',
    [string]$PackageBase = 'https://update.luetcke.eu',
    [string]$NotesFile = 'deploy/system-upgrade/RELEASE_NOTES_1.0.2.txt',
    [string]$OutDir = 'deploy/system-upgrade'
)

$ErrorActionPreference = 'Stop'
Add-Type -AssemblyName System.IO.Compression
Add-Type -AssemblyName System.IO.Compression.FileSystem

$root = Split-Path $PSScriptRoot -Parent
$safeFile = ($Release -replace '[^a-zA-Z0-9._-]+', '-')
$zipName = "news-portal-update-$safeFile.zip"
$zipPath = Join-Path (Join-Path $root $OutDir) $zipName
$notesPath = Join-Path $root $NotesFile

if (-not (Test-Path $notesPath)) {
    throw "Release notes not found: $notesPath"
}

$notes = (Get-Content -Path $notesPath -Raw -Encoding UTF8) -replace "`r`n", "`n" -replace "`r", "`n"

$blockedPrefixes = @(
    '.git/', 'node_modules/', '.idea/', '.vscode/', '.cursor/',
    'storage/logs/', 'storage/app/public/', 'storage/app/backups/', 'storage/app/cms/',
    'storage/framework/cache/data/', 'storage/framework/sessions/', 'storage/framework/views/',
    'public/update/', 'public/storage/', 'tests/',
    'filezilla-upload/', 'filezilla-upload-handwerk/', 'filezilla-upload-themes/',
    'deploy/system-upgrade/'
)
$blockedExact = @('.env', '.env.backup', 'htdocs.lnk', 'mkdir', 'public/hot', 'php')

function Test-IncludeRelativePath {
    param([string]$Relative)
    $rel = $Relative.Replace('\', '/').TrimStart('/').ToLowerInvariant()
    foreach ($prefix in $blockedPrefixes) {
        $p = $prefix.ToLowerInvariant()
        $trimmed = $p.TrimEnd('/')
        if ($rel -eq $trimmed -or $rel.StartsWith($p)) { return $false }
    }
    foreach ($name in $blockedExact) {
        if ($rel -eq $name.ToLowerInvariant()) { return $false }
    }
    if ($rel.EndsWith('/.env') -or $rel.EndsWith('/.env.backup')) { return $false }
    if ($rel.Contains('/.git/')) { return $false }
    return $true
}

$outDirFull = Join-Path $root $OutDir
if (-not (Test-Path $outDirFull)) {
    New-Item -ItemType Directory -Path $outDirFull -Force | Out-Null
}

if (Test-Path $zipPath) { Remove-Item $zipPath -Force }

$zip = [System.IO.Compression.ZipFile]::Open($zipPath, [System.IO.Compression.ZipArchiveMode]::Create)
$fileCount = 0

try {
    Get-ChildItem -Path $root -Recurse -File -Force | ForEach-Object {
        $full = $_.FullName
        $rel = $full.Substring($root.Length + 1)
        if (-not (Test-IncludeRelativePath $rel)) { return }
        $entryName = $rel.Replace('\', '/')
        [void][System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $full, $entryName, [System.IO.Compression.CompressionLevel]::Optimal)
        $script:fileCount++
    }

    $marker = @(
        'aresCMS CMS-Update',
        "Version: $Release",
        "Erzeugt: $((Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ'))",
        'Nach Installation sollte diese Datei unter public/ liegen.'
    ) -join "`n"
    $marker += "`n"

    $entry = $zip.CreateEntry('public/cms-update-verification.txt')
    $stream = $entry.Open()
    $bytes = [System.Text.Encoding]::UTF8.GetBytes($marker)
    $stream.Write($bytes, 0, $bytes.Length)
    $stream.Close()
}
finally {
    $zip.Dispose()
}

$sha256 = (Get-FileHash -Path $zipPath -Algorithm SHA256).Hash.ToLowerInvariant()
$packageUrl = "$($PackageBase.TrimEnd('/'))/$zipName"

$manifest = [ordered]@{
    version     = $Release
    min_php     = '8.1.0'
    package_url = $packageUrl
    sha256      = $sha256
    notes       = $notes
}

$manifestPath = Join-Path $outDirFull 'manifest.json'
$json = ($manifest | ConvertTo-Json -Depth 5) + "`n"
[System.IO.File]::WriteAllText($manifestPath, $json, [System.Text.Encoding]::UTF8)

$publicUpdate = Join-Path $root 'public/update'
if (-not (Test-Path $publicUpdate)) {
    New-Item -ItemType Directory -Path $publicUpdate -Force | Out-Null
}
Copy-Item $zipPath (Join-Path $publicUpdate $zipName) -Force
Copy-Item $manifestPath (Join-Path $publicUpdate 'manifest.json') -Force

$zipSize = (Get-Item $zipPath).Length
Write-Host ''
Write-Host '=== System-Upgrade-Paket erstellt ===' -ForegroundColor Green
Write-Host "ZIP:       $zipPath"
Write-Host "Manifest:  $manifestPath"
Write-Host "Dateien:   $fileCount (+ verification marker)"
Write-Host ("Groesse:   {0:N2} MB" -f ($zipSize / 1MB))
Write-Host "SHA-256:   $sha256"
Write-Host ''
Write-Host 'Upload auf update.luetcke.eu:'
Write-Host "  1. $zipName"
Write-Host '  2. manifest.json'
