[CmdletBinding()]
param(
    [Parameter(Mandatory = $true)][string]$CurrentVersion,
    [Parameter(Mandatory = $true)][string]$ResultPath,
    [string]$BaseUrl = ""
)

$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"

function Assert-ProductVersion([string]$Value) {
    if ($Value -notmatch "^\d+\.\d+\.\d+$") {
        throw "Invalid BMCLI version '$Value'; expected X.Y.Z"
    }
}

function Compare-ProductVersion([string]$Left, [string]$Right) {
    $a = @($Left.Split('.') | ForEach-Object { [int]$_ })
    $b = @($Right.Split('.') | ForEach-Object { [int]$_ })
    for ($i = 0; $i -lt 3; $i++) {
        if ($a[$i] -lt $b[$i]) { return -1 }
        if ($a[$i] -gt $b[$i]) { return 1 }
    }
    return 0
}

Assert-ProductVersion $CurrentVersion
if (-not $BaseUrl) {
    $BaseUrl = if ($env:BMCLI_BASE_URL) { $env:BMCLI_BASE_URL } `
        else { "https://download.busmust.com/bmcli" }
}
$manifest = Invoke-RestMethod -Uri "$BaseUrl/releases/latest/manifest.json"
if ($manifest.schema_version -ne 1) { throw "Unsupported manifest schema" }
$latestVersion = [string]$manifest.version
Assert-ProductVersion $latestVersion

$releaseNotes = ""
$releaseNotesUrl = ""
if ($manifest.release_notes) {
    $releaseNotesUrl = [string]$manifest.release_notes.url
    $expected = [string]$manifest.release_notes.sha256
    if ($expected -notmatch "^[0-9A-Fa-f]{64}$") {
        throw "Release notes contain an invalid SHA-256"
    }
    $notesPath = [IO.Path]::GetTempFileName()
    try {
        Invoke-WebRequest -Uri $releaseNotesUrl -OutFile $notesPath
        $actual = (Get-FileHash -LiteralPath $notesPath -Algorithm SHA256).Hash
        if ($actual.ToLowerInvariant() -ne $expected.ToLowerInvariant()) {
            throw "Release notes SHA-256 mismatch"
        }
        $releaseNotes = Get-Content -Raw -LiteralPath $notesPath
    } finally {
        Remove-Item -LiteralPath $notesPath -Force -ErrorAction SilentlyContinue
    }
}

$comparison = Compare-ProductVersion $CurrentVersion $latestVersion
$relevantNotes = ""
if ($comparison -lt 0 -and $releaseNotes) {
    $collected = [Collections.Generic.List[string]]::new()
    foreach ($line in ($releaseNotes -split "`r?`n")) {
        if ($line -match ("^" + [regex]::Escape($CurrentVersion) + "(?:\s|$)")) { break }
        $collected.Add($line)
    }
    $relevantNotes = ($collected -join "`n").Trim()
}
$state = if ($comparison -lt 0) { "update_available" } `
    elseif ($comparison -eq 0) { "up_to_date" } else { "local_newer" }
$result = [ordered]@{
    status = "ok"
    action = "update_check"
    current_version = $CurrentVersion
    latest_version = $latestVersion
    update_available = ($comparison -lt 0)
    state = $state
    release_notes_url = $releaseNotesUrl
    release_notes = $relevantNotes
}
[IO.File]::WriteAllText([IO.Path]::GetFullPath($ResultPath),
    ($result | ConvertTo-Json -Compress) + "`n", [Text.UTF8Encoding]::new($false))
