#!/usr/bin/env bash

set -euo pipefail

APP_DIR="${APP_DIR:-/opt/ypchat}"
REPO_URL="${REPO_URL:-ssh://git@tsschulz.de:2222/torsten/singlechat}"
BRANCH="${BRANCH:-main}"
SERVICE_NAME="${SERVICE_NAME:-ypchat}"
RUN_USER="${RUN_USER:-www-data}"
RUN_GROUP="${RUN_GROUP:-www-data}"
DEPLOY_USER="${DEPLOY_USER:-${SUDO_USER:-$(id -un)}}"
DEPLOY_GROUP="${DEPLOY_GROUP:-$(id -gn "$DEPLOY_USER")}"
LOCK_DIR="${LOCK_DIR:-/tmp/actualize-singlechat}"
LOCK_FILE="${LOCK_FILE:-$LOCK_DIR/deploy.lock}"
NPM_CACHE_DIR="${NPM_CACHE_DIR:-$APP_DIR/.npm-cache}"

log() {
  printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*"
}

run_as_deploy_user() {
  if [ "$(id -u)" -eq 0 ]; then
    sudo -u "$DEPLOY_USER" env HOME="$(getent passwd "$DEPLOY_USER" | cut -d: -f6)" npm_config_cache="$NPM_CACHE_DIR" "$@"
  else
    env HOME="$APP_DIR" npm_config_cache="$NPM_CACHE_DIR" "$@"
  fi
}

need_cmd() {
  if ! command -v "$1" >/dev/null 2>&1; then
    echo "FEHLER: $1 ist nicht installiert." >&2
    exit 1
  fi
}

need_cmd git
need_cmd npm
need_cmd node
need_cmd rsync
need_cmd flock
need_cmd openssl
if [ "$(id -u)" -ne 0 ]; then
  need_cmd sudo
fi

mkdir -p "$LOCK_DIR"
if [ "$(id -u)" -eq 0 ]; then
  chown "$DEPLOY_USER:$DEPLOY_GROUP" "$LOCK_DIR" 2>/dev/null || true
fi
exec 9>"$LOCK_FILE"
if ! flock -n 9; then
  echo "Deployment laeuft bereits: $LOCK_FILE" >&2
  exit 1
fi

log "Starte SingleChat Rollout"
log "APP_DIR=$APP_DIR"
log "REPO_URL=$REPO_URL"
log "BRANCH=$BRANCH"
log "SERVICE_NAME=$SERVICE_NAME"
log "DEPLOY_USER=$DEPLOY_USER"

mkdir -p "$APP_DIR" "$NPM_CACHE_DIR"
if [ "$(id -u)" -eq 0 ]; then
  chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$APP_DIR" "$NPM_CACHE_DIR"
fi

if [ ! -d "$APP_DIR/.git" ]; then
  log "Erstelle initialen Git-Checkout fuer $APP_DIR"
  if [ "$(id -u)" -eq 0 ]; then
    tmp_checkout="$(sudo -u "$DEPLOY_USER" mktemp -d)"
  else
    tmp_checkout="$(mktemp -d)"
  fi
  run_as_deploy_user git clone --branch "$BRANCH" --single-branch "$REPO_URL" "$tmp_checkout"
  rsync -a --delete \
    --no-owner \
    --no-group \
    --omit-dir-times \
    --exclude '.env' \
    --exclude '.npm-cache/' \
    --exclude 'node_modules/' \
    --exclude 'client/node_modules/' \
    --exclude 'client/dist/' \
    --exclude 'docroot/dist/' \
    --exclude 'logs/' \
    --exclude 'tmp/' \
    "$tmp_checkout/" "$APP_DIR/"
  rm -rf "$tmp_checkout"
fi

if [ "$(id -u)" -eq 0 ]; then
  chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$APP_DIR" "$NPM_CACHE_DIR"
fi

cd "$APP_DIR"

if ! run_as_deploy_user git remote get-url origin >/dev/null 2>&1; then
  run_as_deploy_user git remote add origin "$REPO_URL"
fi

current_origin="$(run_as_deploy_user git remote get-url origin)"
if [ "$current_origin" != "$REPO_URL" ]; then
  log "Setze Git-Origin von $current_origin auf $REPO_URL"
  run_as_deploy_user git remote set-url origin "$REPO_URL"
fi

log "Hole neuesten Stand"
run_as_deploy_user git fetch --prune origin "$BRANCH"
run_as_deploy_user git reset --hard "origin/$BRANCH"
run_as_deploy_user git clean -fd \
  -e .env \
  -e .npm-cache/ \
  -e node_modules/ \
  -e client/node_modules/ \
  -e client/dist/ \
  -e logs/ \
  -e tmp/ \
  -e docroot/dist/

if [ "$(id -u)" -eq 0 ]; then
  chown -R "$DEPLOY_USER:$DEPLOY_GROUP" "$APP_DIR" "$NPM_CACHE_DIR"
fi

log "Installiere Root-Dependencies"
run_as_deploy_user npm ci

log "Installiere Client-Dependencies"
run_as_deploy_user npm --prefix client ci

if [ ! -f "$APP_DIR/.env" ]; then
  log "Erstelle .env"
  session_secret="$(openssl rand -hex 32)"
  cat > "$APP_DIR/.env" <<EOF
NODE_ENV=production
PORT=4000
SESSION_SECRET=$session_secret
EOF
fi

if [ "$(id -u)" -eq 0 ]; then
  chown "$RUN_USER:$RUN_GROUP" "$APP_DIR/.env"
fi

log "Baue Client"
run_as_deploy_user npm run build

log "Aktualisiere docroot/dist"
rm -rf "$APP_DIR/docroot/dist"
cp -r "$APP_DIR/client/dist" "$APP_DIR/docroot/dist"

mkdir -p "$APP_DIR/logs" "$APP_DIR/tmp"
if [ "$(id -u)" -eq 0 ]; then
  chown -R "$RUN_USER:$RUN_GROUP" "$APP_DIR/docroot/dist" "$APP_DIR/logs" "$APP_DIR/tmp"
fi

log "Pruefe Server-Syntax"
node --check "$APP_DIR/server/index.js"
node --check "$APP_DIR/server/routes-seo.js"

if command -v systemctl >/dev/null 2>&1; then
  log "Starte Service neu: $SERVICE_NAME"
  if [ "$(id -u)" -eq 0 ]; then
    systemctl restart "$SERVICE_NAME"
    systemctl --no-pager --lines=20 status "$SERVICE_NAME"
  else
    sudo systemctl restart "$SERVICE_NAME"
    sudo systemctl --no-pager --lines=20 status "$SERVICE_NAME"
  fi
else
  log "systemctl nicht gefunden, Service-Neustart uebersprungen"
fi

log "SingleChat Rollout abgeschlossen"
