#!/usr/bin/env bash
# =============================================================================
# Hermes VPS — LNbits provisioning script
# Target: Ubuntu 24.04 LTS (tested on root@143.198.27.163)
#
# Usage:
#   export DB_PASS="$(openssl rand -hex 20)"
#   export TAILSCALE_IP="$(tailscale ip -4)"   # e.g. 100.x.x.x
#   bash scripts/hermes-lnbits/provision.sh
#
# Required env vars (no defaults — operator must supply):
#   DB_PASS        — password for the lnbits PostgreSQL role
#   TAILSCALE_IP   — Tailscale IPv4 of this host (Nginx binds only to this)
#
# Backend note:
#   FakeWallet is used rather than VoidWallet because FakeWallet settles
#   internal (self-payment) invoices in real-time, which is required for
#   the dev/test payment simulation loop. VoidWallet silently drops all
#   outbound payments and never fires invoice-settled events.
#
# After this script:
#   1. Extract the admin key non-interactively (see step below).
#   2. Set Replit secrets:
#        LNBITS_URL=http://${TAILSCALE_IP}:5000
#        LNBITS_API_KEY=<admin-key>
#   3. Restart the api-server workflow.
# =============================================================================
set -euo pipefail

: "${DB_PASS:?DB_PASS must be set. Run: export DB_PASS=\$(openssl rand -hex 20)}"
: "${TAILSCALE_IP:?TAILSCALE_IP must be set. Run: export TAILSCALE_IP=\$(tailscale ip -4)}"

LNBITS_VERSION="${LNBITS_VERSION:-0.12.12}"
LNBITS_PORT="${LNBITS_PORT:-5000}"
LNBITS_DIR="${LNBITS_DIR:-/opt/lnbits}"
SERVICE_USER="${SERVICE_USER:-lnbits}"
DB_NAME=lnbits
DB_USER=lnbits

echo "==> Installing system deps"
apt-get update -qq
apt-get install -y -qq python3.11 python3.11-venv python3-pip \
  postgresql postgresql-contrib nginx curl git openssl jq

echo "==> Creating dedicated service user (non-root)"
id -u "${SERVICE_USER}" &>/dev/null || \
  useradd -r -m -d "${LNBITS_DIR}" -s /usr/sbin/nologin "${SERVICE_USER}"

echo "==> Configuring PostgreSQL"
systemctl enable --now postgresql
sudo -u postgres psql -tc "SELECT 1 FROM pg_roles WHERE rolname='${DB_USER}'" \
  | grep -q 1 || sudo -u postgres createuser -D -R -S "${DB_USER}"
sudo -u postgres psql -c "ALTER ROLE ${DB_USER} WITH PASSWORD '${DB_PASS}';"
sudo -u postgres psql -tc "SELECT 1 FROM pg_database WHERE datname='${DB_NAME}'" \
  | grep -q 1 || sudo -u postgres createdb -O "${DB_USER}" "${DB_NAME}"

echo "==> Creating LNbits venv at ${LNBITS_DIR}/.venv"
mkdir -p "${LNBITS_DIR}/data"
python3.11 -m venv "${LNBITS_DIR}/.venv"
"${LNBITS_DIR}/.venv/bin/pip" install --quiet --upgrade pip
"${LNBITS_DIR}/.venv/bin/pip" install --quiet "lnbits==${LNBITS_VERSION}" psycopg2-binary

echo "==> Writing ${LNBITS_DIR}/.env (mode 600, owned by ${SERVICE_USER})"
cat > "${LNBITS_DIR}/.env" << ENVFILE
LNBITS_BACKEND_WALLET_CLASS=FakeWallet
HOST=0.0.0.0
PORT=${LNBITS_PORT}
LNBITS_DATA_FOLDER=${LNBITS_DIR}/data
LNBITS_DATABASE_URL=postgres://${DB_USER}:${DB_PASS}@localhost:5432/${DB_NAME}
LNBITS_SITE_TITLE=Timmy Tower LNbits
ENVFILE
chmod 600 "${LNBITS_DIR}/.env"
chown "${SERVICE_USER}:${SERVICE_USER}" "${LNBITS_DIR}/.env"

echo "==> Writing ${LNBITS_DIR}/run.sh"
cat > "${LNBITS_DIR}/run.sh" << 'RUNSH'
#!/usr/bin/env bash
set -a
source /opt/lnbits/.env
set +a
exec /opt/lnbits/.venv/bin/lnbits --host 0.0.0.0 --port "${PORT}"
RUNSH
chmod 750 "${LNBITS_DIR}/run.sh"
chown -R "${SERVICE_USER}:${SERVICE_USER}" "${LNBITS_DIR}"

echo "==> Installing systemd unit (User=${SERVICE_USER}, hardened)"
cat > /etc/systemd/system/lnbits.service << UNIT
[Unit]
Description=LNbits Lightning wallet server
After=network.target postgresql.service
Requires=postgresql.service

[Service]
Type=simple
User=${SERVICE_USER}
WorkingDirectory=${LNBITS_DIR}
ExecStart=${LNBITS_DIR}/run.sh
Restart=always
RestartSec=5
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=${LNBITS_DIR}/data

[Install]
WantedBy=multi-user.target
UNIT

systemctl daemon-reload
systemctl enable lnbits
systemctl restart lnbits

echo "==> Waiting for LNbits to start (20 s)..."
sleep 20

echo "==> Ensuring FakeWallet is set in DB"
sudo -u postgres psql "${DB_NAME}" -c \
  "INSERT INTO system_settings (id, value) VALUES ('lnbits_backend_wallet_class', '\"FakeWallet\"')
   ON CONFLICT (id) DO UPDATE SET value = EXCLUDED.value;" 2>/dev/null || true

echo "==> Configuring Nginx (Tailscale-only listener on ${TAILSCALE_IP})"
cat > /etc/nginx/sites-available/lnbits << NGINX
# Bind only to the Tailscale interface — not exposed on public IP
server {
    listen ${TAILSCALE_IP}:80;
    server_name _;

    location / {
        proxy_pass         http://127.0.0.1:${LNBITS_PORT};
        proxy_set_header   Host              \$host;
        proxy_set_header   X-Real-IP         \$remote_addr;
        proxy_set_header   X-Forwarded-For   \$proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto \$scheme;
        proxy_read_timeout 120s;
        proxy_connect_timeout 10s;
    }
}
NGINX
ln -sf /etc/nginx/sites-available/lnbits /etc/nginx/sites-enabled/lnbits
rm -f /etc/nginx/sites-enabled/default
nginx -t && systemctl enable --now nginx && systemctl reload nginx

echo "==> Health check"
if HEALTH=$(curl -sf "http://localhost:${LNBITS_PORT}/api/v1/health" 2>&1); then
  echo "    LNbits health: ${HEALTH}"
else
  echo "    WARNING: health check failed"
  journalctl -u lnbits -n 30 --no-pager
  exit 1
fi

echo "==> Extracting admin key (non-interactive)"
# LNbits >= 0.12 creates a superuser on first start. Query the DB directly.
ADMIN_KEY=$(sudo -u postgres psql "${DB_NAME}" -tAc \
  "SELECT adminkey FROM wallets WHERE deleted = false LIMIT 1;" 2>/dev/null || true)
if [[ -n "${ADMIN_KEY}" ]]; then
  echo "    Admin key: ${ADMIN_KEY}"
  echo "    Set in Replit: LNBITS_API_KEY=${ADMIN_KEY}"
else
  echo "    No wallet found yet — open LNbits UI to create one, then run:"
  echo "    sudo -u postgres psql lnbits -c \"SELECT adminkey FROM wallets LIMIT 1;\""
fi

systemctl status lnbits --no-pager | head -8

echo ""
echo "==> DONE. Set these Replit secrets:"
echo "    LNBITS_URL=http://${TAILSCALE_IP}:80"
echo "    LNBITS_API_KEY=${ADMIN_KEY:-<run-key-extraction-above>}"
echo "    Then restart the api-server workflow."
