# Upload myoffice-publish.tar.gz to a Gitea Release on the public repo.
# Usage:
#   $env:GITEA_TOKEN = '<token>'
#   .\proxmox\publish.ps1 -Tar
#   .\proxmox\release.ps1 -GiteaUrl https://gitea.example.com -Owner org -Repo myoffice-public -Tag v1.2.3
#
# Token needs write:repository on the public repo.

[CmdletBinding()]
param(
	[Parameter(Mandatory = $true)]
	[string]$GiteaUrl,

	[Parameter(Mandatory = $true)]
	[string]$Owner,

	[string]$Repo = 'myoffice-public',

	[Parameter(Mandatory = $true)]
	[string]$Tag,

	[string]$Token = $env:GITEA_TOKEN,

	[string]$AssetPath = '',

	[string]$Title = '',

	[string]$Body = 'MyOffice published API + SPA (Proxmox CT artifact).',

	[string]$Target = 'main'
)

$ErrorActionPreference = 'Stop'

if (-not $Token) {
	throw 'GITEA_TOKEN (or -Token) is required.'
}

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

if (-not $AssetPath) {
	$AssetPath = Join-Path $repoRoot 'myoffice-publish.tar.gz'
}
if (-not (Test-Path $AssetPath)) {
	throw "Asset not found: $AssetPath — run .\proxmox\publish.ps1 -Tar first."
}

$GiteaUrl = $GiteaUrl.TrimEnd('/')
$api = "$GiteaUrl/api/v1"
$assetName = 'myoffice-publish.tar.gz'
if (-not $Title) { $Title = $Tag }

$headers = @{
	Authorization = "token $Token"
	Accept        = 'application/json'
}

function Invoke-GiteaJson {
	param(
		[string]$Method,
		[string]$Uri,
		[object]$BodyObject = $null
	)
	$params = @{
		Method  = $Method
		Uri     = $Uri
		Headers = $headers
	}
	if ($null -ne $BodyObject) {
		$params.ContentType = 'application/json'
		$params.Body = ($BodyObject | ConvertTo-Json -Depth 6)
	}
	return Invoke-RestMethod @params
}

Write-Host "-----------------------------------------------"
Write-Host "Gitea release $Owner/$Repo tag $Tag"
Write-Host "-----------------------------------------------"

$release = $null
try {
	$release = Invoke-GiteaJson -Method GET -Uri "$api/repos/$Owner/$Repo/releases/tags/$Tag"
	Write-Host "Release $Tag already exists (id $($release.id))."
}
catch {
	Write-Host "Creating release $Tag..."
	$release = Invoke-GiteaJson -Method POST -Uri "$api/repos/$Owner/$Repo/releases" -BodyObject @{
		tag_name         = $Tag
		target_commitish = $Target
		name             = $Title
		body             = $Body
		draft            = $false
		prerelease       = $false
	}
	Write-Host "Created release id $($release.id)."
}

# Remove existing asset with the same name so re-upload works
$existing = @($release.assets) | Where-Object { $_.name -eq $assetName }
foreach ($a in $existing) {
	Write-Host "Deleting existing asset id $($a.id) ($($a.name))..."
	Invoke-GiteaJson -Method DELETE -Uri "$api/repos/$Owner/$Repo/releases/$($release.id)/assets/$($a.id)" | Out-Null
}

$uploadUrl = "$api/repos/$Owner/$Repo/releases/$($release.id)/assets?name=$assetName"
Write-Host "Uploading $AssetPath ..."

# Prefer curl multipart (reliable on Windows PowerShell 5 + 7)
$curl = Get-Command curl.exe -ErrorAction SilentlyContinue
if ($curl) {
	$args = @(
		'-fsS', '-X', 'POST',
		'-H', "Authorization: token $Token",
		'-F', "attachment=@$AssetPath",
		$uploadUrl
	)
	& curl.exe @args
	if ($LASTEXITCODE -ne 0) {
		throw "curl upload failed with exit code $LASTEXITCODE"
	}
}
else {
	# Fallback: .NET multipart
	Add-Type -AssemblyName System.Net.Http
	$handler = [System.Net.Http.HttpClientHandler]::new()
	$client = [System.Net.Http.HttpClient]::new($handler)
	$client.DefaultRequestHeaders.Add('Authorization', "token $Token")
	$content = [System.Net.Http.MultipartFormDataContent]::new()
	$fs = [System.IO.File]::OpenRead($AssetPath)
	try {
		$streamContent = [System.Net.Http.StreamContent]::new($fs)
		$streamContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse('application/octet-stream')
		$content.Add($streamContent, 'attachment', $assetName)
		$resp = $client.PostAsync($uploadUrl, $content).Result
		if (-not $resp.IsSuccessStatusCode) {
			$err = $resp.Content.ReadAsStringAsync().Result
			throw "Upload failed: $($resp.StatusCode) $err"
		}
	}
	finally {
		$fs.Dispose()
		$content.Dispose()
		$client.Dispose()
	}
}

$downloadUrl = "$GiteaUrl/$Owner/$Repo/releases/download/$Tag/$assetName"
Write-Host ""
Write-Host "Uploaded. Download URL:"
Write-Host "  $downloadUrl"
Write-Host "Latest API:"
Write-Host "  $api/repos/$Owner/$Repo/releases/latest"
Write-Host ""
