#!/usr/bin/env bash
#
# browse4.me CLI installer
#
#   curl -fsSL https://browse4.me/cli/install.sh | bash
#
# With options:
#   curl -fsSL https://browse4.me/cli/install.sh | bash -s -- \
#     --api-url https://app.browse4.me \
#     --project my-project
#
# Note the two hosts are different and both are correct: releases are published
# on browse4.me, while the API the CLI talks to lives on app.browse4.me.
#
# The tarball is served next to this script rather than published to npm, so
# installing is a download plus a local npm install — no registry account
# involved. The download is checksum-verified before anything is unpacked.

set -euo pipefail

BOLD='\033[1m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
RED='\033[0;31m'
DIM='\033[0;90m'
RESET='\033[0m'

# Where releases are published. Not the API host — see the note above.
BASE_URL="${B4M_CLI_BASE_URL:-https://browse4.me/cli}"
INSTALL_DIR="${B4M_INSTALL_DIR:-$HOME/.browse4me/cli}"
MIN_NODE_VERSION=20

API_URL=""
PROJECT=""
VERSION="latest"
SKIP_CHECKSUM="false"
UNINSTALL="false"

say()  { echo -e "${GREEN}✓${RESET} $1"; }
warn() { echo -e "${YELLOW}!${RESET} $1"; }
fail() { echo -e "${RED}✖${RESET} $1" >&2; exit 1; }
step() { echo -e "${DIM}→${RESET} $1"; }

usage() {
  cat <<'EOF'
browse4.me CLI installer

  --api-url <url>     API to point at after installing
  --project <name>    Default project
  --version <ver>     Version to install (default: latest)
  --skip-checksum     Install without verifying the download (not advised)
  --uninstall         Remove the CLI
  -h, --help          This message
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --api-url) API_URL="$2"; shift 2 ;;
    --project) PROJECT="$2"; shift 2 ;;
    --version) VERSION="$2"; shift 2 ;;
    --skip-checksum) SKIP_CHECKSUM="true"; shift ;;
    --uninstall) UNINSTALL="true"; shift ;;
    -h|--help) usage; exit 0 ;;
    *) fail "Unknown argument: $1" ;;
  esac
done

# ---------------------------------------------------------------------
# uninstall
# ---------------------------------------------------------------------

if [[ "$UNINSTALL" == "true" ]]; then
  rm -rf "$INSTALL_DIR"
  for dir in "$HOME/.local/bin" /usr/local/bin; do
    [[ -L "$dir/b4m" ]] && rm -f "$dir/b4m"
  done
  say "Removed the browse4.me CLI"
  echo -e "${DIM}Credentials in ~/.bitbot and ~/.browse4me* were left alone.${RESET}"
  exit 0
fi

# ---------------------------------------------------------------------
# prerequisites
# ---------------------------------------------------------------------

command -v node >/dev/null 2>&1 || fail "node is required (v${MIN_NODE_VERSION}+). Install it from https://nodejs.org"
command -v npm  >/dev/null 2>&1 || fail "npm is required. It ships with node."
command -v curl >/dev/null 2>&1 || fail "curl is required."

NODE_MAJOR="$(node -p 'process.versions.node.split(".")[0]')"
[[ "$NODE_MAJOR" -ge "$MIN_NODE_VERSION" ]] || fail "node v${MIN_NODE_VERSION}+ is required (found v${NODE_MAJOR})"

# ---------------------------------------------------------------------
# download
# ---------------------------------------------------------------------

TARBALL="b4m-cli-${VERSION}.tgz"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT

step "Downloading ${TARBALL}"
curl -fsSL "${BASE_URL}/${TARBALL}" -o "${TMP}/${TARBALL}" \
  || fail "Could not download ${BASE_URL}/${TARBALL}"

if [[ "$SKIP_CHECKSUM" == "true" ]]; then
  warn "Skipping checksum verification"
else
  step "Verifying checksum"
  if curl -fsSL "${BASE_URL}/${TARBALL}.sha256" -o "${TMP}/${TARBALL}.sha256" 2>/dev/null; then
    EXPECTED="$(awk '{print $1}' "${TMP}/${TARBALL}.sha256")"

    if command -v sha256sum >/dev/null 2>&1; then
      ACTUAL="$(sha256sum "${TMP}/${TARBALL}" | awk '{print $1}')"
    elif command -v shasum >/dev/null 2>&1; then
      ACTUAL="$(shasum -a 256 "${TMP}/${TARBALL}" | awk '{print $1}')"
    else
      fail "No sha256sum or shasum available. Re-run with --skip-checksum if you accept the risk."
    fi

    # A mismatch means the bytes are not what was published. Stop.
    [[ "$EXPECTED" == "$ACTUAL" ]] || fail "Checksum mismatch — refusing to install.
  expected ${EXPECTED}
  actual   ${ACTUAL}"
    say "Checksum verified"
  else
    fail "No published checksum for ${TARBALL}. Re-run with --skip-checksum if you accept the risk."
  fi
fi

# ---------------------------------------------------------------------
# install
# ---------------------------------------------------------------------

step "Installing to ${INSTALL_DIR}"
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR"
tar -xzf "${TMP}/${TARBALL}" -C "$TMP"
cp -r "${TMP}/package/." "$INSTALL_DIR/"

( cd "$INSTALL_DIR" && npm install --omit=dev --silent --no-audit --no-fund >/dev/null 2>&1 ) \
  || fail "npm install failed in ${INSTALL_DIR}"

chmod +x "${INSTALL_DIR}/index.js"

# Record how this install was made, so `b4m update` knows where it came from
# and can refuse to "update" a git checkout it has no business touching.
node -e "
  const fs = require('fs');
  fs.writeFileSync('${INSTALL_DIR}/.install-manifest.json', JSON.stringify({
    installedAt: new Date().toISOString(),
    baseUrl: '${BASE_URL}',
    version: require('${INSTALL_DIR}/package.json').version,
  }, null, 2) + '\n');
"

# ---------------------------------------------------------------------
# link onto PATH
# ---------------------------------------------------------------------

LINK_DIR=""
if [[ -d "$HOME/.local/bin" ]]; then
  LINK_DIR="$HOME/.local/bin"
elif [[ -w /usr/local/bin ]]; then
  LINK_DIR="/usr/local/bin"
else
  mkdir -p "$HOME/.local/bin"
  LINK_DIR="$HOME/.local/bin"
fi

ln -sf "${INSTALL_DIR}/index.js" "${LINK_DIR}/b4m"
say "Linked ${LINK_DIR}/b4m"

case ":${PATH}:" in
  *":${LINK_DIR}:"*) ;;
  *) warn "${LINK_DIR} is not on your PATH — add it to your shell profile:
    export PATH=\"${LINK_DIR}:\$PATH\"" ;;
esac

# ---------------------------------------------------------------------
# optional configuration
# ---------------------------------------------------------------------

if [[ -n "$API_URL" || -n "$PROJECT" ]]; then
  step "Writing ~/.browse4me.json"
  node -e "
    const fs = require('fs'), os = require('os'), path = require('path');
    const file = path.join(os.homedir(), '.browse4me.json');
    let cfg = {};
    try { cfg = JSON.parse(fs.readFileSync(file, 'utf8')); } catch {}
    if ('$API_URL') cfg.apiUrl = '$API_URL'.replace(/\/\$/, '');
    if ('$PROJECT') cfg.project = '$PROJECT';
    fs.writeFileSync(file, JSON.stringify(cfg, null, 2) + '\n', { mode: 0o600 });
  "
fi

echo
say "$(b4m --version 2>/dev/null | sed 's/^/browse4.me CLI v/' || echo 'browse4.me CLI installed')"
echo
echo -e "${BOLD}Next:${RESET}"
echo "  b4m login                       authenticate with BitBot"
echo "  b4m project join <name>         point this directory at a project"
echo "  b4m open https://example.com    open a page"
echo "  b4m shell                       interactive session"
echo
