#!/bin/bash
# deploy.sh – Rebreak Deploy Script (backend/-Layout, post-cutover)
#
# Wird vom Webhook-Listener (scripts/deploy-webhook/server.mjs) aufgerufen.
# Repo-Root: /srv/rebreak
# Clone:     git@github.com:RaynisDev/rebreak.git
# Backend:   /srv/rebreak/backend  (standalone Nitro, package: rebreak-backend)
#
# Ablauf:
#   1. Git pull (via Deploy-Key)
#   2. pnpm install --frozen-lockfile (mit hoisted node-linker via .npmrc)
#   3. cd backend && pnpm --filter rebreak-backend build (Prisma generate + Nitro build)
#   4. .output → .output-staging (atomisch via tmp)
#   5. pm2 restart rebreak-staging --update-env
#   6. pm2 restart rebreak-imap-staging / rebreak-idle-staging (best-effort, falls vorhanden)
#   7. pm2 restart dns-rebreak-staging / dns-rebreak (best-effort, falls vorhanden)
#
# Secrets: via Infisical (INFISICAL_CLIENT_ID/SECRET in /etc/environment) — NICHT hier,
#          sondern in start-staging.sh / ecosystem.config.js zur Laufzeit.

set -euo pipefail

REPO_ROOT="/srv/rebreak"
APP_DIR="${REPO_ROOT}/backend"
NODE_BIN="/root/.nvm/versions/node/v24.11.1/bin/node"
PNPM_BIN="/root/.nvm/versions/node/v24.11.1/bin/pnpm"
PM2_BIN="/root/.nvm/versions/node/v24.11.1/bin/pm2"

log() { echo "[deploy] $(date '+%H:%M:%S') $*"; }
log_err() { echo "[deploy:err] $(date '+%H:%M:%S') $*" >&2; }

log "=== Rebreak Deploy gestartet (backend/-Layout) ==="

# 0. Sicherstellen dass PATH stimmt
export PATH="/root/.nvm/versions/node/v24.11.1/bin:$PATH"

# 1. Git pull via Deploy-Key (SSH ist konfiguriert in /root/.ssh/config)
log "Step 1: git pull..."
cd "${REPO_ROOT}"
git fetch origin main 2>&1
git reset --hard origin/main 2>&1
git clean -fd 2>&1
log "Git updated to $(git rev-parse --short HEAD)"

# 2. pnpm install (workspace-root, .npmrc mit node-linker=hoisted ist im Repo)
log "Step 2: pnpm install --frozen-lockfile..."
cd "${REPO_ROOT}"
CI=true "${PNPM_BIN}" install --frozen-lockfile 2>&1 || {
  log_err "frozen-lockfile fehlgeschlagen, fallback ohne frozen..."
  CI=true "${PNPM_BIN}" install --no-frozen-lockfile 2>&1
}
log "pnpm install done"

# 2.5 Prisma-Migration auto-deploy wenn neue migration-files committed wurden
#     Detect via git diff zwischen .last-deployed-sha und HEAD.
#     Idempotent: prisma migrate deploy skipped already-applied migrations.
#     Failure-Mode: bei Migration-Fehler pm2 NICHT restarten (alter Code/alte DB konsistent).
#     First-deploy-Edge-Case: wenn .last-deployed-sha fehlt → Migration ausführen (sicher
#     weil idempotent).
log "Step 2.5: Migration-Check..."
PREV_SHA=$(cat "${REPO_ROOT}/.last-deployed-sha" 2>/dev/null || echo "")
CUR_SHA=$(git -C "${REPO_ROOT}" rev-parse HEAD)

run_migration=false
if [[ -z "$PREV_SHA" ]]; then
  log "Kein .last-deployed-sha gefunden — first-deploy: Migration sicherheitshalber ausführen"
  run_migration=true
elif ! git -C "${REPO_ROOT}" diff --quiet "$PREV_SHA"..HEAD -- backend/prisma/migrations/ backend/prisma/schema.prisma; then
  log "Migration-Changes detected zwischen ${PREV_SHA} und ${CUR_SHA}"
  run_migration=true
else
  log "Keine Migration-Changes seit ${PREV_SHA} — skip migrate deploy"
fi

if $run_migration; then
  log "Running prisma migrate deploy..."
  cd "${APP_DIR}"

  # Infisical-Wrapper für DATABASE_URL (analog start-staging.sh)
  source /etc/environment
  if [[ -z "${INFISICAL_CLIENT_ID:-}" || -z "${INFISICAL_CLIENT_SECRET:-}" ]]; then
    log_err "INFISICAL_CLIENT_ID / INFISICAL_CLIENT_SECRET fehlt — kann Migration nicht ausführen"
    exit 1
  fi

  INFISICAL_TOKEN=$(infisical login \
    --method=universal-auth \
    --client-id="${INFISICAL_CLIENT_ID}" \
    --client-secret="${INFISICAL_CLIENT_SECRET}" \
    --silent --plain 2>/dev/null)

  if [[ -z "$INFISICAL_TOKEN" ]]; then
    log_err "Infisical login fehlgeschlagen — Migration abgebrochen"
    exit 1
  fi

  # DATABASE_URL injecten via infisical run; Aliasing analog start-staging.sh
  # (Infisical-Secret heißt evtl. NUXT_DATABASE_URL, prisma erwartet DATABASE_URL).
  infisical run \
    --projectId="${INFISICAL_PROJECT_ID:-14b11b35-ef59-4b8a-a16b-398f0cc3ad93}" \
    --env=staging \
    --token="$INFISICAL_TOKEN" \
    -- bash -c '
      set -e
      export DATABASE_URL="${DATABASE_URL:-${NUXT_DATABASE_URL:-}}"
      if [[ -z "$DATABASE_URL" ]]; then
        echo "[deploy:err] DATABASE_URL nicht in Infisical-staging — Migration abgebrochen" >&2
        exit 1
      fi
      "'"${PNPM_BIN}"'" prisma migrate deploy --schema prisma/schema.prisma
    ' 2>&1 || {
    log_err "Migration-Deploy fehlgeschlagen — pm2-restart ABGEBROCHEN (Daten-Konsistenz-Schutz)"
    exit 1
  }

  log "Migration done"
fi

# 3. Build backend (Nitro standalone) — Prisma generate ist Teil des build-scripts
log "Step 3: pnpm --filter rebreak-backend build..."
cd "${APP_DIR}"
# NODE_OPTIONS: max 1.5 GB für den Build-Prozess (4 GB RAM Server)
NODE_OPTIONS="--max-old-space-size=1536" CI=true "${PNPM_BIN}" --filter rebreak-backend build 2>&1
log "Build done"

# 4. Atomisches Deploy: .output → .output-staging (relativ zu backend/)
log "Step 4: Atomisches Deploy .output → .output-staging..."
cd "${APP_DIR}"
if [ -d ".output" ]; then
  rm -rf .output-staging-new
  cp -r .output .output-staging-new
  rm -rf .output-staging
  mv .output-staging-new .output-staging
  log ".output-staging aktualisiert"
else
  log_err "FEHLER: .output Verzeichnis nicht gefunden nach Build!"
  exit 1
fi

# 5. pm2 restart rebreak-staging (--update-env zieht neue Infisical-secrets)
log "Step 5: pm2 restart rebreak-staging..."
"${PM2_BIN}" restart rebreak-staging --update-env 2>/dev/null || \
  "${PM2_BIN}" start "${REPO_ROOT}/ecosystem.config.js" --only rebreak-staging
log "rebreak-staging restarted"

# 6. IMAP + DNS Services (optional – kein Fehler wenn nicht vorhanden, Mo's Scope)
log "Step 6: Optional services restart..."
"${PM2_BIN}" restart rebreak-imap-staging 2>/dev/null || true
"${PM2_BIN}" restart rebreak-idle-staging 2>/dev/null || true
"${PM2_BIN}" restart dns-rebreak-staging 2>/dev/null || \
  "${PM2_BIN}" start "${REPO_ROOT}/ecosystem.config.js" --only dns-rebreak-staging 2>/dev/null || true
"${PM2_BIN}" restart dns-rebreak 2>/dev/null || \
  "${PM2_BIN}" start "${REPO_ROOT}/ecosystem.config.js" --only dns-rebreak 2>/dev/null || true

# 7. pm2 save
"${PM2_BIN}" save 2>/dev/null || true

# 8. Last-deployed-SHA persistieren (für Step 2.5 beim nächsten Deploy)
echo "${CUR_SHA}" > "${REPO_ROOT}/.last-deployed-sha"
log "Last-deployed-SHA gespeichert: ${CUR_SHA}"

log "=== Deploy erfolgreich: $(git -C ${REPO_ROOT} rev-parse --short HEAD) ==="
