#Requires -Version 5.1
<#
.SYNOPSIS
    ClawdDotNet Deployment-Paket erstellen.
    Baut Release, packt alles Noetige in ein ZIP das per AnyDesk auf den Server kopiert wird.

.DESCRIPTION
    Zwei Modi:
      -Full     Komplettes Deployment (alle Dateien, ~300 MB) — fuer Erstinstallation oder Dependency-Updates
      -Quick    Nur ClawdDotNet-eigene Binaries (~2 MB) — fuer normale Code-Aenderungen (DEFAULT)

.EXAMPLE
    .\Deploy-Build.ps1              # Quick-Deploy (nur eigene DLLs)
    .\Deploy-Build.ps1 -Full        # Alles inkl. Dependencies
    .\Deploy-Build.ps1 -SkipBuild   # ZIP ohne vorher zu bauen (wenn Build schon aktuell)
#>
param(
    [switch]$Full,
    [switch]$SkipBuild,
    [switch]$IncludeAgentConfigs
)

$ErrorActionPreference = 'Stop'

# ─── Pfade ───
$projectRoot  = $PSScriptRoot
$buildOutput  = Join-Path $projectRoot "bin\Release\net10.0-windows"
$deployDir    = Join-Path $projectRoot "deploy"
$timestamp    = Get-Date -Format "yyyyMMdd_HHmmss"
$mode         = if ($Full) { "full" } else { "quick" }
$zipName      = "ClawdDotNet_${mode}_${timestamp}.zip"
$zipPath      = Join-Path $deployDir $zipName

# ─── 1. Build ───
if (-not $SkipBuild) {
    Write-Host "`n=== Building Release ===" -ForegroundColor Cyan
    Push-Location $projectRoot
    dotnet build -c Release --no-restore
    if ($LASTEXITCODE -ne 0) {
        Write-Host "BUILD FAILED!" -ForegroundColor Red
        Pop-Location
        exit 1
    }
    Pop-Location
    Write-Host "Build OK" -ForegroundColor Green
} else {
    Write-Host "`n=== Build uebersprungen (SkipBuild) ===" -ForegroundColor Yellow
}

# ─── 2. Staging-Ordner vorbereiten ───
$stagingDir = Join-Path $deployDir "staging_$timestamp"
if (Test-Path $stagingDir) { Remove-Item $stagingDir -Recurse -Force }
New-Item -ItemType Directory -Path $stagingDir -Force | Out-Null

if ($Full) {
    # ── Full Deploy: Alles ausser Instances/, Logs/, PDBs ──
    Write-Host "`n=== Full Deploy: Kopiere alle Dateien ===" -ForegroundColor Cyan

    # Dateien im Root
    Get-ChildItem $buildOutput -File | Where-Object {
        $_.Extension -ne '.pdb'
    } | ForEach-Object {
        Copy-Item $_.FullName $stagingDir
    }

    # Unterordner (ohne Instances und Logs)
    Get-ChildItem $buildOutput -Directory | Where-Object {
        $_.Name -notin @('Instances', 'Logs')
    } | ForEach-Object {
        Copy-Item $_.FullName (Join-Path $stagingDir $_.Name) -Recurse
    }

} else {
    # ── Quick Deploy: Nur ClawdDotNet-eigene Dateien ──
    Write-Host "`n=== Quick Deploy: Nur eigene Binaries ===" -ForegroundColor Cyan

    Get-ChildItem $buildOutput -File | Where-Object {
        $_.Name -match '^ClawdDotNet\.' -and $_.Extension -ne '.pdb'
    } | ForEach-Object {
        Copy-Item $_.FullName $stagingDir
    }
}

# ─── 2b. Optional: Agent-Configs mitkopieren ───
if ($IncludeAgentConfigs) {
    Write-Host "=== Agent-Configs werden mitgepackt ===" -ForegroundColor Yellow
    $instancesSource = Join-Path $buildOutput "Instances"
    if (Test-Path $instancesSource) {
        $instancesDest = Join-Path $stagingDir "Instances"
        # Agent-Configs + Shared-Website-Templates kopieren
        Get-ChildItem $instancesSource -Recurse -File -Include "Identity.md","Soul.md","AgentSettings.json","AgentList.json","InstanceSettings.json","style.css","script.js" | ForEach-Object {
            $relPath = $_.FullName.Substring($instancesSource.Length)
            $destPath = Join-Path $instancesDest $relPath
            $destDir = Split-Path $destPath -Parent
            if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir -Force | Out-Null }
            Copy-Item $_.FullName $destPath
        }
    }
}

# ─── 3. Install-Skript beilegen ───
$installScript = @'
#Requires -Version 5.1
<#
.SYNOPSIS
    ClawdDotNet Update auf dem Server installieren.
    Stoppt die laufende Instanz, kopiert neue Dateien, startet neu.

.EXAMPLE
    .\Deploy-Install.ps1                               # Standard: ClawdDotNet.exe automatisch suchen
    .\Deploy-Install.ps1 -TargetDir "D:\ClawdDotNet"   # Zielordner explizit angeben
#>
param(
    [string]$TargetDir
)

$ErrorActionPreference = 'Stop'

# Zielordner bestimmen
if (-not $TargetDir) {
    $candidates = @(
        "C:\ClawdDotNet",
        "D:\ClawdDotNet",
        "$env:ProgramFiles\ClawdDotNet",
        "$env:LOCALAPPDATA\ClawdDotNet"
    )
    foreach ($c in $candidates) {
        if (Test-Path (Join-Path $c "ClawdDotNet.exe")) {
            $TargetDir = $c
            break
        }
    }
    if (-not $TargetDir) {
        Write-Host "ClawdDotNet-Installation nicht gefunden!" -ForegroundColor Red
        Write-Host 'Bitte mit -TargetDir angeben, z.B.:'
        Write-Host '  .\Deploy-Install.ps1 -TargetDir "D:\ClawdDotNet"'
        exit 1
    }
}

Write-Host ""
Write-Host "=== ClawdDotNet Update ===" -ForegroundColor Cyan
Write-Host "Ziel: $TargetDir"

# 1. Prozess stoppen
$proc = Get-Process -Name "ClawdDotNet" -ErrorAction SilentlyContinue
if ($proc) {
    Write-Host "Stoppe ClawdDotNet..." -ForegroundColor Yellow
    $proc | Stop-Process -Force -Confirm:$false
    Start-Sleep -Seconds 2
    $timeout = 15
    while ((Get-Process -Name "ClawdDotNet" -ErrorAction SilentlyContinue) -and $timeout -gt 0) {
        Start-Sleep -Seconds 1
        $timeout--
    }
    if ($timeout -eq 0) {
        Write-Host "WARNUNG: Prozess konnte nicht gestoppt werden!" -ForegroundColor Red
        exit 1
    }
    Write-Host "Gestoppt." -ForegroundColor Green
} else {
    Write-Host "ClawdDotNet laeuft nicht - kein Stopp noetig." -ForegroundColor Gray
}

# 2. Backup erstellen (nur eigene DLLs)
$backupDir = Join-Path $TargetDir ("_backup_" + (Get-Date -Format "yyyyMMdd_HHmmss"))
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
Get-ChildItem $TargetDir -File | Where-Object { $_.Name -match '^ClawdDotNet\.' } | ForEach-Object {
    Copy-Item $_.FullName $backupDir
}
Write-Host "Backup erstellt: $backupDir" -ForegroundColor Gray

# 3. Neue Dateien kopieren
$sourceDir = $PSScriptRoot
$sourceFull = (Resolve-Path $sourceDir).Path.TrimEnd('\')
$targetFull = (Resolve-Path $TargetDir).Path.TrimEnd('\')

if ($sourceFull -eq $targetFull) {
    # ZIP wurde direkt im Zielordner entpackt - Dateien sind schon da
    Write-Host "ZIP wurde direkt im Zielordner entpackt - Dateien bereits vorhanden." -ForegroundColor Yellow
    $fileCount = (Get-ChildItem $sourceDir -File | Where-Object { $_.Name -notin @('Deploy-Install.ps1') }).Count
} else {
    $fileCount = 0
    Get-ChildItem $sourceDir -File | Where-Object { $_.Name -notin @('Deploy-Install.ps1') } | ForEach-Object {
        Copy-Item $_.FullName $TargetDir -Force
        $fileCount++
    }

    # Unterordner kopieren (falls vorhanden, z.B. bei Full-Deploy)
    Get-ChildItem $sourceDir -Directory | Where-Object { $_.Name -notmatch '^_backup' } | ForEach-Object {
        $destSubDir = Join-Path $TargetDir $_.Name
        Copy-Item $_.FullName $destSubDir -Recurse -Force
        $fileCount += (Get-ChildItem $_.FullName -Recurse -File).Count
    }
}

Write-Host "$fileCount Dateien aktualisiert." -ForegroundColor Green

# 4. Neu starten
Write-Host "Starte ClawdDotNet..." -ForegroundColor Cyan
$exePath = Join-Path $TargetDir "ClawdDotNet.exe"
Start-Process $exePath -WorkingDirectory $TargetDir
Start-Sleep -Seconds 3

if (Get-Process -Name "ClawdDotNet" -ErrorAction SilentlyContinue) {
    Write-Host ""
    Write-Host "=== Update erfolgreich! ClawdDotNet laeuft. ===" -ForegroundColor Green
} else {
    Write-Host ""
    Write-Host "=== WARNUNG: Prozess nicht gefunden. Bitte manuell pruefen. ===" -ForegroundColor Yellow
}

# 5. Alte Backups aufraeumen (behalte die letzten 5)
$oldBackups = Get-ChildItem $TargetDir -Directory | Where-Object { $_.Name -match '^_backup_' } | Sort-Object Name -Descending | Select-Object -Skip 5
foreach ($old in $oldBackups) {
    Remove-Item $old.FullName -Recurse -Force
    Write-Host "Altes Backup entfernt: $($old.Name)" -ForegroundColor Gray
}

Write-Host ""
Write-Host "Fertig." -ForegroundColor Green
'@

$installScriptPath = Join-Path $stagingDir "Deploy-Install.ps1"
# UTF-8 OHNE BOM - wichtig fuer PowerShell 5.1 auf Windows Server
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
[System.IO.File]::WriteAllText($installScriptPath, $installScript, $utf8NoBom)

# ─── 4. ZIP erstellen ───
if (-not (Test-Path $deployDir)) { New-Item -ItemType Directory -Path $deployDir -Force | Out-Null }

Write-Host "`n=== Erstelle ZIP: $zipName ===" -ForegroundColor Cyan
if (Test-Path $zipPath) { Remove-Item $zipPath -Force }
Compress-Archive -Path "$stagingDir\*" -DestinationPath $zipPath -CompressionLevel Optimal

# Staging aufraeumen
Remove-Item $stagingDir -Recurse -Force

# ─── 5. Zusammenfassung ───
$zipSize = (Get-Item $zipPath).Length
Write-Host "`n========================================" -ForegroundColor Green
Write-Host " Deployment-Paket erstellt!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
Write-Host " Modus:   $( if ($Full) { 'FULL (alle Dateien)' } else { 'QUICK (nur eigene DLLs)' } )"
Write-Host " Datei:   $zipPath"
Write-Host " Groesse: $([math]::Round($zipSize/1KB, 0)) KB ($([math]::Round($zipSize/1MB, 1)) MB)"
Write-Host ""
Write-Host " Naechste Schritte:" -ForegroundColor Yellow
Write-Host "   1. ZIP per AnyDesk auf den Server kopieren"
Write-Host "   2. Auf dem Server entpacken"
Write-Host "   3. Deploy-Install.ps1 als Admin ausfuehren"
Write-Host ""

# ZIP-Ordner im Explorer oeffnen
Start-Process "explorer.exe" "/select,`"$zipPath`""
