#!/usr/bin/env bash
# Deploy VPD Backoffice to an SSH-accessible VM.
set -Eeuo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

# shellcheck disable=SC1091
. "$ROOT/scripts/lib/common.sh"

HOST="hermes"
REMOTE_DIR='$HOME/apps/vpd-backoffice'
REMOTE_PORT="${BACKOFFICE_PORT:-8082}"
IDENTITY_FILE=""
KNOWN_HOSTS_FILE=""
ACCEPT_HOST_KEY="N"
DRY_RUN="N"
SKIP_BUILD="N"
START_APP="Y"

usage() {
  cat <<USAGE
Usage: $0 [--host SSH_ALIAS] [--identity-file KEY] [--known-hosts-file FILE] [--accept-host-key] [--remote-dir PATH] [--port PORT] [--dry-run] [--skip-build] [--no-start]

Defaults:
  --host       hermes
  --remote-dir \$HOME/apps/vpd-backoffice
  --port       8082

Production transport defaults are always applied on the VM:
  bind address 127.0.0.1, forwarded headers enabled,
  HTTPS required, Secure/HttpOnly/SameSite session cookie.

The script uploads:
  - target/*.jar as app.jar
  - .env rewritten for the VM wallet path
  - TNS_ADMIN wallet directory
  - start.sh / stop.sh / status.sh
USAGE
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --host)
      HOST="${2:?--host requires a value}"
      shift 2
      ;;
    --identity-file)
      IDENTITY_FILE="${2:?--identity-file requires a value}"
      shift 2
      ;;
    --known-hosts-file)
      KNOWN_HOSTS_FILE="${2:?--known-hosts-file requires a value}"
      shift 2
      ;;
    --accept-host-key)
      ACCEPT_HOST_KEY="Y"
      shift
      ;;
    --remote-dir)
      REMOTE_DIR="${2:?--remote-dir requires a value}"
      shift 2
      ;;
    --port)
      REMOTE_PORT="${2:?--port requires a value}"
      shift 2
      ;;
    --dry-run)
      DRY_RUN="Y"
      shift
      ;;
    --skip-build)
      SKIP_BUILD="Y"
      shift
      ;;
    --no-start)
      START_APP="N"
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      die "알 수 없는 옵션: $1"
      ;;
  esac
done

[[ -f "$ROOT/.env" ]] || die ".env 파일이 없습니다."
# shellcheck disable=SC1091
set -a; . "$ROOT/.env"; set +a

require_env TNS_ADMIN ADB_TNS BACKOFFICE_DB_USERNAME BACKOFFICE_DB_PASSWORD
[[ -d "$TNS_ADMIN" ]] || die "TNS_ADMIN 디렉토리가 없습니다: $TNS_ADMIN"
[[ -f "$TNS_ADMIN/tnsnames.ora" ]] || die "tnsnames.ora가 없습니다: $TNS_ADMIN/tnsnames.ora"

REMOTE_WALLET_DIR="${REMOTE_DIR%/}/wallet"
REMOTE_ENV_FILE="${REMOTE_DIR%/}/.env"
SSH_ARGS=(-o BatchMode=yes -o ConnectTimeout=8)
if [[ -n "$IDENTITY_FILE" ]]; then
  [[ -f "$IDENTITY_FILE" ]] || die "identity file을 찾을 수 없습니다: $IDENTITY_FILE"
  SSH_ARGS+=(-i "$IDENTITY_FILE")
fi
if [[ -n "$KNOWN_HOSTS_FILE" ]]; then
  SSH_ARGS+=(-o "UserKnownHostsFile=$KNOWN_HOSTS_FILE")
fi
if [[ "$ACCEPT_HOST_KEY" == "Y" ]]; then
  SSH_ARGS+=(-o StrictHostKeyChecking=no)
fi

if [[ "$DRY_RUN" == "Y" ]]; then
  log "dry-run: host=$HOST"
  [[ -n "$IDENTITY_FILE" ]] && log "dry-run: identity_file=$IDENTITY_FILE"
  log "dry-run: remote_dir=$REMOTE_DIR"
  log "dry-run: remote_wallet_dir=$REMOTE_WALLET_DIR"
  log "dry-run: port=$REMOTE_PORT"
  log "dry-run: bind_address=127.0.0.1"
  log "dry-run: require_https=true"
  log "dry-run: session_cookie_secure=true"
  log "dry-run: local_wallet=$TNS_ADMIN"
  exit 0
fi

log "SSH 대상 확인: $HOST"
ssh "${SSH_ARGS[@]}" "$HOST" 'printf "connected %s %s\n" "$(hostname)" "$(whoami)"'

if [[ "$SKIP_BUILD" != "Y" ]]; then
  log "jar 빌드"
  mvn -DskipTests package
fi

JAR_PATH="$(find "$ROOT/target" -maxdepth 1 -type f -name '*.jar' ! -name '*sources.jar' ! -name '*javadoc.jar' | sort | tail -n 1)"
[[ -n "$JAR_PATH" && -f "$JAR_PATH" ]] || die "target jar를 찾을 수 없습니다. mvn package를 먼저 실행하세요."

TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/vpd-backoffice-deploy.XXXXXX")"
cleanup() {
  rm -rf "$TMP_DIR"
}
trap cleanup EXIT

mkdir -p "$TMP_DIR/wallet"
cp "$JAR_PATH" "$TMP_DIR/app.jar"
cp -R "$TNS_ADMIN"/. "$TMP_DIR/wallet/"

cp "$ROOT/.env" "$TMP_DIR/.env"
cat >> "$TMP_DIR/.env" <<ENVEOF

# --- VM deployment overrides ---
export TNS_ADMIN="${REMOTE_WALLET_DIR}"
export BACKOFFICE_DB_URL="jdbc:oracle:thin:@\${ADB_TNS}?TNS_ADMIN=\${TNS_ADMIN}"
export BACKOFFICE_ORDS_DB_URL="\${BACKOFFICE_DB_URL}"
export BACKOFFICE_PORT="${REMOTE_PORT}"
export BACKOFFICE_BIND_ADDRESS="127.0.0.1"
export BACKOFFICE_FORWARD_HEADERS_STRATEGY="framework"
export BACKOFFICE_REQUIRE_HTTPS="true"
export BACKOFFICE_SESSION_COOKIE_SECURE="true"
ENVEOF
chmod 600 "$TMP_DIR/.env"

cat > "$TMP_DIR/start.sh" <<'START'
#!/usr/bin/env bash
set -Eeuo pipefail
APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$APP_DIR"
set -a
. "$APP_DIR/.env"
set +a
PID_FILE="$APP_DIR/app.pid"
LOG_FILE="$APP_DIR/app.log"

if [[ -f "$PID_FILE" ]] && kill -0 "$(cat "$PID_FILE")" >/dev/null 2>&1; then
  echo "already running pid=$(cat "$PID_FILE")"
  exit 0
fi

setsid nohup java -jar "$APP_DIR/app.jar" > "$LOG_FILE" 2>&1 < /dev/null &
echo $! > "$PID_FILE"
echo "started pid=$(cat "$PID_FILE") log=$LOG_FILE"
START

cat > "$TMP_DIR/stop.sh" <<'STOP'
#!/usr/bin/env bash
set -Eeuo pipefail
APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PID_FILE="$APP_DIR/app.pid"

if [[ ! -f "$PID_FILE" ]]; then
  echo "not running: pid file not found"
  exit 0
fi

PID="$(cat "$PID_FILE")"
if kill -0 "$PID" >/dev/null 2>&1; then
  kill "$PID"
  for _ in {1..20}; do
    if ! kill -0 "$PID" >/dev/null 2>&1; then
      break
    fi
    sleep 1
  done
fi
rm -f "$PID_FILE"
echo "stopped"
STOP

cat > "$TMP_DIR/status.sh" <<'STATUS'
#!/usr/bin/env bash
set -Eeuo pipefail
APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PID_FILE="$APP_DIR/app.pid"
if [[ -f "$PID_FILE" ]] && kill -0 "$(cat "$PID_FILE")" >/dev/null 2>&1; then
  echo "running pid=$(cat "$PID_FILE")"
else
  echo "stopped"
fi
STATUS

chmod +x "$TMP_DIR/start.sh" "$TMP_DIR/stop.sh" "$TMP_DIR/status.sh"

log "원격 디렉토리 생성"
ssh "${SSH_ARGS[@]}" "$HOST" "mkdir -p \"$REMOTE_DIR\""

log "패키지 업로드"
tar -C "$TMP_DIR" -czf - app.jar .env wallet start.sh stop.sh status.sh \
  | ssh "${SSH_ARGS[@]}" "$HOST" "tar -C \"$REMOTE_DIR\" -xzf - && chmod 600 \"$REMOTE_ENV_FILE\" && chmod +x \"$REMOTE_DIR\"/start.sh \"$REMOTE_DIR\"/stop.sh \"$REMOTE_DIR\"/status.sh"

log "원격 Java 확인"
ssh "${SSH_ARGS[@]}" "$HOST" "java -version >/tmp/vpd-backoffice-java-version.out 2>&1 && cat /tmp/vpd-backoffice-java-version.out | head -n 1"

if [[ "$START_APP" == "Y" ]]; then
  log "원격 앱 재기동"
  ssh "${SSH_ARGS[@]}" "$HOST" "\"$REMOTE_DIR\"/stop.sh || true; \"$REMOTE_DIR\"/start.sh; sleep 8; \"$REMOTE_DIR\"/status.sh"

  log "원격 헬스체크"
  ssh "${SSH_ARGS[@]}" "$HOST" "curl -sS -H 'X-Forwarded-Proto: https' -H 'X-Forwarded-Host: localhost' -o /tmp/vpd-backoffice-login.html -w '%{http_code}\n' http://127.0.0.1:${REMOTE_PORT}/login"
fi

ok "배포 완료: $HOST:$REMOTE_DIR"
