#!/bin/sh
# Cade installer — the recommended way to install Cade.
# Fetches the right prebuilt binary and drops it on your PATH.
#
#   curl -fsSL https://arcadeagent.dev/install | sh
#
# Environment overrides:
#   CADE_VERSION       install a specific version (default: latest "stable")
#   CADE_INSTALL_DIR   where to put the binary  (default: ~/.local/bin)
#   CADE_INSTALL_BASE  asset base URL           (default: https://arcadeagent.dev)
#   CADE_VARIANT       Linux only: 'cpu' or 'gpu' (default: auto-detect — 'gpu'
#                      when an NVIDIA GPU is found via nvidia-smi, else 'cpu')
#   CADE_SKIP_MCP_HOSTS=1  skip registering Cade in Claude/Cursor/etc MCP configs
#
# Layout it expects at CADE_INSTALL_BASE:
#   /stable                                  -> text file with the latest version
#   /releases/<version>/cade-<version>-<target>.tar.gz       (+ .sha256)
set -eu

BASE="${CADE_INSTALL_BASE:-https://arcadeagent.dev}"
INSTALL_DIR="${CADE_INSTALL_DIR:-${HOME}/.local/bin}"

info() { printf '\033[1;36mcade\033[0m %s\n' "$1"; }
err() {
    printf '\033[1;31merror\033[0m %s\n' "$1" >&2
    exit 1
}

# --- pick a downloader -------------------------------------------------------
if command -v curl >/dev/null 2>&1; then
    dl() { curl -fsSL "$1" -o "$2"; }
    fetch() { curl -fsSL "$1"; }
elif command -v wget >/dev/null 2>&1; then
    dl() { wget -qO "$2" "$1"; }
    fetch() { wget -qO- "$1"; }
else
    err "need curl or wget on PATH"
fi

# --- detect platform ---------------------------------------------------------
os="$(uname -s)"
arch="$(uname -m)"
case "${os}" in
    Darwin)
        case "${arch}" in
            arm64 | aarch64) target="macos-arm64" ;;
            *) err "unsupported macOS arch '${arch}' (only Apple Silicon binaries are published)" ;;
        esac
        ;;
    Linux)
        case "${arch}" in
            x86_64 | amd64) target="linux-x64" ;;
            *) err "unsupported Linux arch '${arch}' (only x86_64 binaries are published)" ;;
        esac
        # CPU vs GPU build. Default: GPU when an NVIDIA GPU is detected, else CPU.
        # Override with CADE_VARIANT=cpu|gpu. The GPU build bundles the CUDA stack
        # and is a much larger download, so we tell the user what we picked.
        variant="${CADE_VARIANT:-}"
        if [ -z "${variant}" ]; then
            if command -v nvidia-smi >/dev/null 2>&1 && nvidia-smi >/dev/null 2>&1; then
                variant="gpu"
                info "detected NVIDIA GPU → installing the gpu build (set CADE_VARIANT=cpu to override)"
            else
                variant="cpu"
            fi
        fi
        case "${variant}" in
            cpu) ;;
            gpu) target="linux-x64-gpu" ;;
            *) err "invalid CADE_VARIANT '${variant}' (expected 'cpu' or 'gpu')" ;;
        esac
        ;;
    *)
        err "unsupported OS '${os}'. On Windows use the .zip from the releases page; or 'pip install cade-cli'."
        ;;
esac

# --- resolve version ---------------------------------------------------------
VERSION="${CADE_VERSION:-}"
if [ -z "${VERSION}" ]; then
    VERSION="$(fetch "${BASE}/stable" 2>/dev/null | tr -d '[:space:]')" ||
        err "could not fetch the latest version from ${BASE}/stable"
fi
[ -n "${VERSION}" ] || err "empty version"

asset="cade-${VERSION}-${target}.tar.gz"
url="${BASE}/releases/${VERSION}/${asset}"

info "installing cade ${VERSION} (${target})"

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

dl "${url}" "${tmp}/${asset}" || err "download failed: ${url}"

# --- verify checksum if one is published -------------------------------------
if fetch "${url}.sha256" >"${tmp}/sum" 2>/dev/null && [ -s "${tmp}/sum" ]; then
    expected="$(cut -d' ' -f1 <"${tmp}/sum")"
    if command -v sha256sum >/dev/null 2>&1; then
        actual="$(sha256sum "${tmp}/${asset}" | cut -d' ' -f1)"
    elif command -v shasum >/dev/null 2>&1; then
        actual="$(shasum -a 256 "${tmp}/${asset}" | cut -d' ' -f1)"
    else
        actual=""
    fi
    if [ -n "${actual}" ] && [ "${expected}" != "${actual}" ]; then
        err "checksum mismatch (expected ${expected}, got ${actual})"
    fi
    [ -n "${actual}" ] && info "checksum verified"
fi

# --- extract + install (PyInstaller onefile -> a single 'cade' binary) -------
tar -xzf "${tmp}/${asset}" -C "${tmp}"
[ -f "${tmp}/cade" ] || err "archive did not contain a 'cade' binary"

mkdir -p "${INSTALL_DIR}"
if command -v install >/dev/null 2>&1; then
    install -m 0755 "${tmp}/cade" "${INSTALL_DIR}/cade"
else
    cp "${tmp}/cade" "${INSTALL_DIR}/cade"
    chmod 0755 "${INSTALL_DIR}/cade"
fi

# macOS quarantines anything fetched over the network; strip it so the binary
# runs without a Gatekeeper prompt.
if [ "${os}" = "Darwin" ] && command -v xattr >/dev/null 2>&1; then
    xattr -d com.apple.quarantine "${INSTALL_DIR}/cade" 2>/dev/null || true
fi

info "installed to ${INSTALL_DIR}/cade"

# --- PATH setup --------------------------------------------------------------
# Persist INSTALL_DIR on PATH by appending to the user's shell profile(s), so a
# new terminal finds `cade` without a manual export. We still print the export
# for the *current* shell, since sourcing an rc file can't reach this piped
# subshell or its parent.
persist_path() {
    dir="$1"
    line="export PATH=\"${dir}:\$PATH\""
    marker="# cade installer: add ${dir} to PATH"

    shell_name="$(basename "${SHELL:-sh}")"
    case "${shell_name}" in
        zsh) profiles="${ZDOTDIR:-${HOME}}/.zshrc" ;;
        bash) profiles="${HOME}/.bashrc ${HOME}/.bash_profile" ;;
        *) profiles="${HOME}/.profile" ;;
    esac

    written=""
    for prof in ${profiles}; do
        # Idempotent: skip if this dir is already referenced in the file.
        if [ -f "${prof}" ] && grep -Fq "${dir}" "${prof}" 2>/dev/null; then
            written="${written}${prof} "
            continue
        fi
        if printf '\n%s\n%s\n' "${marker}" "${line}" >>"${prof}" 2>/dev/null; then
            written="${written}${prof} "
        fi
    done
    printf '%s' "${written}"
}

case ":${PATH}:" in
    *":${INSTALL_DIR}:"*) ;;
    *)
        profiles_written="$(persist_path "${INSTALL_DIR}")"
        if [ -n "${profiles_written}" ]; then
            info "added ${INSTALL_DIR} to your PATH in: ${profiles_written}"
            info "restart your terminal, or run this now to use cade immediately:"
        else
            info "add it to your PATH:"
        fi
        printf '    export PATH="%s:$PATH"\n' "${INSTALL_DIR}"
        ;;
esac

"${INSTALL_DIR}/cade" --version 2>/dev/null || true

# --- register as MCP server in detected AI hosts -----------------------------
# Claude Desktop, Cursor, Claude Code, OpenCode, Windsurf — only when their
# config dir already exists. Opt out with CADE_SKIP_MCP_HOSTS=1.
skip_hosts="${CADE_SKIP_MCP_HOSTS:-}"
case "${skip_hosts}" in
    1 | true | TRUE | yes | YES) ;;
    *)
        info "registering Cade as an MCP server in detected hosts…"
        if "${INSTALL_DIR}/cade" mcp install-hosts 2>/dev/null; then
            :
        else
            info "skipped MCP host registration (run 'cade mcp install-hosts' later)"
        fi
        ;;
esac

info "done — run 'cade' to start (daemon autostarts; restart Claude/Cursor to load MCP)"
