#!/usr/bin/env sh
# Vulcan CI installer
#
#   curl -fsSL https://get.vulcan-ci.io/install.sh | sh
#
# Installs the vulcan-ci CLI and places the server deployment package
# (Docker Compose and Kubernetes config) under ~/.vulcan/install, ready
# to launch with whichever stack you choose.
set -eu

# --- Configuration -----------------------------------------------------
# TODO: fill these in once release hosting is finalized.
REPO="vulcan-ci/vulcan-ci"
BASE_URL="https://github.com/${REPO}/releases"
BIN_NAME="vulcan-ci"
INSTALL_DIR="${VULCAN_INSTALL_DIR:-/usr/local/bin}"
VERSION="${VULCAN_VERSION:-latest}"
SITE_URL="${VULCAN_SITE_URL:-https://get.vulcan-ci.io}"
VULCAN_HOME="${VULCAN_HOME:-$HOME/.vulcan}"
INSTALL_BASE="${VULCAN_HOME}/install"

# --- Helpers -------------------------------------------------------------
err() {
  echo "error: $*" >&2
  exit 1
}

info() {
  echo "==> $*"
}

warn() {
  echo "warning: $*" >&2
}

need_cmd() {
  command -v "$1" >/dev/null 2>&1 || err "required command '$1' not found"
}

detect_os() {
  os=$(uname -s)
  case "$os" in
    Linux) echo "linux" ;;
    Darwin) echo "darwin" ;;
    *) err "unsupported OS: $os" ;;
  esac
}

detect_arch() {
  arch=$(uname -m)
  case "$arch" in
    x86_64 | amd64) echo "amd64" ;;
    arm64 | aarch64) echo "arm64" ;;
    *) err "unsupported architecture: $arch" ;;
  esac
}

download_url() {
  os="$1"
  arch="$2"
  version="$3"

  if [ "$version" = "latest" ]; then
    path="latest/download"
  else
    path="download/${version}"
  fi

  # TODO: confirm asset naming convention once releases are published.
  echo "${BASE_URL}/${path}/${BIN_NAME}_${os}_${arch}.tar.gz"
}

# Expand the server deployment package (install.zip) into ~/.vulcan.
# Best-effort: a missing unzip skips this step rather than failing the
# CLI install.
install_server_package() {
  if ! command -v unzip >/dev/null 2>&1; then
    warn "unzip not found — skipping the server deployment package."
    warn "fetch it later from ${SITE_URL}/install.zip and expand into ${VULCAN_HOME}"
    return 0
  fi
  info "fetching the server deployment package"
  curl -fsSL "${SITE_URL}/install.zip" -o "${tmp_dir}/install.zip" \
    || err "download failed: ${SITE_URL}/install.zip"
  mkdir -p "$VULCAN_HOME"
  unzip -o -q "${tmp_dir}/install.zip" -d "$VULCAN_HOME"
  info "server config expanded into ${INSTALL_BASE}"
  info "choose a stack when you're ready:"
  info "  Docker:     docker compose -f ${INSTALL_BASE}/docker/docker-compose.yml up -d"
  info "  Kubernetes: kubectl apply -k ${INSTALL_BASE}/kubernetes"
  info "see ${INSTALL_BASE}/kubernetes/README.md and the compose file header"
  info "for the required configuration."
}

install_cli() {
  os=$(detect_os)
  arch=$(detect_arch)
  url=$(download_url "$os" "$arch" "$VERSION")

  info "downloading ${BIN_NAME} (${os}/${arch}, ${VERSION})"
  curl -fsSL "$url" -o "${tmp_dir}/${BIN_NAME}.tar.gz" \
    || err "download failed: $url"

  info "extracting archive"
  tar -xzf "${tmp_dir}/${BIN_NAME}.tar.gz" -C "$tmp_dir"

  [ -f "${tmp_dir}/${BIN_NAME}" ] || err "expected binary '${BIN_NAME}' not found in archive"

  if [ ! -w "$INSTALL_DIR" ]; then
    info "installing to ${INSTALL_DIR} (requires sudo)"
    sudo install -m 0755 "${tmp_dir}/${BIN_NAME}" "${INSTALL_DIR}/${BIN_NAME}"
  else
    info "installing to ${INSTALL_DIR}"
    install -m 0755 "${tmp_dir}/${BIN_NAME}" "${INSTALL_DIR}/${BIN_NAME}"
  fi

  info "installed: $("${INSTALL_DIR}/${BIN_NAME}" --version 2>/dev/null || echo "${BIN_NAME}")"
  info "done. run '${BIN_NAME} --help' to get started."
}

main() {
  need_cmd curl
  need_cmd tar
  need_cmd uname
  need_cmd mktemp

  tmp_dir=$(mktemp -d)
  trap 'rm -rf "$tmp_dir"' EXIT

  install_server_package
  install_cli
}

main "$@"
