#!/usr/bin/env bash
set -uo pipefail

APP_VERSION="1.5.2-r3"
APP_DIR=/opt/docking-riset
APP="$APP_DIR/docking_riset_app.py"
VERSIONED_APP="$APP_DIR/Docking_Riset_1.5.2-r3.py"
[ -f "$APP" ] || APP="$VERSIONED_APP"
DATA_DIR="${DOCKING_RISET_DATA_DIR:-$HOME/.local/share/docking-riset}"
ENV_NEW="$DATA_DIR/env-1.4.1"
ENV_OLD1="$DATA_DIR/env-1.4.0"
ENV_OLD2="$DATA_DIR/env-1.3.9"
ENV_OLD3="$DATA_DIR/env-1.3.8"
ENV_OLD4="$DATA_DIR/env-1.3.7"
ENV_OLD5="$DATA_DIR/env-1.3.6"
PORT="${DOCKING_RISET_PORT:-8802}"
URL="http://127.0.0.1:${PORT}"
LOG_DIR="$DATA_DIR/logs"
SERVER_LOG="$LOG_DIR/streamlit-server.log"
SUP_LOG="$LOG_DIR/server-supervisor.log"
STATUS_FILE="$LOG_DIR/server_status.json"
CRASH_DIAG="$LOG_DIR/last_crash_diagnostics.txt"
LOCK_FILE="$DATA_DIR/server-${PORT}.lock"
SUP_PID_FILE="$DATA_DIR/server-${PORT}-supervisor.pid"
MAX_RESTARTS="${DOCKING_RISET_MAX_RESTARTS:-0}"
HEALTH_INTERVAL="${DOCKING_RISET_HEALTH_INTERVAL:-5}"
HEALTH_FAIL_LIMIT="${DOCKING_RISET_HEALTH_FAIL_LIMIT:-12}"
STARTUP_GRACE="${DOCKING_RISET_STARTUP_GRACE:-120}"
RESTART_ON_UNHEALTHY="${DOCKING_RISET_RESTART_ON_UNHEALTHY:-1}"
SYSTEMD_UNIT="docking-riset.service"

mkdir -p "$DATA_DIR" "$LOG_DIR"

choose_env() {
  if [ -x "$ENV_NEW/bin/python" ]; then
    VENV="$ENV_NEW"
  elif [ -x "$ENV_OLD1/bin/python" ]; then
    VENV="$ENV_OLD1"
  elif [ -x "$ENV_OLD2/bin/python" ]; then
    VENV="$ENV_OLD2"
  elif [ -x "$ENV_OLD3/bin/python" ]; then
    VENV="$ENV_OLD3"
  elif [ -x "$ENV_OLD4/bin/python" ]; then
    VENV="$ENV_OLD4"
  elif [ -x "$ENV_OLD5/bin/python" ]; then
    VENV="$ENV_OLD5"
  else
    VENV="$ENV_NEW"
  fi
  PY="$VENV/bin/python"
  export DOCKING_RISET_DATA_DIR="$DATA_DIR"
  export PATH="$VENV/bin:$PATH"
}
choose_env

log() {
  local msg="[$(date '+%Y-%m-%d %H:%M:%S')] $*"
  printf '%s\n' "$msg" >> "$SUP_LOG"
  if [ -t 1 ]; then printf '%s\n' "$msg"; fi
}

rotate_log() {
  local f="$1" max="${2:-10485760}"
  if [ -f "$f" ]; then
    local size
    size=$(wc -c < "$f" 2>/dev/null || printf '0')
    if [ "${size:-0}" -gt "$max" ]; then
      mv -f "$f" "${f}.1" 2>/dev/null || true
      : > "$f"
    fi
  fi
}

pid_alive() {
  local p="${1:-0}"
  [ "$p" -gt 1 ] 2>/dev/null && kill -0 "$p" 2>/dev/null
}

read_pid_file() {
  if [ -s "$SUP_PID_FILE" ]; then
    tr -cd '0-9' < "$SUP_PID_FILE" 2>/dev/null || true
  fi
}

health_check() {
  [ -x "$PY" ] || return 1
  # Coba endpoint health resmi lebih dulu, lalu root page sebagai fallback.
  # Fallback mencegah restart palsu bila endpoint health berubah tetapi HTTP server masih sehat.
  "$PY" - "$URL/_stcore/health" "$URL/" <<'PY' >/dev/null 2>&1
import sys, urllib.request
for url in sys.argv[1:]:
    try:
        req = urllib.request.Request(url, headers={"User-Agent": "Docking-Riset-Supervisor/1.5.2-r3"})
        with urllib.request.urlopen(req, timeout=2.0) as r:
            if 200 <= int(getattr(r, "status", 0)) < 400:
                raise SystemExit(0)
    except Exception:
        pass
raise SystemExit(1)
PY
}

open_url() {
  if grep -qi microsoft /proc/version 2>/dev/null && command -v explorer.exe >/dev/null 2>&1; then
    explorer.exe "$URL" >/dev/null 2>&1 & disown || true
  elif command -v xdg-open >/dev/null 2>&1 && [ -n "${DISPLAY:-}${WAYLAND_DISPLAY:-}" ]; then
    xdg-open "$URL" >/dev/null 2>&1 & disown || true
  elif command -v gio >/dev/null 2>&1 && [ -n "${DISPLAY:-}${WAYLAND_DISPLAY:-}" ]; then
    gio open "$URL" >/dev/null 2>&1 & disown || true
  elif [ -x "$PY" ]; then
    "$PY" -m webbrowser -t "$URL" >/dev/null 2>&1 & disown || true
  fi
}

write_status() {
  local status="$1" pid="${2:-0}" restarts="${3:-0}" now tmp
  now=$(date '+%Y-%m-%d %H:%M:%S')
  tmp="${STATUS_FILE}.tmp.$$"
  printf '{"status":"%s","pid":%s,"port":%s,"restart_count":%s,"updated":"%s","url":"%s","supervisor_pid":%s,"launcher_version":"%s","app_path":"%s"}\n' \
    "$status" "${pid:-0}" "$PORT" "${restarts:-0}" "$now" "$URL" "$$" "$APP_VERSION" "$APP" > "$tmp"
  mv -f "$tmp" "$STATUS_FILE"
}

runtime_launcher_version() {
  [ -s "$STATUS_FILE" ] || return 1
  local py="${PY:-python3}"
  command -v "$py" >/dev/null 2>&1 || py=python3
  "$py" - "$STATUS_FILE" <<'PY' 2>/dev/null
import json,sys
try:
    print(json.load(open(sys.argv[1], encoding="utf-8")).get("launcher_version", ""))
except Exception:
    pass
PY
}

ensure_dependencies() {
  choose_env
  local needs_install=0
  if [ ! -x "$PY" ]; then
    needs_install=1
  else
    "$PY" - <<'PY' >/dev/null 2>&1 || needs_install=1
import streamlit, numpy, pandas, scipy, requests, h5py
import rdkit, py3Dmol, vina, meeko, gemmi, tqdm
import openmm, pdbfixer, pyscf, geometric, berny, openbabel, prody
PY
    for c in obabel xtb mopac; do
      [ -x "$VENV/bin/$c" ] || needs_install=1
    done
    if [ ! -x "$VENV/bin/mk_prepare_receptor.py" ] && [ ! -x "$VENV/bin/mk_prepare_receptor" ]; then needs_install=1; fi
    if [ ! -x "$VENV/bin/mk_prepare_ligand.py" ] && [ ! -x "$VENV/bin/mk_prepare_ligand" ]; then needs_install=1; fi
  fi
  if [ "$needs_install" -eq 1 ]; then
    log "Dependensi FULL belum tersedia; menjalankan docking-riset-install all..."
    if ! /usr/bin/docking-riset-install all; then
      log "ERROR: instalasi FULL gagal. Jalankan: docking-riset-install repair"
      return 1
    fi
    choose_env
  fi
  return 0
}

collect_crash_diagnostics() {
  {
    echo "DOCKING RISET 1.5.2 — SERVER DIAGNOSTICS"
    echo "Time: $(date '+%Y-%m-%d %H:%M:%S')"
    echo "URL: $URL"
    echo "Supervisor PID: $$"
    echo
    echo "== uptime =="; uptime 2>&1 || true
    echo; echo "== memory =="; free -h 2>&1 || true
    echo; echo "== /proc/meminfo =="; head -30 /proc/meminfo 2>&1 || true
    echo; echo "== disk =="; df -h "$DATA_DIR" 2>&1 || true
    echo; echo "== top memory processes =="; ps -eo pid,ppid,pgid,sid,stat,%cpu,%mem,rss,cmd --sort=-rss 2>&1 | head -40 || true
    echo; echo "== kernel OOM clues =="; dmesg 2>&1 | grep -Ei 'out of memory|oom|killed process' | tail -40 || true
    echo; echo "== last Streamlit log =="; tail -200 "$SERVER_LOG" 2>&1 || true
    echo; echo "== last supervisor log =="; tail -120 "$SUP_LOG" 2>&1 || true
  } > "$CRASH_DIAG" 2>&1
}

systemd_user_available() {
  command -v systemctl >/dev/null 2>&1 || return 1
  systemctl --user show-environment >/dev/null 2>&1 || return 1
  [ -f /usr/lib/systemd/user/docking-riset.service ] || [ -f /lib/systemd/user/docking-riset.service ] || return 1
  return 0
}

supervisor_main() {
  ensure_dependencies || exit 1
  rotate_log "$SERVER_LOG"
  rotate_log "$SUP_LOG"

  export OMP_NUM_THREADS="${OMP_NUM_THREADS:-2}"
  export OPENBLAS_NUM_THREADS="${OPENBLAS_NUM_THREADS:-2}"
  export MKL_NUM_THREADS="${MKL_NUM_THREADS:-2}"
  export NUMEXPR_NUM_THREADS="${NUMEXPR_NUM_THREADS:-2}"


  if "$PY" "$APP_DIR/patch_streamlit_shell.py" >/dev/null 2>&1; then
    export DOCKING_RISET_TRANSLATION_GUARD=1
  else
    log "WARNING: browser-translation guard tidak dapat diterapkan."
  fi

  # Lock hanya dipegang daemon supervisor.
  if command -v flock >/dev/null 2>&1; then
    exec 9>"$LOCK_FILE"
    if ! flock -n 9; then
      log "Supervisor lain sudah memegang lock port $PORT; daemon baru batal."
      exit 0
    fi
  fi

  # Jika supervisor sebelumnya mati mendadak, proses Streamlit lama dapat tertinggal.
  # Bersihkan hanya server Streamlit Docking Riset; worker docking tidak cocok regex ini
  # dan sengaja dibiarkan hidup agar komputasi dapat dilanjutkan setelah UI pulih.
  cleanup_orphan_streamlit

  printf '%s\n' "$$" > "$SUP_PID_FILE"
  SERVER_PID=0
  SERVER_SESSION=0
  STOP_REQUESTED=0
  RESTART_COUNT=0

  cleanup_pidfile() {
    local cur
    cur=$(read_pid_file)
    if [ "$cur" = "$$" ]; then rm -f "$SUP_PID_FILE"; fi
  }

  stop_server() {
    local pid="${SERVER_PID:-0}"
    [ "$pid" -gt 1 ] 2>/dev/null || return 0
    if kill -0 "$pid" 2>/dev/null; then
      log "Menghentikan Streamlit PID $pid..."
      if [ "$SERVER_SESSION" -eq 1 ]; then
        kill -TERM -- "-$pid" 2>/dev/null || kill -TERM "$pid" 2>/dev/null || true
      else
        kill -TERM "$pid" 2>/dev/null || true
      fi
      for _ in $(seq 1 30); do
        kill -0 "$pid" 2>/dev/null || break
        sleep 0.1
      done
      if kill -0 "$pid" 2>/dev/null; then
        if [ "$SERVER_SESSION" -eq 1 ]; then
          kill -KILL -- "-$pid" 2>/dev/null || kill -KILL "$pid" 2>/dev/null || true
        else
          kill -KILL "$pid" 2>/dev/null || true
        fi
      fi
    fi
    wait "$pid" 2>/dev/null || true
    SERVER_PID=0
    SERVER_SESSION=0
  }

  shutdown_supervisor() {
    STOP_REQUESTED=1
    write_status "stopping" "${SERVER_PID:-0}" "$RESTART_COUNT"
    stop_server
    write_status "stopped" 0 "$RESTART_COUNT"
    cleanup_pidfile
    log "Supervisor daemon dihentikan melalui perintah resmi."
    exit 0
  }
  external_signal() {
    log "Sinyal $1 eksternal diterima supervisor dan diabaikan; server tetap dipertahankan. Gunakan 'docking-riset stop' untuk berhenti."
    write_status "healthy-protected" "${SERVER_PID:-0}" "$RESTART_COUNT"
  }
  trap 'external_signal TERM' TERM
  trap 'external_signal HUP' HUP
  trap shutdown_supervisor USR1 INT
  trap 'cleanup_pidfile' EXIT

  start_server() {
    rotate_log "$SERVER_LOG"
    log "Menjalankan Streamlit pada $URL (restart=$RESTART_COUNT, supervisor=$$)..."
    local cmd=(
      "$PY" -m streamlit run "$APP"
      --server.address 127.0.0.1
      --server.port "$PORT"
      --server.headless true
      --server.fileWatcherType none
      --server.runOnSave false
      --browser.gatherUsageStats false
    )
    if command -v setsid >/dev/null 2>&1; then
      setsid "${cmd[@]}" >>"$SERVER_LOG" 2>&1 < /dev/null &
      SERVER_SESSION=1
    else
      nohup "${cmd[@]}" >>"$SERVER_LOG" 2>&1 < /dev/null &
      SERVER_SESSION=0
    fi
    SERVER_PID=$!
    write_status "starting" "$SERVER_PID" "$RESTART_COUNT"
  }

  log "Supervisor v1.5.2-r3 aktif. PID=$$ SID=$(ps -o sid= -p $$ | tr -d ' ' 2>/dev/null || true)"

  while [ "$STOP_REQUESTED" -eq 0 ]; do
    if [ "$MAX_RESTARTS" -gt 0 ] 2>/dev/null && [ "$RESTART_COUNT" -gt "$MAX_RESTARTS" ]; then
      collect_crash_diagnostics
      write_status "failed" 0 "$RESTART_COUNT"
      log "ERROR: batas restart ($MAX_RESTARTS) terlampaui. Lihat $CRASH_DIAG"
      exit 1
    fi

    start_server
    ready=0
    for _ in $(seq 1 "$STARTUP_GRACE"); do
      if ! kill -0 "$SERVER_PID" 2>/dev/null; then break; fi
      if health_check; then ready=1; break; fi
      sleep 1
    done

    if [ "$ready" -eq 1 ]; then
      write_status "healthy" "$SERVER_PID" "$RESTART_COUNT"
      log "Streamlit sehat. PID=$SERVER_PID"
    elif kill -0 "$SERVER_PID" 2>/dev/null; then
      write_status "alive-health-pending" "$SERVER_PID" "$RESTART_COUNT"
      log "Streamlit masih hidup tetapi health belum merespons setelah ${STARTUP_GRACE}s; proses DIPERTAHANKAN."
    else
      log "Streamlit berhenti saat startup; akan direstart otomatis."
    fi

    failures=0
    healthy_cycles=0
    restart_reason=""
    while kill -0 "$SERVER_PID" 2>/dev/null; do
      sleep "$HEALTH_INTERVAL"
      if health_check; then
        failures=0
        healthy_cycles=$((healthy_cycles + 1))
        if [ "$healthy_cycles" -ge 60 ]; then
          RESTART_COUNT=0
          healthy_cycles=0
        fi
        write_status "healthy" "$SERVER_PID" "$RESTART_COUNT"
      else
        failures=$((failures + 1))
        write_status "unhealthy-alive" "$SERVER_PID" "$RESTART_COUNT"
        if [ "$failures" -eq 1 ] || [ $((failures % HEALTH_FAIL_LIMIT)) -eq 0 ]; then
          log "Health endpoint belum merespons ($failures kali), tetapi PID $SERVER_PID masih hidup; tidak dimatikan."
        fi
        if [ "$failures" -eq "$HEALTH_FAIL_LIMIT" ]; then collect_crash_diagnostics; fi
        if [ "$RESTART_ON_UNHEALTHY" = "1" ] && [ "$failures" -ge "$HEALTH_FAIL_LIMIT" ]; then
          restart_reason="HTTP/health tidak merespons ${failures} kali; Streamlit direstart tanpa menghentikan worker komputasi"
          break
        fi
      fi
    done

    if [ "$STOP_REQUESTED" -ne 0 ]; then break; fi
    if [ -z "$restart_reason" ]; then
      wait "$SERVER_PID" 2>/dev/null
      rc=$?
      restart_reason="proses Streamlit benar-benar berhenti (exit=$rc)"
    fi
    log "Server akan dipulihkan otomatis: $restart_reason"
    collect_crash_diagnostics
    stop_server
    RESTART_COUNT=$((RESTART_COUNT + 1))
    write_status "restarting" 0 "$RESTART_COUNT"
    delay=$((RESTART_COUNT < 10 ? RESTART_COUNT * 2 : 20)); [ "$delay" -lt 2 ] && delay=2; sleep "$delay"
  done
  shutdown_supervisor
}



cleanup_orphan_streamlit() {
  # Bersihkan hanya Streamlit milik Docking Riset di /opt/docking-riset.
  local pids p
  pids=$(pgrep -f 'python.*-m streamlit run /opt/docking-riset/(Docking_Riset_|docking_riset_app\.py)' 2>/dev/null || true)
  [ -n "$pids" ] || return 0
  echo "[Docking Riset] Membersihkan server Streamlit lama/orphan sebelum supervisor baru..."
  for p in $pids; do
    [ "$p" = "$$" ] && continue
    kill -TERM "$p" 2>/dev/null || true
  done
  sleep 2
  for p in $pids; do
    [ "$p" = "$$" ] && continue
    kill -0 "$p" 2>/dev/null && kill -KILL "$p" 2>/dev/null || true
  done
}

start_fallback_daemon() {
  local spid; spid=$(read_pid_file)
  if pid_alive "$spid"; then
    echo "[Docking Riset] Supervisor fallback aktif (PID=$spid)."
  else
    rm -f "$SUP_PID_FILE"
    echo "[Docking Riset] Menyalakan supervisor fallback terisolasi..."
    if command -v setsid >/dev/null 2>&1; then
      nohup setsid "$0" --supervisor >>"$SUP_LOG" 2>&1 < /dev/null &
    else
      nohup "$0" --supervisor >>"$SUP_LOG" 2>&1 < /dev/null &
    fi
    spid=$!; printf '%s\n' "$spid" > "$SUP_PID_FILE"
  fi
}

start_daemon() {
  ensure_dependencies || return 1
  choose_env
  local spid managed=0 running_version=""
  spid=$(read_pid_file)
  if pid_alive "$spid"; then managed=1; fi

  if systemd_user_available; then
    # Penting setelah upgrade DEB: proses systemd lama masih dapat menyimpan APP path
    # versi sebelumnya walau /usr/bin/docking-riset sudah diganti. Selalu reload unit,
    # lalu restart otomatis bila status runtime bukan versi paket saat ini.
    systemctl --user daemon-reload >/dev/null 2>&1 || true
    if systemctl --user is-active --quiet "$SYSTEMD_UNIT"; then
      managed=1
      running_version=$(runtime_launcher_version || true)
      if [ "$running_version" != "$APP_VERSION" ]; then
        echo "[Docking Riset] Supervisor lama terdeteksi (${running_version:-unknown} -> $APP_VERSION); restart otomatis..."
        systemctl --user restart "$SYSTEMD_UNIT" || true
        sleep 2
      fi
    fi
  fi

  # Setelah restart versi lama, evaluasi ulang health.
  if health_check && [ "$managed" -eq 1 ]; then
    running_version=$(runtime_launcher_version || true)
    if [ -z "$running_version" ] || [ "$running_version" = "$APP_VERSION" ]; then
      echo "[Docking Riset] Server sudah sehat dan berada di bawah supervisor v$APP_VERSION: $URL"
      open_url
      return 0
    fi
  elif health_check; then
    echo "[Docking Riset] Ditemukan Streamlit sehat tetapi tanpa supervisor aktif (orphan dari versi lama)."
    cleanup_orphan_streamlit
  fi

  if systemd_user_available; then
    echo "[Docking Riset] Menggunakan systemd user service (Restart=always)."
    systemctl --user daemon-reload >/dev/null 2>&1 || true
    if ! systemctl --user start "$SYSTEMD_UNIT"; then
      echo "[Docking Riset] systemd gagal; memakai daemon fallback."
      start_fallback_daemon
    fi
  else
    echo "[Docking Riset] systemd user tidak tersedia; memakai daemon fallback terisolasi."
    start_fallback_daemon
  fi

  for _ in $(seq 1 120); do
    if health_check; then
      echo "[Docking Riset] Streamlit sehat pada $URL"
      if systemd_user_available && systemctl --user is-active --quiet "$SYSTEMD_UNIT"; then
        echo "[Docking Riset] Supervisor dikelola systemd dan akan direstart otomatis bila mati."
      fi
      open_url
      return 0
    fi
    sleep 1
  done
  echo "[Docking Riset] Server belum sehat, tetapi supervisor tetap dipertahankan. Cek: docking-riset status" >&2
  return 1
}

stop_daemon() {
  if systemd_user_available; then
    # Penting sesudah upgrade DEB: muat KillMode=process sebelum STOP agar worker
    # komputasi yang sedang berjalan tidak ikut dibunuh oleh unit lama yang masih cache.
    systemctl --user daemon-reload >/dev/null 2>&1 || true
    if systemctl --user is-active --quiet "$SYSTEMD_UNIT"; then
      echo "[Docking Riset] Menghentikan systemd user service (worker komputasi dipertahankan)..."
      systemctl --user stop "$SYSTEMD_UNIT" || true
    fi
  fi
  local spid; spid=$(read_pid_file)
  if pid_alive "$spid"; then
    echo "[Docking Riset] Mengirim SIGUSR1 (stop resmi) ke supervisor PID $spid..."
    kill -USR1 "$spid" 2>/dev/null || true
    for _ in $(seq 1 100); do pid_alive "$spid" || break; sleep 0.1; done
  fi
  if pid_alive "$spid"; then
    echo "[Docking Riset] Supervisor belum berhenti; KILL terakhir." >&2
    kill -KILL "$spid" 2>/dev/null || true
  fi
  rm -f "$SUP_PID_FILE"
  cleanup_orphan_streamlit
  echo "[Docking Riset] Server dihentikan."
}

status_daemon() {
  local spid; spid=$(read_pid_file)
  echo "Docking Riset $APP_VERSION"
  echo "URL        : $URL"
  echo "App path   : $APP"
  echo "Environment: $VENV"
  echo "Runtime ver: $(runtime_launcher_version || true)"
  if systemd_user_available; then
    if systemctl --user is-active --quiet "$SYSTEMD_UNIT"; then echo "systemd    : ACTIVE (Restart=always)"; else echo "systemd    : tersedia, service tidak aktif"; fi
  else
    echo "systemd    : user service tidak tersedia"
  fi
  if pid_alive "$spid"; then echo "Supervisor : aktif (PID=$spid)"; else echo "Supervisor : tidak aktif"; fi
  if health_check; then echo "Streamlit  : HEALTHY"; else echo "Streamlit  : health endpoint belum merespons"; fi
  [ -f "$STATUS_FILE" ] && { echo; cat "$STATUS_FILE"; echo; }
}

diagnose() {
  choose_env
  collect_crash_diagnostics
  echo "Diagnostik: $CRASH_DIAG"
  echo
  tail -120 "$CRASH_DIAG" 2>/dev/null || true
  if systemd_user_available; then
    echo; echo "== systemd journal terakhir =="
    journalctl --user -u "$SYSTEMD_UNIT" -n 80 --no-pager 2>/dev/null || true
  fi
}

follow_console() {
  touch "$SERVER_LOG" "$SUP_LOG"
  echo
  echo "[Docking Riset] Server berjalan sebagai daemon terpisah."
  echo "[Docking Riset] Terminal ini hanya menampilkan log; Ctrl+C/menutup terminal TIDAK menghentikan server."
  echo "[Docking Riset] Untuk benar-benar berhenti: docking-riset stop"
  echo
  tail -n 30 -F "$SERVER_LOG"
}

RAW_ACTION="${1:-}"
ACTION="${RAW_ACTION:-start-follow}"
case "$ACTION" in
  --supervisor)
    supervisor_main
    ;;
  start)
    start_daemon
    ;;
  start-follow)
    start_daemon && follow_console
    ;;
  follow)
    follow_console
    ;;
  stop)
    stop_daemon
    ;;
  restart)
    stop_daemon
    sleep 1
    start_daemon
    ;;
  status)
    status_daemon
    ;;
  diagnose)
    diagnose
    ;;
  logs)
    tail -f "$SUP_LOG"
    ;;
  server-logs)
    tail -f "$SERVER_LOG"
    ;;
  *)
    echo "Penggunaan: docking-riset [start|follow|stop|restart|status|diagnose|logs|server-logs]" >&2
    exit 2
    ;;
esac
