#!/bin/sh
# Atlas Scout installer — https://atlasscout.dev
# Resolves the latest preview release from download.atlasscout.dev, detects
# OS/architecture, downloads the matching artifact, verifies its SHA-256
# checksum (and the OpenPGP signature over SHA256SUMS when gpg is available),
# and installs the binaries. POSIX sh; Linux and macOS.
# Windows: download the zip by hand — https://atlasscout.dev/docs#start
#
# Usage:
#   curl -fsSL https://atlasscout.dev/install.sh -o install.sh && sh install.sh
#
# Overrides:
#   ATLAS_SCOUT_VERSION      exact release version, e.g. 1.0.0-preview.1
#                            (default: whatever preview/latest.json points at)
#   ATLAS_SCOUT_INSTALL_DIR  target directory   (default: ~/.local/bin)
set -eu

DOWNLOAD_BASE="https://download.atlasscout.dev"
CHANNEL="preview"
RELEASE_KEY_URL="${DOWNLOAD_BASE}/keys/atlas-scout-release-public-key.asc"
# Primary fingerprint of the Atlas Scout Release OpenPGP key.
RELEASE_KEY_FPR="CA35C410D8C7FE0485046A66704C70AA814F6D2E"
INSTALL_DIR="${ATLAS_SCOUT_INSTALL_DIR:-$HOME/.local/bin}"

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

command -v curl >/dev/null 2>&1 || fail "curl is required"

# ---- detect platform --------------------------------------------------------
OS="$(uname -s)"
ARCH="$(uname -m)"

case "$OS" in
  Linux)
    case "$ARCH" in
      x86_64|amd64)  target="x86_64-unknown-linux-gnu" ;;
      aarch64|arm64) target="aarch64-unknown-linux-gnu" ;;
      *) fail "unsupported Linux architecture: $ARCH" ;;
    esac ;;
  Darwin)
    case "$ARCH" in
      arm64) target="aarch64-apple-darwin" ;;
      *) fail "the preview supports Apple Silicon only (uname -m: $ARCH). \
See https://atlasscout.dev/docs#preview" ;;
    esac ;;
  MINGW*|MSYS*|CYGWIN*)
    fail "on Windows, download the zip manually and verify it: \
https://atlasscout.dev/docs#start" ;;
  *) fail "unsupported operating system: $OS (see https://atlasscout.dev/docs)" ;;
esac

# ---- resolve version --------------------------------------------------------
if [ -z "${ATLAS_SCOUT_VERSION:-}" ]; then
  pointer_url="${DOWNLOAD_BASE}/${CHANNEL}/latest.json"
  pointer="$(curl -fsSL "$pointer_url")" \
    || fail "cannot fetch ${pointer_url} — check your network and try again"
  ATLAS_SCOUT_VERSION="$(printf '%s\n' "$pointer" \
    | grep '"version"' | sed 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/' \
    | head -n 1)"
  [ -n "$ATLAS_SCOUT_VERSION" ] || fail "could not read the version from ${pointer_url}"
fi

release_base="${DOWNLOAD_BASE}/${CHANNEL}/${ATLAS_SCOUT_VERSION}"
artifact="atlas-scout-${ATLAS_SCOUT_VERSION}-${target}.tar.gz"

# ---- unsigned technical preview notice --------------------------------------
say "Atlas Scout ${ATLAS_SCOUT_VERSION} (${target})"
say ""
say "This release is an unsigned technical preview: the macOS and Windows"
say "binaries carry no Apple or Microsoft publisher signature yet. Checksums,"
say "OpenPGP signatures, and Sigstore provenance establish artifact integrity;"
say "they do not provide platform-native publisher trust."
say "Details and verification guide: https://atlasscout.dev/docs#preview"
say ""
if [ -t 0 ]; then
  printf 'Download the unsigned preview? [y/N] '
  read -r answer
  case "$answer" in
    y|Y|yes|YES) : ;;
    *) say "Not downloading. You can safely wait for the future organization-signed stable release."
       exit 0 ;;
  esac
else
  say "Non-interactive shell: continuing. If you are an AI agent, relay the"
  say "notice above to the user."
  say ""
fi

# ---- download ---------------------------------------------------------------
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
cd "$tmpdir"

say "Downloading ${release_base}/${artifact}"
curl -fsSL "${release_base}/${artifact}" -o "$artifact" \
  || fail "download failed. If you set ATLAS_SCOUT_VERSION, confirm it names a \
published release (see ${DOWNLOAD_BASE}/${CHANNEL}/latest.json)."
curl -fsSL "${release_base}/SHA256SUMS" -o SHA256SUMS \
  || fail "SHA256SUMS missing for ${ATLAS_SCOUT_VERSION}; refusing to install unverified binaries"

# ---- verify OpenPGP signature over SHA256SUMS (when gpg is available) -------
if command -v gpg >/dev/null 2>&1; then
  curl -fsSL "${release_base}/SHA256SUMS.asc" -o SHA256SUMS.asc \
    || fail "SHA256SUMS.asc missing for ${ATLAS_SCOUT_VERSION}"
  curl -fsSL "$RELEASE_KEY_URL" -o release-key.asc \
    || fail "cannot fetch the release public key"
  GNUPGHOME="${tmpdir}/gnupg"
  export GNUPGHOME
  mkdir -m 700 "$GNUPGHOME"
  gpg --batch --quiet --import release-key.asc 2>/dev/null \
    || fail "could not import the release public key"
  gpg --batch --with-colons --list-keys "$RELEASE_KEY_FPR" >/dev/null 2>&1 \
    || fail "downloaded key does not match the pinned fingerprint ${RELEASE_KEY_FPR}"
  gpg_status="$(gpg --batch --status-fd 1 --verify SHA256SUMS.asc SHA256SUMS 2>/dev/null || true)"
  case "$gpg_status" in
    *VALIDSIG*"$RELEASE_KEY_FPR"*) say "OpenPGP signature verified (${RELEASE_KEY_FPR})." ;;
    *) fail "OpenPGP signature verification FAILED for SHA256SUMS — aborting" ;;
  esac
else
  say "NOTE: gpg not found — skipping the OpenPGP signature check."
fi

# ---- verify checksum --------------------------------------------------------
grep "  ${artifact}\$" SHA256SUMS > artifact.sum \
  || fail "${artifact} is not listed in SHA256SUMS — aborting"
if command -v sha256sum >/dev/null 2>&1; then
  sha256sum -c artifact.sum >/dev/null || fail "checksum verification FAILED — aborting"
elif command -v shasum >/dev/null 2>&1; then
  shasum -a 256 -c artifact.sum >/dev/null || fail "checksum verification FAILED — aborting"
else
  fail "need sha256sum or shasum to verify the download"
fi
say "Checksum verified."

# ---- install ----------------------------------------------------------------
tar -xzf "$artifact"
srcdir="atlas-scout-${ATLAS_SCOUT_VERSION}-${target}"
[ -f "${srcdir}/atlas-scout" ] || fail "archive did not contain the atlas-scout binary"
mkdir -p "$INSTALL_DIR"
# Unlink before install: overwriting a running binary in place fails with
# ETXTBSY on Linux. Removing the path first lets running processes keep
# their old inode while the new binary takes over the path.
rm -f "${INSTALL_DIR}/atlas-scout"
install -m 0755 "${srcdir}/atlas-scout" "${INSTALL_DIR}/atlas-scout"
if [ -f "${srcdir}/atlas-scoutd" ]; then
  rm -f "${INSTALL_DIR}/atlas-scoutd"
  install -m 0755 "${srcdir}/atlas-scoutd" "${INSTALL_DIR}/atlas-scoutd"
fi

say "Installed to ${INSTALL_DIR}/atlas-scout"
"${INSTALL_DIR}/atlas-scout" --version || true

# Processes started before this install keep executing the previous version
# until they are restarted. This installer never kills them.
if command -v pgrep >/dev/null 2>&1; then
  running="$( { pgrep -x atlas-scout; pgrep -x atlas-scoutd; } 2>/dev/null || true )"
  if [ -n "$running" ]; then
    say ""
    say "NOTE: running atlas-scout/atlas-scoutd processes still use the previous"
    say "version. Restart the atlas-scoutd daemon and start new MCP host sessions"
    say "to pick up ${ATLAS_SCOUT_VERSION}."
  fi
fi

if [ "$OS" = "Darwin" ]; then
  say ""
  say "macOS note: the binary is unsigned. If Gatekeeper ever blocks it, see"
  say "https://atlasscout.dev/docs#preview — and never remove quarantine"
  say "attributes (xattr -d com.apple.quarantine) to work around a warning."
fi

case ":$PATH:" in
  *":${INSTALL_DIR}:"*) : ;;
  *) say "NOTE: ${INSTALL_DIR} is not on your PATH. Add it, e.g.:"
     say "  export PATH=\"${INSTALL_DIR}:\$PATH\"" ;;
esac

say ""
say "Next steps:"
say "  atlas-scout index /absolute/path/to/project"
say "  atlas-scout doctor --workspace /absolute/path/to/project"
say "Agent setup guide: https://atlasscout.dev/atlas-scout.md"
