#!/bin/bash
# WarpSend DSM 7 start-stop-status script.

set -euo pipefail

PACKAGE_DIR="${WARPSEND_SPK_PACKAGE_DIR:-/var/packages/WarpSend/target}"
CLI_BINARY="${PACKAGE_DIR}/bin/warpsend"
CONFIG_DIR="${WARPSEND_SPK_HOME_DIR:-${WARPSEND_SPK_CONFIG_DIR:-/var/packages/WarpSend/home}}"
PID_FILE="${CONFIG_DIR}/warpsend.pid"
LOCK_FILE="${CONFIG_DIR}/supervisor.lock"
LOG_FILE="${CONFIG_DIR}/warpsend.log"
RESPAWN_DELAY_SECS="${WARPSEND_SPK_RESPAWN_DELAY_SECS:-10}"

is_alive() {
  local pid="${1:-}"
  [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null
}

supervisor_pid() {
  [ -s "$LOCK_FILE" ] || return 1
  local pid
  pid="$(cat "$LOCK_FILE" 2>/dev/null || true)"
  is_alive "$pid" || return 1
  printf '%s\n' "$pid"
}

pid_file_pid() {
  [ -s "$PID_FILE" ] || return 1
  local pid
  pid="$(cat "$PID_FILE" 2>/dev/null || true)"
  is_alive "$pid" || return 1
  printf '%s\n' "$pid"
}

sync_pid_file() {
  local pid="$1"
  printf '%s\n' "$pid" > "$PID_FILE"
}

stop_pid() {
  local pid="${1:-}"
  [ -n "$pid" ] || return 0
  is_alive "$pid" || return 0
  kill "$pid" 2>/dev/null || true
  for _ in $(seq 1 30); do
    is_alive "$pid" || return 0
    sleep 1
  done
  is_alive "$pid" && kill -9 "$pid" 2>/dev/null || true
}

case "${1:-}" in
  start)
    mkdir -p "$CONFIG_DIR"
    export HOME="$CONFIG_DIR"

    if pid="$(pid_file_pid)"; then
      # Startup may still be acquiring the supervisor lock. Preserve the
      # current live PID instead of spawning a duplicate and clobbering state.
      sync_pid_file "$pid"
      exit 0
    fi

    if pid="$(supervisor_pid)"; then
      sync_pid_file "$pid"
      exit 0
    fi

    rm -f "$PID_FILE"

    (
      while :; do
        set +e
        WARPSEND_CONFIG_DIR="$CONFIG_DIR" \
        WARPSEND_AGENT_VARIANT=nas \
        WARPSEND_WEB_PORT=9090 \
        WARPSEND_LOG_FILE="$LOG_FILE" \
        WARPSEND_SIBLING_AGENT_REFRESH_MARKER="$CONFIG_DIR/.config/warpsend/refresh-from-package" \
          "$CLI_BINARY" service run \
          >> "$LOG_FILE" 2>&1
        rc="$?"
        set -e
        [ "$rc" -eq 0 ] && exit 0
        printf '[start-stop-status] supervisor exited rc=%s; respawning in %ss\n' "$rc" "$RESPAWN_DELAY_SECS" >> "$LOG_FILE"
        sleep "$RESPAWN_DELAY_SECS"
      done
    ) &

    child="$!"
    sync_pid_file "$child"

    # Wait briefly for the supervisor to acquire its canonical lock. If it
    # exits during startup, report failure instead of writing a dead PID.
    for _ in $(seq 1 20); do
      if pid="$(supervisor_pid)"; then
        sync_pid_file "$child"
        exit 0
      fi
      if ! is_alive "$child"; then
        rc=0
        wait "$child" || rc="$?"
        rm -f "$PID_FILE"
        exit "$rc"
      fi
      sleep 0.2
    done

    if is_alive "$child"; then
      sync_pid_file "$child"
      exit 0
    fi
    rc=0
    wait "$child" || rc="$?"
    rm -f "$PID_FILE"
    exit "$rc"
    ;;

  stop)
    # Stop the respawn loop first so killing the current supervisor does not
    # immediately launch a replacement.
    if pid="$(pid_file_pid)"; then
      stop_pid "$pid"
    fi
    if pid="$(supervisor_pid)"; then
      stop_pid "$pid"
    fi

    rm -f "$PID_FILE"
    if [ -s "$LOCK_FILE" ]; then
      lock_pid="$(cat "$LOCK_FILE" 2>/dev/null || true)"
      is_alive "$lock_pid" || rm -f "$LOCK_FILE"
    fi
    ;;

  status)
    if pid="$(pid_file_pid)"; then
      exit 0
    fi
    if pid="$(supervisor_pid)"; then
      sync_pid_file "$pid"
      exit 0
    fi
    [ -f "$PID_FILE" ] && exit 1
    exit 3
    ;;

  log)
    echo "$LOG_FILE"
    ;;
esac

exit 0
