#!/bin/bash
#
# Numira CLI bootstrap installer.
#   curl -fsSL https://<host>/install.sh | bash
#   curl -fsSL https://<host>/install.sh | bash -s -- <version>
#
# Env overrides:
#   NUMIRA_DL_HOST   override base (default https://storage.numira.ai/code/cli)
#
set -eu

TARGET="${1:-latest}"

if [[ ! "$TARGET" =~ ^(latest|[0-9]+\.[0-9]+\.[0-9]+(-[^[:space:]]+)?)$ ]]; then
    echo "Usage: install.sh [latest|VERSION]" >&2
    exit 1
fi

# Production download base. Maps to https://storage.numira.ai/code/cli/.
DEFAULT_DOWNLOAD_BASE_URL="https://storage.stage.numira.ai/code/cli"

DOWNLOAD_BASE_URL="${NUMIRA_DL_HOST:-$DEFAULT_DOWNLOAD_BASE_URL}"
DOWNLOAD_BASE_URL="${DOWNLOAD_BASE_URL%/}"

if [ -z "$DOWNLOAD_BASE_URL" ]; then
    echo "Download host not configured. Set NUMIRA_DL_HOST or build with DEFAULT_DOWNLOAD_BASE_URL set." >&2
    exit 1
fi
RELEASES_URL="$DOWNLOAD_BASE_URL"
DOWNLOAD_DIR="$HOME/.numira/downloads"
BIN_NAME="numira"

# Probe whether a directory accepts an executable (catches noexec, SELinux, perms).
dir_usable() {
    dir="$1"
    [ -d "$dir" ] || mkdir -p "$dir" 2>/dev/null || return 1
    [ -w "$dir" ] || return 1
    probe="$dir/.numira-probe.$$"
    printf '#!/bin/sh\nexit 0\n' > "$probe" 2>/dev/null || return 1
    chmod +x "$probe" 2>/dev/null || { rm -f "$probe"; return 1; }
    "$probe" >/dev/null 2>&1
    rc=$?
    rm -f "$probe"
    return $rc
}

# Same probe but using sudo for system dirs.
dir_usable_sudo() {
    dir="$1"
    command -v sudo >/dev/null 2>&1 || return 1
    sudo -n true >/dev/null 2>&1 || sudo -v >/dev/null 2>&1 || return 1
    sudo mkdir -p "$dir" >/dev/null 2>&1 || return 1
    probe="$dir/.numira-probe.$$"
    sudo sh -c "printf '#!/bin/sh\nexit 0\n' > '$probe' && chmod +x '$probe'" >/dev/null 2>&1 || return 1
    sudo "$probe" >/dev/null 2>&1
    rc=$?
    sudo rm -f "$probe" >/dev/null 2>&1 || true
    return $rc
}

USER_BIN="$HOME/.local/bin"
SYS_BIN="/usr/local/bin"

INSTALL_DIR=""
USE_SUDO=0

if dir_usable "$USER_BIN"; then
    INSTALL_DIR="$USER_BIN"
elif [ "$(id -u)" = "0" ] && dir_usable "$SYS_BIN"; then
    INSTALL_DIR="$SYS_BIN"
elif dir_usable_sudo "$SYS_BIN"; then
    INSTALL_DIR="$SYS_BIN"
    USE_SUDO=1
else
    echo "Cannot find a writable, exec-allowed directory for the binary." >&2
    echo "Tried:" >&2
    echo "  $USER_BIN (likely noexec mount or no write access)" >&2
    echo "  $SYS_BIN  (needs sudo; not available or also blocked)" >&2
    exit 1
fi

# Detect downloader
if command -v curl >/dev/null 2>&1; then
    DOWNLOADER="curl"
elif command -v wget >/dev/null 2>&1; then
    DOWNLOADER="wget"
else
    echo "Either curl or wget is required but neither is installed." >&2
    exit 1
fi

download_to_stdout() {
    if [ "$DOWNLOADER" = "curl" ]; then
        curl -fsSL "$1"
    else
        wget -q -O - "$1"
    fi
}

download_to_file() {
    if [ "$DOWNLOADER" = "curl" ]; then
        curl -fsSL -o "$2" "$1"
    else
        wget -q -O "$2" "$1"
    fi
}

# Detect platform. Only x64 is shipped.
case "$(uname -s)" in
    Linux)              os="linux" ;;
    Darwin)             echo "macOS not yet supported." >&2; exit 1 ;;
    MINGW*|MSYS*|CYGWIN*)
        echo "Windows: use the PowerShell installer ($DOWNLOAD_BASE_URL/install.ps1)." >&2
        exit 1 ;;
    *) echo "Unsupported OS: $(uname -s)" >&2; exit 1 ;;
esac

case "$(uname -m)" in
    x86_64|amd64) : ;;
    *) echo "Unsupported architecture: $(uname -m) (only x64 is shipped)." >&2; exit 1 ;;
esac

platform="linux64"

# Resolve the manifest: "latest" reads the moving channel, an explicit version
# reads its immutable dir. The manifest is the single source of truth.
if [ "$TARGET" = "latest" ]; then
    manifest_url="$RELEASES_URL/latest/$platform/manifest.json"
else
    manifest_url="$RELEASES_URL/versions/$TARGET/$platform/manifest.json"
fi

manifest_json="$(download_to_stdout "$manifest_url")" || {
    echo "Failed to fetch manifest: $manifest_url" >&2
    exit 1
}

# Parse manifest. Prefer jq, fall back to bash regex.
version=""
checksum=""
rel_url=""
if command -v jq >/dev/null 2>&1; then
    version="$(printf '%s' "$manifest_json" | jq -r '.version // empty')"
    checksum="$(printf '%s' "$manifest_json" | jq -r '.checksum // empty')"
    rel_url="$(printf '%s' "$manifest_json" | jq -r '.url // empty')"
else
    flat="$(printf '%s' "$manifest_json" | tr -d '\n\r\t' | sed 's/  */ /g')"
    if [[ $flat =~ \"version\"[[:space:]]*:[[:space:]]*\"([^\"]+)\" ]]; then
        version="${BASH_REMATCH[1]}"
    fi
    if [[ $flat =~ \"checksum\"[[:space:]]*:[[:space:]]*\"([a-f0-9]{64})\" ]]; then
        checksum="${BASH_REMATCH[1]}"
    fi
    if [[ $flat =~ \"url\"[[:space:]]*:[[:space:]]*\"([^\"]+)\" ]]; then
        rel_url="${BASH_REMATCH[1]}"
    fi
fi

if [ -z "$version" ]; then
    echo "Manifest at $manifest_url missing 'version'" >&2
    exit 1
fi

if [ -z "$checksum" ] || [[ ! "$checksum" =~ ^[a-f0-9]{64}$ ]]; then
    echo "Manifest at $manifest_url missing valid checksum" >&2
    exit 1
fi

if [ -z "$rel_url" ]; then
    rel_url="$BIN_NAME"
fi

echo "Numira CLI: installing $version ($platform)"

# Always download from the immutable versioned path (never from latest/), so an
# in-progress 'latest' republish can't hand back a checksum-mismatched binary.
binary_url="$RELEASES_URL/versions/$version/$platform/$rel_url"

mkdir -p "$DOWNLOAD_DIR"

tmp_binary="$DOWNLOAD_DIR/numira-$version-$platform"
if ! download_to_file "$binary_url" "$tmp_binary"; then
    rm -f "$tmp_binary"
    echo "Failed to download binary: $binary_url" >&2
    exit 1
fi

# Verify checksum
if command -v sha256sum >/dev/null 2>&1; then
    actual="$(sha256sum "$tmp_binary" | cut -d' ' -f1)"
elif command -v shasum >/dev/null 2>&1; then
    actual="$(shasum -a 256 "$tmp_binary" | cut -d' ' -f1)"
else
    echo "sha256sum or shasum is required for verification." >&2
    rm -f "$tmp_binary"
    exit 1
fi

if [ "$actual" != "$checksum" ]; then
    echo "Checksum mismatch. Expected $checksum, got $actual" >&2
    rm -f "$tmp_binary"
    exit 1
fi

# Install
dest="$INSTALL_DIR/$BIN_NAME"
if [ "$USE_SUDO" = "1" ]; then
    sudo mv -f "$tmp_binary" "$dest"
    sudo chmod +x "$dest"
else
    mv -f "$tmp_binary" "$dest"
    chmod +x "$dest"
fi

# PATH wiring only needed for the user-local dir; /usr/local/bin is in PATH by default.
if [ "$INSTALL_DIR" = "$USER_BIN" ]; then
    case ":${PATH:-}:" in
        *":$INSTALL_DIR:"*) already_in_path=1 ;;
        *)                  already_in_path=0 ;;
    esac

    if [ "$already_in_path" -eq 0 ]; then
        LINE='export PATH="$HOME/.local/bin:$PATH"'
        MARKER='# Added by Numira CLI installer'
        updated=0
        for rc in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile"; do
            [ -f "$rc" ] || continue
            if grep -Fq "$LINE" "$rc"; then continue; fi
            printf '\n%s\n%s\n' "$MARKER" "$LINE" >> "$rc"
            echo "Updated: $rc"
            updated=1
        done
        if [ "$updated" -eq 0 ]; then
            echo "No shell rc found. Add this to your shell init manually:"
            echo "    $LINE"
        fi
    fi
fi

echo ""
echo "Numira CLI $version installed."
echo "Run: numira"
if [ "$INSTALL_DIR" = "$USER_BIN" ]; then
    echo "If 'numira' is not recognized, open a new terminal or run: source ~/.bashrc"
fi
