#!/usr/bin/env bash
set -euo pipefail

BASE_URL="${BOTTLY_URL:-https://bottly.xyz}"
CODE="${1:-${BOTTLY_PAIRING_CODE:-}}"
if [ -z "$CODE" ]; then
  echo "Usage: curl -fsSL $BASE_URL/api/public/hosting/install.sh | sudo bash -s BOTTLY-XXXX-XXXX"
  exit 1
fi
if [ "$(id -u)" != "0" ]; then echo "Please run this as root (sudo)."; exit 1; fi

say() { echo "[bottly] $1"; }

say "checking system"
. /etc/os-release || true
echo "OS: ${PRETTY_NAME:-unknown} ($(uname -m))"
export DEBIAN_FRONTEND=noninteractive
if command -v apt-get >/dev/null 2>&1; then
  apt-get update -y >/dev/null && apt-get install -y curl ca-certificates >/dev/null
elif command -v dnf >/dev/null 2>&1; then
  dnf install -y curl ca-certificates >/dev/null
elif command -v yum >/dev/null 2>&1; then
  yum install -y curl ca-certificates >/dev/null
fi

say "installing docker if missing"
if ! command -v docker >/dev/null 2>&1; then
  curl -fsSL https://get.docker.com | sh >/dev/null
fi
systemctl enable --now docker >/dev/null 2>&1 || true

say "installing node.js if missing"
NODE_OK=0
if command -v node >/dev/null 2>&1; then
  NODE_MAJOR="$(node -p 'process.versions.node.split(".")[0]')"
  if [ "$NODE_MAJOR" -ge 20 ]; then NODE_OK=1; fi
fi
if [ "$NODE_OK" != "1" ]; then
  curl -fsSL https://deb.nodesource.com/setup_22.x | bash - >/dev/null 2>&1 || true
  (apt-get install -y nodejs >/dev/null 2>&1) || (dnf install -y nodejs >/dev/null 2>&1) || true
fi
node -v

mkdir -p /opt/bottly/agent /opt/bottly/build /etc/bottly
chmod 750 /opt/bottly /etc/bottly

say "preparing the bot runtime image (this can take a few minutes)"
RUNTIME_IMAGE="ghcr.io/nataliasnappriv-beep/bottly-runtime:latest"
BUILD_LOCAL=1
if [ -n "$RUNTIME_IMAGE" ] && docker pull "$RUNTIME_IMAGE" >/dev/null 2>&1; then
  BUILD_LOCAL=0
  say "pulled $RUNTIME_IMAGE"
fi
if [ "$BUILD_LOCAL" = "1" ]; then
  curl -fsSL "$BASE_URL/api/public/hosting/runtime-source" -o /opt/bottly/build/source.json
  test -s /opt/bottly/build/source.json
  node -e 'const fs=require("fs"),p=require("path");const j=JSON.parse(fs.readFileSync("/opt/bottly/build/source.json","utf8"));if(!j.files)throw new Error("no runtime source");for(const[f,c]of Object.entries(j.files)){const t=p.join("/opt/bottly/build",f);fs.mkdirSync(p.dirname(t),{recursive:true});fs.writeFileSync(t,c);}console.log("wrote "+Object.keys(j.files).length+" runtime files");'
  docker build -f /opt/bottly/build/runtime/Dockerfile -t bottly-runtime:local /opt/bottly/build
  RUNTIME_IMAGE="bottly-runtime:local"
fi
docker image inspect "$RUNTIME_IMAGE" >/dev/null
say "runtime image ready: $RUNTIME_IMAGE"

say "installing the bottly agent"
curl -fsSL "$BASE_URL/api/public/hosting/agent.js" -o /opt/bottly/agent/index.mjs
test -s /opt/bottly/agent/index.mjs
cat > /etc/bottly/agent.json <<BOTTLY_AGENT_CONFIG
{
  "baseUrl": "$BASE_URL",
  "runtimeUrl": "http://127.0.0.1:8787",
  "runtimeImage": "$RUNTIME_IMAGE",
  "agentVersion": "1.4.0"
}
BOTTLY_AGENT_CONFIG
chmod 600 /etc/bottly/agent.json

say "pairing with Bottly"
BOTTLY_URL="$BASE_URL" node /opt/bottly/agent/index.mjs pair "$CODE"

say "installing the background service"
cat > /etc/systemd/system/bottly-agent.service <<'BOTTLY_AGENT_UNIT'
[Unit]
Description=Bottly VPS Agent
After=network-online.target docker.service
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/bin/env node /opt/bottly/agent/index.mjs
Restart=always
RestartSec=5
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
BOTTLY_AGENT_UNIT
systemctl daemon-reload
systemctl enable --now bottly-agent >/dev/null
sleep 3
systemctl is-active bottly-agent
say "done - this machine should appear online in Bottly within a minute"
