# Kigi installer (Windows x86_64) — PRD F8.
#
# Downloads the x86_64-pc-windows-msvc artifact from this repo's GitHub
# Releases, verifies its SHA-256 against the release's SHA256SUMS manifest,
# and installs the binary as %USERPROFILE%\.kigi\bin\kigi.exe.
#
# Usage:
#   irm https://raw.githubusercontent.com/ZacharyZhang-NY/Kigi-CLI/main/install.ps1 | iex
#   powershell -ExecutionPolicy Bypass -File install.ps1 -Version v0.1.0
#
# Environment:
#   KIGI_SHARE_DIR        install root (default: %USERPROFILE%\.kigi)
#   KIGI_UPDATE_BASE_URL  GitHub-Releases-shaped API base (default:
#                         https://api.github.com/repos/ZacharyZhang-NY/Kigi-CLI/releases)

[CmdletBinding()]
param(
    [string]$Version = ""
)

$ErrorActionPreference = "Stop"
Set-StrictMode -Version Latest

function Fail([string]$Message) {
    Write-Error "install.ps1: error: $Message"
    exit 1
}

$Repo = "ZacharyZhang-NY/Kigi-CLI"
$ApiBase = if ($env:KIGI_UPDATE_BASE_URL) { $env:KIGI_UPDATE_BASE_URL } else { "https://api.github.com/repos/$Repo/releases" }
$KigiHome = if ($env:KIGI_SHARE_DIR) { $env:KIGI_SHARE_DIR } else { Join-Path $env:USERPROFILE ".kigi" }
$Triple = "x86_64-pc-windows-msvc"

# ── Platform gate ────────────────────────────────────────────────────────────
if (-not [System.Environment]::Is64BitOperatingSystem) {
    Fail "kigi requires 64-bit Windows (x86_64)"
}
$arch = $env:PROCESSOR_ARCHITECTURE
if ($arch -ne "AMD64") {
    Fail "unsupported architecture '$arch' (only x86_64/AMD64 Windows builds are published)"
}

# ── Version argument ─────────────────────────────────────────────────────────
$Version = $Version.TrimStart("v")
if ($Version -and $Version -notmatch '^\d+\.\d+\.\d+([-.][0-9A-Za-z.-]+)?$') {
    Fail "invalid version '$Version' (expected X.Y.Z or vX.Y.Z)"
}

# TLS 1.2 for older PowerShell 5.1 defaults.
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12

$Headers = @{ "User-Agent" = "kigi-install"; "Accept" = "application/vnd.github+json" }

# ── Resolve the release ──────────────────────────────────────────────────────
$ReleaseUrl = if ($Version) { "$ApiBase/tags/v$Version" } else { "$ApiBase/latest" }
Write-Host "Resolving release from $ReleaseUrl"
try {
    $Release = Invoke-RestMethod -Uri $ReleaseUrl -Headers $Headers
} catch {
    Fail "could not fetch release metadata from ${ReleaseUrl}: $($_.Exception.Message)"
}

$Tag = [string]$Release.tag_name
if (-not $Tag) { Fail "release metadata has no tag_name (endpoint: $ReleaseUrl)" }
$ResolvedVersion = $Tag.TrimStart("v")
if ($Version -and $ResolvedVersion -ne $Version) {
    Fail "requested version $Version but release tag is $Tag"
}

$Asset = "kigi-$ResolvedVersion-$Triple.zip"
$ArchiveAsset = $Release.assets | Where-Object { $_.name -eq $Asset } | Select-Object -First 1
$SumsAsset = $Release.assets | Where-Object { $_.name -eq "SHA256SUMS" } | Select-Object -First 1
if (-not $ArchiveAsset) { Fail "release $Tag has no asset $Asset" }
if (-not $SumsAsset) { Fail "release $Tag has no SHA256SUMS asset; refusing to install unverified binaries" }

# ── Download + verify ────────────────────────────────────────────────────────
$TmpDir = Join-Path ([System.IO.Path]::GetTempPath()) ("kigi-install-" + [System.IO.Path]::GetRandomFileName())
New-Item -ItemType Directory -Path $TmpDir -Force | Out-Null
try {
    $ArchivePath = Join-Path $TmpDir $Asset
    $SumsPath = Join-Path $TmpDir "SHA256SUMS"

    Write-Host "Downloading kigi v$ResolvedVersion ($Triple)..."
    Invoke-WebRequest -Uri $ArchiveAsset.browser_download_url -Headers $Headers -OutFile $ArchivePath
    Invoke-WebRequest -Uri $SumsAsset.browser_download_url -Headers $Headers -OutFile $SumsPath

    $Expected = $null
    foreach ($line in Get-Content $SumsPath) {
        $parts = $line.Trim() -split '\s+', 2
        if ($parts.Count -eq 2 -and $parts[1].TrimStart('*') -eq $Asset) {
            $Expected = $parts[0].ToLowerInvariant()
        }
    }
    if (-not $Expected) { Fail "SHA256SUMS has no entry for $Asset" }

    $Actual = (Get-FileHash -Algorithm SHA256 -Path $ArchivePath).Hash.ToLowerInvariant()
    if ($Actual -ne $Expected) {
        Fail "SHA256 mismatch for ${Asset}: expected $Expected, got $Actual"
    }
    Write-Host "Checksum verified."

    # ── Extract + install ────────────────────────────────────────────────────
    $ExtractDir = Join-Path $TmpDir "extracted"
    Expand-Archive -Path $ArchivePath -DestinationPath $ExtractDir -Force
    $Binary = Get-ChildItem -Path $ExtractDir -Recurse -Filter "kigi.exe" | Select-Object -First 1
    if (-not $Binary) { Fail "archive $Asset does not contain kigi.exe" }

    $BinDir = Join-Path $KigiHome "bin"
    New-Item -ItemType Directory -Path $BinDir -Force | Out-Null
    $Dest = Join-Path $BinDir "kigi.exe"

    # A running kigi.exe blocks writes but allows renames — move it aside
    # first (mirrors the self-updater's windows_replace_exe strategy).
    if (Test-Path $Dest) {
        $Aside = "$Dest.old"
        Remove-Item -Path $Aside -Force -ErrorAction SilentlyContinue
        try {
            Move-Item -Path $Dest -Destination $Aside -Force
        } catch {
            Fail "cannot replace $Dest (close all running kigi sessions and retry): $($_.Exception.Message)"
        }
    }
    Move-Item -Path $Binary.FullName -Destination $Dest -Force

    # Smoke-test the installed binary.
    & $Dest --version *> $null
    if ($LASTEXITCODE -ne 0) {
        Fail "installed binary failed to run (exit $LASTEXITCODE)"
    }

    Write-Host ""
    Write-Host "kigi v$ResolvedVersion installed to $Dest"

    # -contains instead of Where-Object/.Count: under Set-StrictMode, .Count
    # on an empty (null) filter result throws PropertyNotFoundStrict — which
    # fired on every fresh install, since that's exactly the not-on-PATH case.
    $UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
    $OnPath = (($UserPath -split ";") -contains $BinDir) -or
              (($env:Path -split ";") -contains $BinDir)
    if (-not $OnPath) {
        # Persist the bin dir on the per-user PATH so the user doesn't have
        # to. Registry-backed; every new terminal picks it up automatically.
        $NewUserPath = if ($UserPath) { "$BinDir;$UserPath" } else { $BinDir }
        [Environment]::SetEnvironmentVariable("Path", $NewUserPath, "User")
        Write-Host ""
        Write-Host "Added $BinDir to your user PATH."
        Write-Host "Open a new terminal, then run 'kigi' to get started."
    } else {
        Write-Host "Run 'kigi' to get started."
    }

    # Graph engineering is enabled by default IN THE BINARY (resolve_graph
    # defaults true) — no environment plumbing needed. The installer used
    # to persist KIGI_GRAPH=1 into the User registry env, but running
    # terminals (and new tabs of an open Windows Terminal) never pick up
    # freshly-written registry variables, which made /graph "missing on
    # Windows" while the shell-rc path worked on macOS/Linux. Opt out any
    # time with: [Environment]::SetEnvironmentVariable('KIGI_GRAPH','0','User')
} finally {
    Remove-Item -Path $TmpDir -Recurse -Force -ErrorAction SilentlyContinue
}
