#!/bin/sh
# Glueprint CLI Installer
#
# Usage:
#   curl -fsSL https://install.glueprint.ai | sh
#   curl -fsSL https://install.glueprint.ai | sh -s -- --version 0.1.0
#
# Environment variables:
#   GLUEPRINT_INSTALL_DIR    Installation directory (default: ~/.glueprint/bin)
#   GLUEPRINT_VERSION        Version to install (default: latest)
#   GLUEPRINT_NO_MODIFY_PATH If set, skip PATH modification
#   GLUEPRINT_BASE_URL       Releases CDN base URL (default: https://releases.glueprint.ai)
#
# The committed default BASE_URL is production; the publish workflow rewrites
# it per environment when uploading this script to the CDN, so the staging
# copy installs from the staging CDN with no flags.

set -eu

BASE_URL="${GLUEPRINT_BASE_URL:-https://releases.glueprint.ai}"
INSTALL_DIR="${GLUEPRINT_INSTALL_DIR:-$HOME/.glueprint/bin}"
VERSION="${GLUEPRINT_VERSION:-}"
NO_MODIFY_PATH="${GLUEPRINT_NO_MODIFY_PATH:-}"

# --- Color output ---

setup_colors() {
  if [ -t 1 ] && [ "${TERM:-}" != "dumb" ]; then
    RED='\033[0;31m'
    GREEN='\033[0;32m'
    YELLOW='\033[0;33m'
    BLUE='\033[0;34m'
    BOLD='\033[1m'
    RESET='\033[0m'
  else
    RED=''
    GREEN=''
    YELLOW=''
    BLUE=''
    BOLD=''
    RESET=''
  fi
}

info() {
  printf "${BLUE}info${RESET}: %s\n" "$1"
}

success() {
  printf "${GREEN}success${RESET}: %s\n" "$1"
}

warn() {
  printf "${YELLOW}warning${RESET}: %s\n" "$1" >&2
}

error() {
  printf "${RED}error${RESET}: %s\n" "$1" >&2
  exit 1
}

# --- Argument parsing ---

parse_args() {
  while [ $# -gt 0 ]; do
    case "$1" in
      --version)
        VERSION="$2"
        shift 2
        ;;
      --install-dir)
        INSTALL_DIR="$2"
        shift 2
        ;;
      --base-url)
        BASE_URL="$2"
        shift 2
        ;;
      --no-modify-path)
        NO_MODIFY_PATH=1
        shift
        ;;
      --help)
        cat <<EOF
Glueprint CLI Installer

USAGE:
    curl -fsSL https://install.glueprint.ai | sh [-- OPTIONS]

OPTIONS:
    --version <VERSION>      Install a specific version (default: latest)
    --install-dir <DIR>      Installation directory (default: ~/.glueprint/bin)
    --base-url <URL>         Releases CDN base URL (default: https://releases.glueprint.ai)
    --no-modify-path         Don't modify shell profile PATH
    --help                   Show this help message

ENVIRONMENT VARIABLES:
    GLUEPRINT_INSTALL_DIR    Override installation directory
    GLUEPRINT_VERSION        Override version to install
    GLUEPRINT_NO_MODIFY_PATH If set, skip PATH modification
    GLUEPRINT_BASE_URL       Override releases CDN base URL
EOF
        exit 0
        ;;
      *)
        error "Unknown argument: $1. Use --help for usage."
        ;;
    esac
  done
}

# --- OS / Arch detection ---

detect_platform() {
  OS="$(uname -s)"
  ARCH="$(uname -m)"

  case "$OS" in
    Darwin)
      PLATFORM="apple-darwin"
      ;;
    Linux)
      PLATFORM="unknown-linux-gnu"
      ;;
    MINGW* | MSYS* | CYGWIN*)
      error "Windows is not supported by this installer. Download the zip instead:
  ${BASE_URL}/cli/glueprint-cli-<version>-x86_64-pc-windows-msvc.zip"
      ;;
    *)
      error "Unsupported operating system: $OS"
      ;;
  esac

  case "$ARCH" in
    x86_64 | amd64)
      ARCH="x86_64"
      ;;
    arm64 | aarch64)
      ARCH="aarch64"
      ;;
    *)
      error "Unsupported architecture: $ARCH"
      ;;
  esac

  TARGET="${ARCH}-${PLATFORM}"
  info "Detected platform: ${TARGET}"
}

# --- Download utility ---

check_command() {
  command -v "$1" >/dev/null 2>&1
}

download() {
  URL="$1"
  OUTPUT="$2"

  if check_command curl; then
    curl -fsSL --retry 3 "$URL" -o "$OUTPUT"
  elif check_command wget; then
    wget -q "$URL" -O "$OUTPUT"
  else
    error "Neither curl nor wget is available. Please install one and try again."
  fi
}

# --- Version resolution ---

resolve_version() {
  if [ -n "$VERSION" ]; then
    info "Using specified version: ${VERSION}"
    return
  fi

  info "Fetching latest CLI release version..."

  TMPFILE="$(mktemp)"
  trap 'rm -f "$TMPFILE"' EXIT

  # cli/latest-version.txt is a bare "X.Y.Z" line on the releases CDN --
  # no JSON parsing needed in POSIX sh.
  if ! download "${BASE_URL}/cli/latest-version.txt" "$TMPFILE" 2>/dev/null; then
    error "Failed to fetch ${BASE_URL}/cli/latest-version.txt. Check your internet connection."
  fi

  VERSION="$(tr -d ' \t\r\n' < "$TMPFILE")"

  case "$VERSION" in
    [0-9]*) ;;
    *)
      error "Could not determine latest CLI version (got: '${VERSION}'). Specify one with --version."
      ;;
  esac

  info "Latest version: ${VERSION}"
  rm -f "$TMPFILE"
  trap - EXIT
}

# --- Checksum verification ---

verify_checksum() {
  ARCHIVE_FILE="$1"
  EXPECTED_HASH="$2"

  if check_command sha256sum; then
    ACTUAL_HASH="$(sha256sum "$ARCHIVE_FILE" | cut -d ' ' -f 1)"
  elif check_command shasum; then
    ACTUAL_HASH="$(shasum -a 256 "$ARCHIVE_FILE" | cut -d ' ' -f 1)"
  else
    warn "Neither sha256sum nor shasum available. Skipping checksum verification."
    return 0
  fi

  if [ "$ACTUAL_HASH" != "$EXPECTED_HASH" ]; then
    error "Checksum verification failed!
  Expected: ${EXPECTED_HASH}
  Actual:   ${ACTUAL_HASH}
This could indicate a corrupted download or a tampered file."
  fi

  info "Checksum verified"
}

# --- PATH management ---

add_to_path() {
  if [ -n "$NO_MODIFY_PATH" ]; then
    return
  fi

  # Check if already in PATH
  case ":${PATH}:" in
    *":${INSTALL_DIR}:"*)
      return
      ;;
  esac

  SHELL_NAME="$(basename "${SHELL:-/bin/sh}")"
  PROFILE_LINE="export PATH=\"${INSTALL_DIR}:\$PATH\""

  case "$SHELL_NAME" in
    zsh)
      PROFILE="$HOME/.zshrc"
      ;;
    bash)
      # Prefer .bashrc on Linux, .bash_profile on macOS
      if [ -f "$HOME/.bashrc" ]; then
        PROFILE="$HOME/.bashrc"
      else
        PROFILE="$HOME/.bash_profile"
      fi
      ;;
    fish)
      PROFILE="$HOME/.config/fish/config.fish"
      PROFILE_LINE="set -gx PATH ${INSTALL_DIR} \$PATH"
      ;;
    *)
      PROFILE="$HOME/.profile"
      ;;
  esac

  # Check if already added to profile
  if [ -f "$PROFILE" ] && grep -qF "$INSTALL_DIR" "$PROFILE" 2>/dev/null; then
    return
  fi

  info "Adding ${INSTALL_DIR} to PATH in ${PROFILE}"
  printf '\n# Glueprint CLI\n%s\n' "$PROFILE_LINE" >> "$PROFILE"
}

# --- Main ---

main() {
  setup_colors
  parse_args "$@"
  detect_platform
  resolve_version

  ARCHIVE_NAME="glueprint-cli-${VERSION}-${TARGET}.tar.gz"
  DOWNLOAD_URL="${BASE_URL}/cli/${ARCHIVE_NAME}"
  # Checksums are versioned (immutable on the CDN) so pinned installs verify
  # against the matching release.
  CHECKSUMS_URL="${BASE_URL}/cli/checksums-${VERSION}.txt"

  # Create temp directory for download
  TMPDIR="$(mktemp -d)"
  trap 'rm -rf "$TMPDIR"' EXIT

  # Download archive
  info "Downloading ${ARCHIVE_NAME}..."
  if ! download "$DOWNLOAD_URL" "${TMPDIR}/${ARCHIVE_NAME}"; then
    error "Failed to download ${DOWNLOAD_URL}
  Check that version ${VERSION} exists and has a ${TARGET} binary."
  fi

  # Download and verify checksum
  info "Verifying checksum..."
  if download "$CHECKSUMS_URL" "${TMPDIR}/checksums.txt" 2>/dev/null; then
    EXPECTED_HASH="$(grep "${ARCHIVE_NAME}" "${TMPDIR}/checksums.txt" | cut -d ' ' -f 1)"
    if [ -n "$EXPECTED_HASH" ]; then
      verify_checksum "${TMPDIR}/${ARCHIVE_NAME}" "$EXPECTED_HASH"
    else
      warn "Archive not found in checksums file. Skipping verification."
    fi
  else
    warn "Could not download checksums file. Skipping verification."
  fi

  # Create install directory
  mkdir -p "$INSTALL_DIR"

  # Extract binaries
  info "Extracting to ${INSTALL_DIR}..."
  tar xzf "${TMPDIR}/${ARCHIVE_NAME}" -C "$TMPDIR"

  # Move binaries to install directory
  EXTRACTED_DIR="${TMPDIR}/glueprint-cli-${VERSION}-${TARGET}"
  cp "${EXTRACTED_DIR}/glueprint" "$INSTALL_DIR/"
  cp "${EXTRACTED_DIR}/glueprint-mcp" "$INSTALL_DIR/"
  cp "${EXTRACTED_DIR}/glueprint-analytics" "$INSTALL_DIR/"

  # Ensure binaries are executable
  chmod +x "${INSTALL_DIR}/glueprint"
  chmod +x "${INSTALL_DIR}/glueprint-mcp"
  chmod +x "${INSTALL_DIR}/glueprint-analytics"

  # Update PATH
  add_to_path

  # Cleanup
  rm -rf "$TMPDIR"
  trap - EXIT

  # Verify installation
  printf "\n"
  success "Glueprint CLI ${VERSION} installed successfully!"
  printf "\n"
  printf "  ${BOLD}Installed binaries:${RESET}\n"
  printf "    %s/glueprint\n" "$INSTALL_DIR"
  printf "    %s/glueprint-mcp\n" "$INSTALL_DIR"
  printf "    %s/glueprint-analytics\n" "$INSTALL_DIR"
  printf "\n"

  # Check if PATH is active
  case ":${PATH}:" in
    *":${INSTALL_DIR}:"*)
      printf "  Run ${BOLD}glueprint --version${RESET} to verify the installation.\n"
      ;;
    *)
      printf "  ${YELLOW}Restart your shell${RESET} or run:\n"
      printf "    export PATH=\"%s:\$PATH\"\n" "$INSTALL_DIR"
      printf "\n"
      printf "  Then run ${BOLD}glueprint --version${RESET} to verify.\n"
      ;;
  esac
  printf "\n"
}

main "$@"
