# Deploy prebuilt MyOffice artifacts to a Proxmox CT (or any Linux host).
# Usage:
#   .\proxmox\publish.ps1
#   .\proxmox\deploy.ps1 -TargetHost 192.168.1.120
#   .\proxmox\deploy.ps1 -TargetHost 192.168.1.120 -User root -RemotePath /opt/myoffice/api
#
# Requires OpenSSH client (ssh/scp). Prefers rsync if available (Git Bash / WSL / cwRsync).
# Preserves CT-owned appsettings.Production.json / appsettings.shared.Production.json.

[CmdletBinding()]
param(
	[Parameter(Mandatory = $true)]
	[Alias('ComputerName', 'Host')]
	[string]$TargetHost,

	[string]$User = 'root',

	[Alias('Path')]
	[string]$RemotePath = '/opt/myoffice/api',

	[string]$Service = 'myoffice-api',

	[string]$PublishDir = '',

	[int]$Port = 22
)

$ErrorActionPreference = 'Stop'

$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$repoRoot = Resolve-Path (Join-Path $scriptDir '..')

if (-not $PublishDir) {
	$PublishDir = Join-Path $repoRoot '_Published'
}
if (-not (Test-Path $PublishDir)) {
	throw "Publish folder not found: $PublishDir — run .\proxmox\publish.ps1 first."
}
if (-not (Test-Path (Join-Path $PublishDir 'MyOffice.Web.dll'))) {
	throw "MyOffice.Web.dll missing in $PublishDir — run .\proxmox\publish.ps1 first."
}

$ctOwnedSettings = @(
	'appsettings.Production.json',
	'appsettings.shared.Production.json'
)

$remote = "${User}@${TargetHost}"
$sshTarget = @('-p', "$Port", $remote)
$scpTarget = @('-P', "$Port")

function Invoke-Remote {
	param([Parameter(Mandatory = $true)][string]$Command)
	& ssh @sshTarget $Command
	if ($LASTEXITCODE -ne 0) {
		throw "ssh failed (exit $LASTEXITCODE): $Command"
	}
}

function Test-Rsync {
	return [bool](Get-Command rsync -ErrorAction SilentlyContinue)
}

function ConvertTo-RsyncPath([string]$WindowsPath) {
	$p = ($WindowsPath.TrimEnd('\', '/') + '/') -replace '\\', '/'
	if ($p -match '^[A-Za-z]:') {
		$drive = $p.Substring(0, 1).ToLower()
		$p = "/$drive" + $p.Substring(2)
	}
	return $p
}

Write-Host "-----------------------------------------------"
Write-Host "Deploy $PublishDir -> ${remote}:${RemotePath}"
Write-Host "-----------------------------------------------"

Write-Host "Stopping $Service..."
Invoke-Remote "systemctl stop $Service || true"

Invoke-Remote "mkdir -p '$RemotePath'"

$rsync = Test-Rsync
if ($rsync) {
	Write-Host "Copying with rsync (preserve CT Production appsettings)..."
	$rsyncSrc = ConvertTo-RsyncPath $PublishDir
	$rsyncArgs = @(
		'-r', '--info=progress2',
		'--exclude', 'appsettings.Production.json',
		'--exclude', 'appsettings.shared.Production.json',
		'-e', "ssh -p $Port",
		$rsyncSrc,
		"${remote}:${RemotePath}/"
	)
	& rsync @rsyncArgs
	if ($LASTEXITCODE -ne 0) {
		throw "rsync failed with exit code $LASTEXITCODE"
	}
}
else {
	Write-Host "rsync not found — using tar+scp fallback..."
	$staging = Join-Path $env:TEMP ("myoffice-deploy-" + [guid]::NewGuid().ToString('N'))
	New-Item -ItemType Directory -Path $staging | Out-Null
	try {
		Get-ChildItem -Path $PublishDir -Force | Where-Object {
			$_.Name -notin $ctOwnedSettings
		} | ForEach-Object {
			Copy-Item $_.FullName -Destination $staging -Recurse -Force
		}

		$tarLocal = Join-Path $env:TEMP 'myoffice-deploy.tar.gz'
		if (Test-Path $tarLocal) { Remove-Item -Force $tarLocal }
		Push-Location $staging
		try {
			tar -czf $tarLocal *
			if ($LASTEXITCODE -ne 0) { throw "tar create failed" }
		}
		finally {
			Pop-Location
		}

		& scp @scpTarget $tarLocal "${remote}:/tmp/myoffice-deploy.tar.gz"
		if ($LASTEXITCODE -ne 0) { throw "scp failed" }

		Invoke-Remote "tar -xzf /tmp/myoffice-deploy.tar.gz -C '$RemotePath' && rm -f /tmp/myoffice-deploy.tar.gz"
	}
	finally {
		Remove-Item -Recurse -Force $staging -ErrorAction SilentlyContinue
		Remove-Item -Force (Join-Path $env:TEMP 'myoffice-deploy.tar.gz') -ErrorAction SilentlyContinue
	}
}

Write-Host "Starting $Service..."
Invoke-Remote "systemctl start $Service"
Invoke-Remote "systemctl --no-pager --full status $Service || true"

Write-Host ""
Write-Host "Deployed to http://${TargetHost}:9100 (or your nginx public URL)"
Write-Host ""
