#!/usr/bin/env bash
#
# deploy-gigafactory.sh — one-shot local deploy of the Agent Gigafactory
# (platform-service fleet module) against the configured backend, then register
# the ecosystem products so live /api/fleet/* calls return data.
#
# Prereqs:
#   - learning_ai_common_plat checked out as a sibling of this repo
#   - services/platform-service/.env filled (Cosmos endpoint/key, JWT_SECRET, ...)
#     e.g. populated from Azure: COSMOS_ENDPOINT/COSMOS_KEY/AZURE_BLOB_CONNECTION_STRING
#   - pnpm deps installed in common_plat; Node 18+
#
# Usage:
#   ./deploy-gigafactory.sh                 # start service, wait for health, register products, smoke
#   ./deploy-gigafactory.sh --full          # full local stack: backend + register factories + web tracker
#   ./deploy-gigafactory.sh --with-tracker  # also start the web tracker (tracker-web) on $TRACKER_PORT
#   ./deploy-gigafactory.sh --tracker-only  # backend already running; just start the web tracker
#   ./deploy-gigafactory.sh --register-only # service already running on $PORT; just register products
#   ./deploy-gigafactory.sh --stop          # stop the service + tracker started by this script
#   ./deploy-gigafactory.sh --no-register   # start + health only, skip product registration
#
# Env overrides:
#   COMMON_PLAT         path to learning_ai_common_plat (default: ../learning_ai_common_plat)
#   PORT                platform-service port (default: 4003)
#   TRACKER_PORT        tracker-web (web tracker) port (default: 3003)
#   DEFAULT_PRODUCT_ID  product the tracker logs in / scopes to (default: first of $PRODUCTS)
#   PRODUCTS            space-separated "id|DisplayName|PREFIX" tuples (default: ecosystem set)
set -euo pipefail

HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
COMMON_PLAT="${COMMON_PLAT:-$(cd "$HERE/../../learning_ai_common_plat" 2>/dev/null && pwd || true)}"
PORT="${PORT:-4003}"
TRACKER_PORT="${TRACKER_PORT:-3003}"
PS_DIR="$COMMON_PLAT/services/platform-service"
TRACKER_DIR="$COMMON_PLAT/dashboards/tracker-web"
ENV_FILE="$PS_DIR/.env"
PID_FILE="$HERE/.gigafactory-platform-service.pid"
TRACKER_PID_FILE="$HERE/.gigafactory-tracker-web.pid"
LOG_FILE="${TMPDIR:-/tmp}/gigafactory-platform-service.log"
TRACKER_LOG="${TMPDIR:-/tmp}/gigafactory-tracker-web.log"
BASE="http://localhost:$PORT"
TRACKER_URL="http://localhost:$TRACKER_PORT"

PRODUCTS="${PRODUCTS:-\
lysnrai|LysnrAI|LYS \
mindlyst|MindLyst|MIND \
chronomind|ChronoMind|CHR \
jarvisjr|JarvisJr|JAR \
nomgap|NomGap|NOM \
peakpulse|PeakPulse|PEAK \
flowmonk|FlowMonk|FLOW \
notelett|NoteLett|NOTE \
actiontrail|ActionTrail|ACT \
localmemgpt|LocalMemGPT|LMG \
efforise|EffoRise|EFF}"

die() { echo "error: $*" >&2; exit 1; }

# Stop a process recorded in a pid file, plus any children it spawned
# (next dev / pnpm fork worker processes). Returns 0 if it stopped something.
stop_pidfile() {
  local pidfile="$1" label="$2"
  [ -f "$pidfile" ] || return 1
  local pid; pid="$(cat "$pidfile")"
  if kill -0 "$pid" 2>/dev/null; then
    pkill -P "$pid" 2>/dev/null || true
    kill "$pid" 2>/dev/null && echo "stopped $label (pid $pid)"
  fi
  rm -f "$pidfile"
  return 0
}

stop_service() {
  local stopped=1
  stop_pidfile "$TRACKER_PID_FILE" "tracker-web" && stopped=0
  stop_pidfile "$PID_FILE" "platform-service" && stopped=0
  [ "$stopped" = 0 ] || echo "no pid files; nothing started by this script"
}

mint_token() {
  node -e '
    const c=require("crypto");const s=process.env.JWT_SECRET;
    if(!s){console.error("JWT_SECRET not set");process.exit(1);}
    const b=o=>Buffer.from(JSON.stringify(o)).toString("base64url");
    const h=b({alg:"HS256",typ:"JWT"});const n=Math.floor(Date.now()/1e3);
    const p=b({sub:"gigafactory-deploy",email:"deploy@bytelyst.local",role:"admin",type:"access",iat:n,exp:n+3600});
    console.log(`${h}.${p}.`+c.createHmac("sha256",s).update(`${h}.${p}`).digest("base64url"));
  '
}

# wait_for_url <url> <label> <attempts> <logfile>
wait_for_url() {
  local url="$1" label="$2" attempts="${3:-60}" log="${4:-}"
  echo -n "waiting for $url "
  for _ in $(seq 1 "$attempts"); do
    if curl -fsS "$url" >/dev/null 2>&1; then echo "— ok"; return 0; fi
    echo -n "."; sleep 1
  done
  echo; die "$label did not become ready${log:+ (see $log)}"
}

wait_for_health() { wait_for_url "$BASE/health" "platform-service" 60 "$LOG_FILE"; }

# Start the web tracker (tracker-web) wired to the local fleet backend.
start_tracker() {
  [ -d "$TRACKER_DIR" ] || die "tracker-web not found at $TRACKER_DIR (set COMMON_PLAT)"
  local first; first="$(echo "$PRODUCTS" | awk '{print $1}' | cut -d'|' -f1)"
  local product="${DEFAULT_PRODUCT_ID:-$first}"
  if curl -fsS "$TRACKER_URL" >/dev/null 2>&1; then
    echo "tracker-web already responding on :$TRACKER_PORT — reusing it"
    return 0
  fi
  echo "starting tracker-web (web tracker) on :$TRACKER_PORT (log: $TRACKER_LOG)"
  ( cd "$TRACKER_DIR" && \
    PLATFORM_API_URL="$BASE" \
    PLATFORM_SERVICE_URL="$BASE" \
    JWT_SECRET="${JWT_SECRET:-}" \
    DEFAULT_PRODUCT_ID="$product" \
    PRODUCT_ID="$product" \
    pnpm dev >"$TRACKER_LOG" 2>&1 ) &
  echo $! >"$TRACKER_PID_FILE"
  # next dev needs a first compile; give it longer than the API health wait.
  wait_for_url "$TRACKER_URL" "tracker-web" 120 "$TRACKER_LOG"
}

register_products() {
  local token; token="$(mint_token)"
  local created=0 existed=0 failed=0
  for tuple in $PRODUCTS; do
    IFS='|' read -r id name prefix <<<"$tuple"
    local code; code="$(curl -s -o /dev/null -w '%{http_code}' -X POST "$BASE/api/products" \
      -H "Authorization: Bearer $token" -H "content-type: application/json" \
      -H "x-product-id: $id" \
      -d "{\"productId\":\"$id\",\"displayName\":\"$name\",\"licensePrefix\":\"$prefix\"}")"
    case "$code" in
      200|201) echo "  created  $id"; created=$((created+1));;
      409)     echo "  exists   $id"; existed=$((existed+1));;
      *)       echo "  FAILED   $id (HTTP $code)"; failed=$((failed+1));;
    esac
  done
  echo "products: created=$created existed=$existed failed=$failed"
  # live smoke: fleet metrics for the first product
  local first; first="$(echo "$PRODUCTS" | awk '{print $1}' | cut -d'|' -f1)"
  echo -n "smoke GET /api/fleet/metrics ($first): "
  curl -s -H "Authorization: Bearer $(mint_token)" -H "x-product-id: $first" \
    "$BASE/api/fleet/metrics" | head -c 200; echo
}

# ── main ─────────────────────────────────────────────────────────
MODE_STOP=0; DO_BACKEND=1; DO_REGISTER=1; WITH_TRACKER=0
for arg in "$@"; do
  case "$arg" in
    --stop)          MODE_STOP=1;;
    --register-only) DO_BACKEND=0;;
    --no-register)   DO_REGISTER=0;;
    --no-backend)    DO_BACKEND=0;;
    --with-tracker)  WITH_TRACKER=1;;
    --full)          DO_BACKEND=1; DO_REGISTER=1; WITH_TRACKER=1;;
    --tracker-only)  DO_BACKEND=0; DO_REGISTER=0; WITH_TRACKER=1;;
    -h|--help)       sed -n '13,27p' "${BASH_SOURCE[0]}" | sed 's/^# \{0,1\}//'; exit 0;;
    *)               die "unknown argument: $arg (try --help)";;
  esac
done

if [ "$MODE_STOP" = 1 ]; then stop_service; exit 0; fi

[ -n "$COMMON_PLAT" ] && [ -d "$PS_DIR" ] || die "platform-service not found (set COMMON_PLAT). Looked in: $PS_DIR"
[ -f "$ENV_FILE" ] || die "$ENV_FILE missing — fill it (Cosmos endpoint/key, JWT_SECRET, blob CS)"
set -a; . "$ENV_FILE"; set +a

if [ "$DO_BACKEND" = 1 ]; then
  if curl -fsS "$BASE/health" >/dev/null 2>&1; then
    echo "platform-service already healthy on :$PORT — reusing it"
  else
    echo "starting platform-service on :$PORT (log: $LOG_FILE)"
    ( cd "$PS_DIR" && pnpm exec tsx src/server.ts >"$LOG_FILE" 2>&1 ) &
    echo $! >"$PID_FILE"
    wait_for_health
  fi
fi

if [ "$DO_REGISTER" = 1 ]; then
  register_products
fi

if [ "$WITH_TRACKER" = 1 ]; then
  start_tracker
fi

cat <<EOF

Gigafactory is up on $BASE  (health: $BASE/health)
EOF
if [ "$WITH_TRACKER" = 1 ]; then
  cat <<EOF
Web tracker is up on $TRACKER_URL  (proxies fleet API -> $BASE)
Next:
  - Open:     $TRACKER_URL
  - Stop all: $HERE/$(basename "$0") --stop
EOF
else
  cat <<EOF
Next:
  - Web UI:   $HERE/$(basename "$0") --with-tracker   (start tracker-web on :$TRACKER_PORT)
  - Run e2e:  (cd "$TRACKER_DIR" && pnpm exec playwright test)
  - Stop:     $HERE/$(basename "$0") --stop
EOF
fi
