#!/usr/bin/env bash
set -euo pipefail

BASE="https://getstream.io/cli"
BIN_DIR="${STREAM_CLI_BIN_DIR:-$HOME/.local/bin}"
CHANNEL="${STREAM_CLI_CHANNEL:-}"

die() { echo "error: $*" >&2; exit 1; }

_curl() {
  # shellcheck disable=SC2086
  curl -fsSL ${STREAM_CLI_CURL_FLAGS:-} "$@"
}

for arg in "$@"; do
  case "$arg" in
    -h|--help)
      cat <<'HELP'
usage: install.sh

  Installs the Stream CLI as `getstream`.

  Environment:
    STREAM_CLI_BIN_DIR     install directory (default ~/.local/bin)
    STREAM_CLI_CHANNEL     release channel (default stable)
    STREAM_CLI_LATEST_URL  full manifest URL, overriding base + channel
    STREAM_CLI_CURL_FLAGS  extra curl flags
HELP
      exit 0
      ;;
    *) die "unknown argument: $arg" ;;
  esac
done

OS=$(uname -s)
ARCH=$(uname -m)
case "$OS/$ARCH" in
  Darwin/arm64)  PLATFORM=darwin_arm64 ;;
  Darwin/x86_64) PLATFORM=darwin_amd64 ;;
  Linux/x86_64)  PLATFORM=linux_amd64  ;;
  Linux/aarch64) PLATFORM=linux_arm64  ;;
  *) die "unsupported platform: $OS/$ARCH (supported: macOS arm64/x86_64, Linux x86_64/arm64)" ;;
esac

# Resolve the manifest URL: an explicit STREAM_CLI_LATEST_URL wins; otherwise
# a named channel is a subdirectory of the base, and stable is the base root.
if [[ -n "${STREAM_CLI_LATEST_URL:-}" ]]; then
  MANIFEST_URL="$STREAM_CLI_LATEST_URL"
elif [[ -n "$CHANNEL" ]]; then
  MANIFEST_URL="$BASE/$CHANNEL/latest.json"
else
  MANIFEST_URL="$BASE/latest.json"
fi

TMP=$(mktemp -d "${TMPDIR:-/tmp}/getstream.XXXXXXXX")
trap 'rm -rf "$TMP"' EXIT

_curl "$MANIFEST_URL" -o "$TMP/latest.json" || die "could not fetch the release manifest: $MANIFEST_URL"

# latest.json is the single source of truth for the version, the binary URL,
# and its checksum. These extractors assume the pretty-printed (one field per
# line) manifest the release pipeline emits.
VERSION=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$TMP/latest.json" | head -1)
read -r URL SHA <<EOF
$(awk -v key="$PLATFORM" '
  index($0, "\"" key "\"") { inblk = 1; next }
  inblk && /"url"/    { v = $0; sub(/.*"url"[[:space:]]*:[[:space:]]*"/, "", v);    sub(/".*/, "", v); url = v }
  inblk && /"sha256"/ { v = $0; sub(/.*"sha256"[[:space:]]*:[[:space:]]*"/, "", v); sub(/".*/, "", v); print url, v; exit }
' "$TMP/latest.json")
EOF
[[ -n "$VERSION" ]] || die "release manifest has no version"
[[ -n "$URL" && -n "$SHA" ]] || die "release $VERSION has no $PLATFORM build"

# Resolve a relative binary URL against the manifest URL, as the binary does.
case "$URL" in
  http://*|https://*) ;;
  /*) ORIGIN=$(printf '%s' "$MANIFEST_URL" | sed -E 's#^([a-zA-Z][a-zA-Z0-9+.-]*://[^/]+).*#\1#'); URL="$ORIGIN$URL" ;;
  *)  URL="${MANIFEST_URL%/*}/$URL" ;;
esac

echo "Installing Stream CLI $VERSION ($PLATFORM)..." >&2

_curl "$URL" -o "$TMP/getstream" || die "could not download $URL"

if command -v shasum >/dev/null 2>&1; then
  GOT=$(shasum -a 256 "$TMP/getstream" | awk '{print $1}')
elif command -v sha256sum >/dev/null 2>&1; then
  GOT=$(sha256sum "$TMP/getstream" | awk '{print $1}')
else
  die "need shasum or sha256sum to verify the download"
fi
# Compare case-insensitively, matching the binary's checksum check.
[[ "$(printf '%s' "$GOT" | tr 'A-Z' 'a-z')" == "$(printf '%s' "$SHA" | tr 'A-Z' 'a-z')" ]] \
  || die "checksum mismatch (got $GOT, want $SHA)"
echo "Checksum verified." >&2

chmod +x "$TMP/getstream"
mkdir -p "$BIN_DIR" || die "could not create $BIN_DIR"
install -m 0755 "$TMP/getstream" "$BIN_DIR/getstream" || die "could not install to $BIN_DIR/getstream"

echo "Stream CLI installed and available at:" >&2
echo "  $BIN_DIR/getstream" >&2

echo "" >&2
echo "To get started:" >&2
echo "  getstream init" >&2
echo "" >&2
echo "To install the Stream skills:" >&2
echo "  getstream skills" >&2

# Make sure $BIN_DIR is on PATH for future shells.
case ":${PATH:-}:" in
  *":$BIN_DIR:"*) exit 0 ;;
esac

SHELL_NAME=$(basename "${SHELL:-}")
PROFILE=""
EXPORT_LINE="case \":\$PATH:\" in *\":$BIN_DIR:\"*) ;; *) export PATH=\"$BIN_DIR:\$PATH\" ;; esac"

case "$SHELL_NAME" in
  bash)
    if [[ -f "$HOME/.bashrc" ]]; then
      PROFILE="$HOME/.bashrc"
    elif [[ -f "$HOME/.bash_profile" ]]; then
      PROFILE="$HOME/.bash_profile"
    else
      PROFILE="$HOME/.profile"
    fi
    ;;
  zsh)
    PROFILE="${ZDOTDIR:-$HOME}/.zshrc"
    ;;
  fish)
    PROFILE="$HOME/.config/fish/config.fish"
    EXPORT_LINE="fish_add_path \"$BIN_DIR\""
    ;;
esac

MARKER="# Stream CLI"
PROFILE_UPDATED=0
if [[ -n "$PROFILE" ]]; then
  if [[ -f "$PROFILE" ]] && grep -Fq "$MARKER" "$PROFILE" 2>/dev/null; then
    PROFILE_UPDATED=1
  elif mkdir -p "$(dirname "$PROFILE")" 2>/dev/null \
    && printf '\n%s\n%s\n' "$MARKER" "$EXPORT_LINE" >> "$PROFILE" 2>/dev/null; then
    PROFILE_UPDATED=1
  fi
fi

echo "" >&2
if [[ $PROFILE_UPDATED -eq 1 ]]; then
  echo "Added $BIN_DIR to your PATH in $PROFILE (new shells only)." >&2
  echo "Use it now with $BIN_DIR/getstream, or reload: source \"$PROFILE\"" >&2
else
  echo "Warning: $BIN_DIR is not on your PATH, and your shell profile could not be updated." >&2
  echo "Use it now with $BIN_DIR/getstream, or add $BIN_DIR to your PATH:" >&2
  echo "  $EXPORT_LINE" >&2
fi
