#!/bin/sh
# install.sh — bootstrap installer for the `w` CLI
#
# Usage (fresh host, no `w` installed yet):
#   curl -fsSL https://storage-hk.myfastools.com/releases/w/install.sh | sh
#
# Environment overrides:
#   W_RELEASES_BASE   Base URL for the R2 releases bucket
#                     (default: https://storage-hk.myfastools.com)
#   PREFIX            Directory to install `w` into
#                     (default: /usr/local/bin)
#
# Dependencies: curl, sha256sum (coreutils/OpenSSL).
# Optional:     python3 (used for JSON parsing when available; falls back to
#               grep/sed otherwise).
#
# The script is idempotent — re-running it upgrades in place.

set -e

BASE="${W_RELEASES_BASE:-https://storage-hk.myfastools.com}"
MANIFEST_URL="${BASE}/releases/w/w-version.json"

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

die() { printf 'install.sh: error: %s\n' "$*" >&2; exit 1; }
info() { printf '[w install] %s\n' "$*"; }

# Extract a top-level JSON string field.  Tries python3 first for correctness,
# then falls back to grep+sed (sufficient for our simple single-line manifests).
json_field() {
    _json="$1"   # JSON text
    _key="$2"    # field name

    if command -v python3 >/dev/null 2>&1; then
        printf '%s' "$_json" | python3 -c \
            "import sys,json; d=json.load(sys.stdin); print(d['$_key'])"
        return
    fi

    # Fallback: extract "key": "value" — works for simple, flat manifests.
    printf '%s' "$_json" \
        | grep -o "\"$_key\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" \
        | sed "s/\"$_key\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\"/\1/"
}

# Extract the linux-x86_64 sub-field (url or sha256) from the nested
# targets.linux-x86_64 object.  python3 preferred; grep/sed fallback.
json_linux_field() {
    _json="$1"
    _key="$2"

    if command -v python3 >/dev/null 2>&1; then
        printf '%s' "$_json" | python3 -c \
            "import sys,json; d=json.load(sys.stdin); print(d['targets']['linux-x86_64']['$_key'])"
        return
    fi

    # Fallback: the manifest is compact enough that grep on the raw text works.
    printf '%s' "$_json" \
        | grep -o "\"$_key\"[[:space:]]*:[[:space:]]*\"[^\"]*\"" \
        | head -1 \
        | sed "s/\"$_key\"[[:space:]]*:[[:space:]]*\"\([^\"]*\)\"/\1/"
}

# ---------------------------------------------------------------------------
# Check dependencies
# ---------------------------------------------------------------------------

command -v curl      >/dev/null 2>&1 || die "'curl' is required but not found"
command -v sha256sum >/dev/null 2>&1 || die "'sha256sum' is required but not found"

# ---------------------------------------------------------------------------
# Fetch manifest
# ---------------------------------------------------------------------------

info "fetching release manifest from ${MANIFEST_URL}"
MANIFEST="$(curl -fsSL "${MANIFEST_URL}")" \
    || die "failed to fetch manifest from ${MANIFEST_URL}"

VERSION="$(json_field "$MANIFEST" version)"
BIN_URL="$(json_linux_field "$MANIFEST" url)"
EXPECTED_SHA="$(json_linux_field "$MANIFEST" sha256)"

[ -n "$VERSION"      ] || die "could not parse 'version' from manifest"
[ -n "$BIN_URL"      ] || die "could not parse linux-x86_64 'url' from manifest"
[ -n "$EXPECTED_SHA" ] || die "could not parse linux-x86_64 'sha256' from manifest"

info "installing w v${VERSION}"
info "binary: ${BIN_URL}"

# ---------------------------------------------------------------------------
# Download to a temp file + verify SHA-256
# ---------------------------------------------------------------------------

TMP_BIN="$(mktemp /tmp/w-install-XXXXXX)"
# Ensure temp file is removed on exit (even on error, thanks to set -e).
trap 'rm -f "$TMP_BIN"' EXIT

info "downloading..."
curl -fsSL --progress-bar -o "$TMP_BIN" "${BIN_URL}" \
    || die "download failed from ${BIN_URL}"

ACTUAL_SHA="$(sha256sum "$TMP_BIN" | awk '{print $1}')"
if [ "$ACTUAL_SHA" != "$EXPECTED_SHA" ]; then
    die "sha256 mismatch! expected=${EXPECTED_SHA} got=${ACTUAL_SHA} — aborting"
fi
info "sha256 ok (${ACTUAL_SHA})"

chmod +x "$TMP_BIN"

# ---------------------------------------------------------------------------
# Install to PREFIX (use sudo only when needed)
# ---------------------------------------------------------------------------

PREFIX="${PREFIX:-/usr/local/bin}"

# Create the install directory if missing (may need sudo).
if [ ! -d "$PREFIX" ]; then
    if [ "$(id -u)" = "0" ] || [ -w "$(dirname "$PREFIX")" ]; then
        mkdir -p "$PREFIX"
    else
        sudo mkdir -p "$PREFIX"
    fi
fi

INSTALL_PATH="${PREFIX}/w"

# Move the verified temp binary into place.
if [ -w "$PREFIX" ] || [ "$(id -u)" = "0" ]; then
    mv "$TMP_BIN" "$INSTALL_PATH"
else
    info "need elevated privileges to write to ${PREFIX} — using sudo"
    sudo mv "$TMP_BIN" "$INSTALL_PATH"
fi

# trap cleanup still runs on EXIT; the file is gone, so the rm is a no-op.

# ---------------------------------------------------------------------------
# Create w-id and w-radar convenience symlinks
# ---------------------------------------------------------------------------

for ALIAS in w-id w-radar; do
    LINK="${PREFIX}/${ALIAS}"
    if [ -w "$PREFIX" ] || [ "$(id -u)" = "0" ]; then
        ln -sf w "$LINK"
    else
        sudo ln -sf w "$LINK"
    fi
done

# ---------------------------------------------------------------------------
# Done
# ---------------------------------------------------------------------------

info "installed w v${VERSION} to ${INSTALL_PATH}"
info ""
info "Next steps:"
info "  1. Log in:          w login"
info "  2. Launch a service: w launch <app>"
info "  3. Check status:    w status <app>"
info "  4. Self-update:     w upgrade"
