#!/bin/sh
# scout installer — https://glidermcp.com/install.sh
#
# Installs the scout native binary (universal read-only code-intelligence MCP
# server) from the public release archives on github.com/glidermcp/scout.
# No Node, no .NET, no package manager required. Usage:
#
#   curl -fsSL https://glidermcp.com/install.sh | sh
#
# Environment overrides:
#   SCOUT_VERSION      install this version instead of the latest release
#   SCOUT_INSTALL_DIR  install directory (default: ~/.local/bin); never sudo
#   SCOUT_BASE_URL     alternate download base (mirrors, tests)
#   SCOUT_ALLOW_HTTP   test-only: permit a plain-http SCOUT_BASE_URL
#
# Everything happens inside main(), invoked on the last line — a truncated
# download parses but executes nothing.

set -eu

fetch() {
  # TLS-pinned by default (rustup style); SCOUT_ALLOW_HTTP exists so CI can
  # drive the full flow against a loopback fixture server.
  if [ "${SCOUT_ALLOW_HTTP:-}" = '1' ]; then
    curl -fsSL "$@"
  else
    curl --proto '=https' --tlsv1.2 -fsSL "$@"
  fi
}

fail() {
  printf 'scout install: %s\n' "$1" >&2
  exit 1
}

main() {
  command -v curl >/dev/null 2>&1 || fail 'curl is required'
  command -v tar >/dev/null 2>&1 || fail 'tar is required'
  command -v awk >/dev/null 2>&1 || fail 'awk is required'

  # The plain-http hatch exists only for CI's loopback fixture server; refuse
  # it for anything that could leave the machine.
  if [ "${SCOUT_ALLOW_HTTP:-}" = '1' ]; then
    case "${SCOUT_BASE_URL:-}" in
      http://127.0.0.1:* | http://127.0.0.1/* | http://localhost:* | http://localhost/*) ;;
      *) fail 'SCOUT_ALLOW_HTTP is test-only and requires a loopback http SCOUT_BASE_URL' ;;
    esac
  fi

  case "$(uname -s)" in
    Linux) os='linux' ;;
    Darwin) os='darwin' ;;
    *)
      fail "unsupported platform '$(uname -s)'. On Windows (or any machine with Node), use: npx @glidermcp/scout"
      ;;
  esac
  case "$(uname -m)" in
    x86_64 | amd64) arch='x64' ;;
    aarch64 | arm64) arch='arm64' ;;
    *)
      fail "unsupported architecture '$(uname -m)'. Supported: x64, arm64. With Node available, use: npx @glidermcp/scout"
      ;;
  esac

  version="${SCOUT_VERSION:-}"
  if [ -z "$version" ]; then
    # Dedicated public repo -> /releases/latest is always a scout release.
    version="$(fetch https://api.github.com/repos/glidermcp/scout/releases/latest |
      sed -n 's/.*"tag_name": *"scout-v\([0-9][0-9.]*\)".*/\1/p' | head -n 1)"
    [ -n "$version" ] || fail 'could not determine the latest scout version (set SCOUT_VERSION to pin one)'
  fi
  # Accept tag-shaped overrides (SCOUT_VERSION=v0.1.0 or scout-v0.1.0).
  version="${version#scout-v}"
  version="${version#v}"

  base_url="${SCOUT_BASE_URL:-https://github.com/glidermcp/scout/releases/download}"
  archive="scout-$os-$arch-v$version.tar.gz"
  install_dir="${SCOUT_INSTALL_DIR:-$HOME/.local/bin}"

  tmp="$(mktemp -d)"
  trap 'rm -rf "$tmp"' EXIT INT TERM

  printf 'Downloading scout %s (%s-%s)...\n' "$version" "$os" "$arch"
  fetch -o "$tmp/$archive" "$base_url/scout-v$version/$archive"
  fetch -o "$tmp/SHA256SUMS" "$base_url/scout-v$version/SHA256SUMS"

  # Compare hashes directly instead of `-c`: sum files vary between
  # `hash  name` and binary-mode `hash *name`, and awk field matching
  # accepts both.
  expected="$(awk -v name="$archive" '$2 == name || $2 == "*" name { print $1; exit }' "$tmp/SHA256SUMS")"
  [ -n "$expected" ] || fail "SHA256SUMS has no entry for $archive"
  if command -v sha256sum >/dev/null 2>&1; then
    actual="$(sha256sum "$tmp/$archive" | awk '{print $1}')"
  elif command -v shasum >/dev/null 2>&1; then
    actual="$(shasum -a 256 "$tmp/$archive" | awk '{print $1}')"
  else
    fail 'neither sha256sum nor shasum is available to verify the download'
  fi
  [ "$actual" = "$expected" ] || fail "checksum verification failed for $archive"

  tar -xzf "$tmp/$archive" -C "$tmp" scout
  mkdir -p "$install_dir"
  # mv, not cp: replacing a running binary in place fails on some systems.
  mv -f "$tmp/scout" "$install_dir/scout"
  chmod 755 "$install_dir/scout"

  printf 'Installed %s\n' "$install_dir/scout"
  case ":$PATH:" in
    *":$install_dir:"*) ;;
    *)
      printf '\nNote: %s is not on your PATH. Add it with:\n' "$install_dir"
      # The hint must print a literal $PATH:
      # shellcheck disable=SC2016
      printf '  export PATH="%s:$PATH"\n\n' "$install_dir"
      ;;
  esac
  "$install_dir/scout" --version
}

main "$@"
