#!/bin/sh
# install.sh — Kami CLI installer (POSIX sh).
#
# Served two ways from get.leistenmacher.de:
#   • per-CLI (recommended):  curl -fsSL https://get.leistenmacher.de/<cli>/install.sh | bash
#   • generic:                curl -fsSL https://get.leistenmacher.de/install.sh | bash -s -- <cli>
#
# This is a TEMPLATE: umami is replaced at publish time — with the CLI
# name for each per-CLI copy, and with nothing for the generic root copy.
#
# Asset layout expected:
#   <BASE_URL>/<cli>/<version>/<cli>-<target>.tar.gz   +   .../SHA256SUMS
# targets: x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu
#          x86_64-apple-darwin aarch64-apple-darwin
# (Windows is install.ps1.) Each .tar.gz holds <cli>-<target>/<cli>.
#
# Env knobs: KAMI_BASE_URL, KAMI_INSTALL_DIR, KAMI_VERSION, KAMI_NO_MODIFY_PATH=1
set -u

# ---- configuration -----------------------------------------------------------
KAMI_BASE_URL="${KAMI_BASE_URL:-https://get.leistenmacher.de}"
KAMI_CLIS="excalidraw listmonk opencode-ctl sish-ctl solidtime umami qcal qcard"

# ---- tiny helpers (lifted from rustup-init.sh) -------------------------------
say()  { printf 'kami-install: %s\n' "$1" >&2; }
warn() { printf 'kami-install: warning: %s\n' "$1" >&2; }
err()  { printf 'kami-install: error: %s\n' "$1" >&2; exit 1; }
check_cmd() { command -v "$1" >/dev/null 2>&1; }
need_cmd()  { check_cmd "$1" || err "need '$1' (command not found)"; }
ensure()    { "$@" || err "command failed: $*"; }

# ---- which CLI? --------------------------------------------------------------
# Per-CLI installers bake the name into umami; the generic one leaves it
# empty and takes the CLI as the first argument.
CLI="${1:-${KAMI_CLI:-umami}}"
VERSION="${2:-${KAMI_VERSION:-latest}}"
[ -n "$CLI" ] || err "no CLI selected.
        Use a per-CLI installer:  curl -fsSL $KAMI_BASE_URL/<cli>/install.sh | bash
        (cli is one of: $KAMI_CLIS)"
_ok=0; for c in $KAMI_CLIS; do [ "$c" = "$CLI" ] && _ok=1; done
[ "$_ok" = 1 ] || err "unknown CLI '$CLI'. Valid: $KAMI_CLIS"

# ---- OS/arch detection -> our target triple ----------------------------------
detect_target() {
    _os="$(uname -s)"; _cpu="$(uname -m)"
    case "$_os" in
        Linux)
            # We only ship glibc (-gnu) Linux assets. Refuse on musl-only hosts.
            if check_cmd ldd && ldd --version 2>&1 | grep -qi musl; then
                err "musl libc detected (e.g. Alpine). Kami ships glibc binaries only.
        Run inside a glibc container or build from source."
            fi
            case "$_cpu" in
                x86_64|x86-64|x64|amd64) TARGET="x86_64-unknown-linux-gnu" ;;
                aarch64|arm64)           TARGET="aarch64-unknown-linux-gnu" ;;
                *) err "unsupported CPU architecture: $_cpu" ;;
            esac ;;
        Darwin)
            _os_part="apple-darwin"
            # Apple Silicon under a Rosetta x86_64 shell still reports x86_64 —
            # probe and prefer the native arm64 build.
            if [ "$_cpu" = "x86_64" ] && sysctl -n hw.optional.arm64 2>/dev/null | grep -q '^1$'; then
                _cpu="arm64"
            fi
            case "$_cpu" in
                x86_64|x86-64|x64|amd64) TARGET="x86_64-apple-darwin" ;;
                aarch64|arm64)           TARGET="aarch64-apple-darwin" ;;
                *) err "unsupported CPU architecture: $_cpu" ;;
            esac ;;
        MINGW*|MSYS*|CYGWIN*|Windows_NT)
            err "Windows detected — use the PowerShell installer:
        irm $KAMI_BASE_URL/$CLI/install.ps1 | iex" ;;
        *) err "unsupported OS: $_os" ;;
    esac
}

# ---- downloader (TLS 1.2 enforced, curl or wget) -----------------------------
download() { # url, dest
    if check_cmd curl; then
        curl --proto '=https' --tlsv1.2 -fsSL "$1" -o "$2"
    elif check_cmd wget; then
        wget --https-only --secure-protocol=TLSv1_2 -q "$1" -O "$2"
    else
        err "need curl or wget to download"
    fi
}

# ---- checksum verification (sha256sum, with macOS shasum fallback) -----------
sha256_of() { # file -> prints hex
    if check_cmd sha256sum; then sha256sum -b "$1" | awk '{print $1}'
    elif check_cmd shasum;   then shasum -a 256 "$1" | awk '{print $1}'
    else return 1; fi
}
verify_checksum() { # file, sumsfile, asset_name
    _want="$(grep " \*\{0,1\}$3\$" "$2" | awk '{print $1}' | head -n1)"
    [ -n "$_want" ] || err "no checksum for $3 in SHA256SUMS"
    _got="$(sha256_of "$1")" || { warn "no sha256 tool; skipping verification"; return 0; }
    [ "$_got" = "$_want" ] || err "checksum mismatch for $3
        want: $_want
        got:  $_got"
    say "checksum OK ($3)"
}

# ---- install-dir selection (no sudo by default) ------------------------------
choose_install_dir() {
    if [ -n "${KAMI_INSTALL_DIR:-}" ]; then INSTALL_DIR="$KAMI_INSTALL_DIR"
    else INSTALL_DIR="$HOME/.local/bin"; fi
    ensure mkdir -p "$INSTALL_DIR"
    [ -w "$INSTALL_DIR" ] || err "install dir not writable: $INSTALL_DIR
        Set KAMI_INSTALL_DIR=/some/writable/path and retry."
}

# ---- PATH update via sourced env file (cargo-dist idiom) ---------------------
maybe_modify_path() {
    case ":${PATH}:" in *:"$INSTALL_DIR":*) return 0 ;; esac   # already on PATH
    [ -z "${KAMI_NO_MODIFY_PATH:-}" ] || { say "added; ensure $INSTALL_DIR is on PATH"; return 0; }
    _env="$INSTALL_DIR/env"
    if [ ! -f "$_env" ]; then
        cat > "$_env" <<EOF
#!/bin/sh
case ":\${PATH}:" in
    *:"$INSTALL_DIR":*) ;;
    *) export PATH="$INSTALL_DIR:\$PATH" ;;
esac
EOF
    fi
    for rc in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile"; do
        [ -f "$rc" ] || continue
        grep -qF ". \"$_env\"" "$rc" 2>/dev/null && continue
        printf '\n. "%s"\n' "$_env" >> "$rc"
    done
    say "added $INSTALL_DIR to PATH (restart shell or: . \"$_env\")"
}

# ---- main --------------------------------------------------------------------
main() {
    need_cmd uname; need_cmd tar; need_cmd mkdir; need_cmd awk
    detect_target
    ASSET="${CLI}-${TARGET}.tar.gz"
    REL="$KAMI_BASE_URL/$CLI/$VERSION"
    say "installing $CLI ($VERSION) for $TARGET"

    TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT
    download "$REL/$ASSET"     "$TMP/$ASSET"     || err "download failed: $REL/$ASSET"
    download "$REL/SHA256SUMS" "$TMP/SHA256SUMS" || err "download failed: $REL/SHA256SUMS"
    verify_checksum "$TMP/$ASSET" "$TMP/SHA256SUMS" "$ASSET"

    ensure tar xf "$TMP/$ASSET" --no-same-owner --strip-components 1 -C "$TMP"
    [ -f "$TMP/$CLI" ] || err "binary '$CLI' not found in archive"

    choose_install_dir
    ensure install -m 0755 "$TMP/$CLI" "$INSTALL_DIR/$CLI"
    say "installed $INSTALL_DIR/$CLI"
    maybe_modify_path
    say "done. run: $CLI --help"
}
main "$@"
