#!/usr/bin/env bash
# =====================================================================
# Create (or update) the standard LogShip ERP proxy host in Nginx Proxy Manager
# ---------------------------------------------------------------------
#   add-instance.sh <domain> <instance-ip> [--cert <id|nice_name|"new">] [--disabled] [--letsencrypt <email>]
#
#   --cert <id|name>   certificate to use (create default: "selfsigned-wildcard"; update default: keep current)
#   --letsencrypt <e>  request a Let's Encrypt cert via http-01 (DNS must already point at the
#                      edge IP and 80/443 must be forwarded) instead of --cert
#   --disabled         create the host disabled (ready, not serving)
#
# Standard per-instance routing (one source of truth, see README):
#   /                         http://IP:3001   websockets on, X-Forwarded-Proto, buffers
#   /api/v1                   https://IP:8443/api/v1   (iDempiere REST, self-signed upstream)
#   /webui, /webui/serverpush https://IP:8443          (ZK UI, websocket, 300 s)
#   /media-api                http://IP:1337/api       (Strapi)
#   /files-api                http://IP:80/            (instance nginx -> uploads)
#   /capi/webhooks/fulfillment-leads/  http://IP:3001  (landing-page lead webhook)
#   ~ ^/api/.*/stream$        http://IP:3001   SSE: no buffering, 1 h read   } advanced-snippet.conf
#   /chat/ws                  http://IP:3001   websocket, 1 h read           }
# Needs: curl, jq. Runs anywhere that reaches the NPM API (edge VM itself, or your Mac).
# =====================================================================
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
# shellcheck source=npm-api.sh
source "$HERE/npm-api.sh"

[ $# -ge 2 ] || { grep '^#   ' "$0" | sed 's/^#  //'; exit 1; }
DOMAIN="$1"; IP="$2"; shift 2
CERT=""; ENABLED=1; LE_EMAIL=""   # empty CERT = keep existing on update / selfsigned-wildcard on create
while [ $# -gt 0 ]; do
  case "$1" in
    --cert) CERT="$2"; shift 2;;
    --letsencrypt) LE_EMAIL="$2"; shift 2;;
    --disabled) ENABLED=0; shift;;
    *) echo "unknown option $1" >&2; exit 1;;
  esac
done

npm_login
snippet=$(sed "s/__IP__/$IP/g" "$HERE/advanced-snippet.conf")
loc_webui=$(cat "$HERE/location-webui.conf")
loc_api=$(cat "$HERE/location-api.conf")

existing=$(npm_host_id_by_domain "$DOMAIN")
cert_id=0; meta='{"letsencrypt_agree":false,"dns_challenge":false}'
if [ -z "$CERT" ] && [ -z "$LE_EMAIL" ]; then
  if [ -n "$existing" ]; then
    cert_id=$(npm_get "/api/nginx/proxy-hosts/$existing" | jq -r '.certificate_id // 0')   # keep what the host has
  else
    CERT="selfsigned-wildcard"
  fi
fi
if [ -n "$LE_EMAIL" ]; then
  meta=$(jq -n --arg e "$LE_EMAIL" '{letsencrypt_agree:true, letsencrypt_email:$e, dns_challenge:false}')
  cert_id='"new"'
elif [[ "$CERT" =~ ^[0-9]+$ ]]; then
  cert_id="$CERT"
elif [ -n "$CERT" ]; then
  cert_id=$(npm_cert_id_by_name "$CERT"); [ -n "$cert_id" ] || { echo "certificate '$CERT' not found" >&2; exit 1; }
fi

body=$(jq -n \
  --arg d "$DOMAIN" --arg ip "$IP" --arg adv "$snippet" --arg lw "$loc_webui" --arg la "$loc_api" \
  --argjson cert "$cert_id" --argjson en "$ENABLED" --argjson meta "$meta" '
{
  domain_names: [$d],
  forward_scheme: "http", forward_host: $ip, forward_port: 3001,
  certificate_id: $cert, ssl_forced: true, http2_support: true, hsts_enabled: true, hsts_subdomains: false,
  block_exploits: true, caching_enabled: false, allow_websocket_upgrade: true, access_list_id: 0,
  advanced_config: $adv, enabled: $en, meta: $meta,
  locations: [
    { path: "/api/v1",            forward_scheme: "https", forward_host: $ip, forward_port: 8443, forward_path: "/api/v1", advanced_config: $la },
    { path: "/webui",             forward_scheme: "https", forward_host: $ip, forward_port: 8443, forward_path: "/webui", advanced_config: $lw },
    { path: "/webui/serverpush",  forward_scheme: "https", forward_host: $ip, forward_port: 8443, forward_path: "/webui/serverpush", advanced_config: $lw },
    { path: "/media-api",         forward_scheme: "http",  forward_host: $ip, forward_port: 1337, forward_path: "/api", advanced_config: "" },
    { path: "/files-api",         forward_scheme: "http",  forward_host: $ip, forward_port: 80,   forward_path: "/", advanced_config: "" },
    { path: "/capi/webhooks/fulfillment-leads/", forward_scheme: "http", forward_host: $ip, forward_port: 3001, advanced_config: "" }
  ]
}')

if [ -n "$existing" ]; then
  out=$(npm_put "/api/nginx/proxy-hosts/$existing" "$(echo "$body" | jq 'del(.enabled)')")
  echo "updated proxy host #$existing $DOMAIN -> $IP"
else
  out=$(npm_post /api/nginx/proxy-hosts "$body")
  echo "created proxy host #$(echo "$out" | jq -r .id) $DOMAIN -> $IP (enabled=$ENABLED, cert=$(echo "$out" | jq -r .certificate_id))"
fi
