#!/bin/sh
#
# Kigi installer (macOS / Linux) — PRD F8.
#
# Downloads the matching platform artifact from this repo's GitHub Releases,
# verifies its SHA-256 against the release's SHA256SUMS manifest, and installs
# the binary as ~/.kigi/bin/kigi (the same managed layout the self-updater
# maintains: versioned binary in ~/.kigi/downloads/, atomic symlink in bin/).
#
# Usage:
#   curl -fsSL https://raw.githubusercontent.com/ZacharyZhang-NY/Kigi-CLI/main/install.sh | sh
#   sh install.sh --version v0.1.0        # pin a specific release
#
# Environment:
#   KIGI_SHARE_DIR        install root (default: ~/.kigi)
#   KIGI_UPDATE_BASE_URL  GitHub-Releases-shaped API base (default:
#                         https://api.github.com/repos/ZacharyZhang-NY/Kigi-CLI/releases)
#
# Fails fast on any error; never leaves a partial binary as the active kigi.

set -eu

REPO="ZacharyZhang-NY/Kigi-CLI"
API_BASE="${KIGI_UPDATE_BASE_URL:-https://api.github.com/repos/${REPO}/releases}"
KIGI_HOME="${KIGI_SHARE_DIR:-$HOME/.kigi}"

err() {
    printf 'install.sh: error: %s\n' "$*" >&2
    exit 1
}

usage() {
    sed -n '2,20p' "$0" 2>/dev/null | sed 's/^# \{0,1\}//'
}

# ── Arguments ────────────────────────────────────────────────────────────────
VERSION=""
while [ $# -gt 0 ]; do
    case "$1" in
        --version)
            [ $# -ge 2 ] || err "--version requires an argument (e.g. --version v0.1.0)"
            VERSION="$2"
            shift
            ;;
        --version=*)
            VERSION="${1#--version=}"
            ;;
        -h|--help)
            usage
            exit 0
            ;;
        *)
            err "unknown argument: $1 (supported: --version vX.Y.Z)"
            ;;
    esac
    shift
done
VERSION="${VERSION#v}"
if [ -n "$VERSION" ]; then
    case "$VERSION" in
        [0-9]*.[0-9]*.[0-9]*) ;;
        *) err "invalid version '$VERSION' (expected X.Y.Z or vX.Y.Z)" ;;
    esac
fi

# ── Platform detection ───────────────────────────────────────────────────────
OS="$(uname -s)"
ARCH="$(uname -m)"
case "$OS" in
    Darwin)
        PLATFORM_OS="macos"
        case "$ARCH" in
            arm64|aarch64) TRIPLE="aarch64-apple-darwin"; PLATFORM_ARCH="aarch64" ;;
            x86_64)        TRIPLE="x86_64-apple-darwin";  PLATFORM_ARCH="x86_64" ;;
            *) err "unsupported macOS architecture: $ARCH" ;;
        esac
        ;;
    Linux)
        PLATFORM_OS="linux"
        case "$ARCH" in
            arm64|aarch64) TRIPLE="aarch64-unknown-linux-gnu"; PLATFORM_ARCH="aarch64" ;;
            x86_64|amd64)  TRIPLE="x86_64-unknown-linux-gnu";  PLATFORM_ARCH="x86_64" ;;
            *) err "unsupported Linux architecture: $ARCH" ;;
        esac
        ;;
    *)
        err "unsupported OS: $OS (Windows: use install.ps1)"
        ;;
esac

# ── Downloader ───────────────────────────────────────────────────────────────
if command -v curl >/dev/null 2>&1; then
    fetch()        { curl -fsSL -o "$2" "$1"; }
    fetch_stdout() { curl -fsSL "$1"; }
elif command -v wget >/dev/null 2>&1; then
    fetch()        { wget -q -O "$2" "$1"; }
    fetch_stdout() { wget -q -O - "$1"; }
else
    err "either curl or wget is required"
fi

# ── SHA-256 tool ─────────────────────────────────────────────────────────────
if command -v sha256sum >/dev/null 2>&1; then
    sha256_of() { sha256sum "$1" | cut -d' ' -f1; }
elif command -v shasum >/dev/null 2>&1; then
    sha256_of() { shasum -a 256 "$1" | cut -d' ' -f1; }
else
    err "either sha256sum or shasum is required to verify the download"
fi

TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/kigi-install.XXXXXX")"
trap 'rm -rf "$TMP_DIR"' EXIT INT TERM

# ── Resolve the release ──────────────────────────────────────────────────────
if [ -n "$VERSION" ]; then
    RELEASE_URL="$API_BASE/tags/v$VERSION"
else
    RELEASE_URL="$API_BASE/latest"
fi
printf 'Resolving release from %s\n' "$RELEASE_URL"
RELEASE_JSON="$(fetch_stdout "$RELEASE_URL")" \
    || err "could not fetch release metadata from $RELEASE_URL"

TAG="$(printf '%s' "$RELEASE_JSON" \
    | tr ',' '\n' \
    | sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
    | head -n 1)"
[ -n "$TAG" ] || err "release metadata has no tag_name (endpoint: $RELEASE_URL)"
RESOLVED_VERSION="${TAG#v}"
if [ -n "$VERSION" ] && [ "$RESOLVED_VERSION" != "$VERSION" ]; then
    err "requested version $VERSION but release tag is $TAG"
fi

ASSET="kigi-${RESOLVED_VERSION}-${TRIPLE}.tar.gz"

# Pull every browser_download_url out of the JSON, then select by asset name.
URLS="$(printf '%s' "$RELEASE_JSON" \
    | tr ',' '\n' \
    | sed -n 's/.*"browser_download_url"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')"
ARCHIVE_URL="$(printf '%s\n' "$URLS" | grep -F "/$ASSET" | head -n 1 || true)"
SUMS_URL="$(printf '%s\n' "$URLS" | grep -F "/SHA256SUMS" | head -n 1 || true)"
[ -n "$ARCHIVE_URL" ] || err "release $TAG has no asset $ASSET (this platform may not be published yet)"
[ -n "$SUMS_URL" ] || err "release $TAG has no SHA256SUMS asset; refusing to install unverified binaries"

# ── Download + verify ────────────────────────────────────────────────────────
printf 'Downloading kigi v%s (%s)...\n' "$RESOLVED_VERSION" "$TRIPLE"
fetch "$ARCHIVE_URL" "$TMP_DIR/$ASSET" || err "download failed: $ARCHIVE_URL"
fetch "$SUMS_URL" "$TMP_DIR/SHA256SUMS" || err "download failed: $SUMS_URL"

EXPECTED=""
while IFS=' 	' read -r hash name; do
    name="${name#\*}"
    if [ "$name" = "$ASSET" ]; then
        EXPECTED="$hash"
    fi
done < "$TMP_DIR/SHA256SUMS"
[ -n "$EXPECTED" ] || err "SHA256SUMS has no entry for $ASSET"

ACTUAL="$(sha256_of "$TMP_DIR/$ASSET")"
if [ "$ACTUAL" != "$EXPECTED" ]; then
    err "SHA256 mismatch for $ASSET: expected $EXPECTED, got $ACTUAL"
fi
printf 'Checksum verified.\n'

# ── Extract + install ────────────────────────────────────────────────────────
tar -xzf "$TMP_DIR/$ASSET" -C "$TMP_DIR" || err "failed to extract $ASSET"
[ -f "$TMP_DIR/kigi" ] || err "archive $ASSET does not contain a 'kigi' binary"
chmod 0755 "$TMP_DIR/kigi"

DOWNLOADS_DIR="$KIGI_HOME/downloads"
BIN_DIR="$KIGI_HOME/bin"
mkdir -p "$DOWNLOADS_DIR" "$BIN_DIR"

# Versioned binary + atomic symlink swap — the exact layout the self-updater
# maintains, so `kigi update` takes over seamlessly from here.
VERSIONED="kigi-${RESOLVED_VERSION}-${PLATFORM_OS}-${PLATFORM_ARCH}"
mv -f "$TMP_DIR/kigi" "$DOWNLOADS_DIR/$VERSIONED"

TMP_LINK="$BIN_DIR/kigi.install.$$"
ln -s "../downloads/$VERSIONED" "$TMP_LINK"
mv -f "$TMP_LINK" "$BIN_DIR/kigi"

# Smoke-test the installed binary through the managed link.
"$BIN_DIR/kigi" --version >/dev/null 2>&1 \
    || err "installed binary failed to run; your PATH still has no working kigi"

printf '\nkigi v%s installed to %s\n' "$RESOLVED_VERSION" "$BIN_DIR/kigi"

# Persist a line into an rc file. Idempotent via the grep guard; on write
# failure the manual command is printed and the script fails loudly (the
# binary itself is already installed).
persist_line() {
    rc="$1"
    line="$2"
    guard="$3"
    what="$4"
    if [ -f "$rc" ] && grep -qF "$guard" "$rc"; then
        printf '\n%s is already configured in %s.\n' "$what" "$rc"
        return 0
    fi
    printf '\n# Added by the kigi installer\n%s\n' "$line" >> "$rc" \
        || err "could not write $rc — configure it manually: $line"
    printf '\nAdded %s in %s.\n' "$what" "$rc"
}

# Resolve the login shell's rc file and env-line syntax once; PATH and
# feature-flag persistence below both write to the same place.
case "${SHELL:-}" in
    */zsh)
        RC_FILE="${ZDOTDIR:-$HOME}/.zshrc"
        PATH_LINE="export PATH=\"$BIN_DIR:\$PATH\""
        ;;
    */bash)
        # macOS login shells read ~/.bash_profile; Linux reads ~/.bashrc.
        if [ "$PLATFORM_OS" = "macos" ]; then
            RC_FILE="$HOME/.bash_profile"
        else
            RC_FILE="$HOME/.bashrc"
        fi
        PATH_LINE="export PATH=\"$BIN_DIR:\$PATH\""
        ;;
    */fish)
        # fish_add_path in config.fish is fish's own idempotent way
        # to persist a PATH entry.
        FISH_CONF_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/fish"
        mkdir -p "$FISH_CONF_DIR"
        RC_FILE="$FISH_CONF_DIR/config.fish"
        PATH_LINE="fish_add_path $BIN_DIR"
        ;;
    *)
        RC_FILE="$HOME/.profile"
        PATH_LINE="export PATH=\"$BIN_DIR:\$PATH\""
        ;;
esac

case ":$PATH:" in
    *":$BIN_DIR:"*)
        printf 'Run `kigi` to get started.\n'
        ;;
    *)
        persist_line "$RC_FILE" "$PATH_LINE" "$BIN_DIR" "$BIN_DIR (PATH)"
        printf 'Open a new terminal, then run `kigi` to get started.\n'
        ;;
esac

# Graph engineering is enabled by default IN THE BINARY (resolve_graph
# defaults true) — the installer no longer writes KIGI_GRAPH=1 into shell
# rc files (per-shell env plumbing was fragile and diverged per platform).
# Disable any time with:
#   echo 'export KIGI_GRAPH=0' >> <your shell rc>
