#!/usr/bin/env bash
# Thin wrapper around `systemctl` / `journalctl` for the per-company
# FileShare storage server. Usable by the `fileshare` system user (via
# a NOPASSWD sudoers drop-in installed alongside this script), by root,
# or by any sudo-capable admin.
set -euo pipefail

UNIT="fileshare-company-server"
SYSTEMCTL="/usr/bin/systemctl"
JOURNALCTL="/usr/bin/journalctl"

INSTALL_DIR=/opt/fileshare_company_server
DATA_DIR=/var/lib/fileshare-company-server
CONFIG_DIR=/etc/fileshare-company-server
UNIT_FILE=/etc/systemd/system/${UNIT}.service
SUDOERS_FILE=/etc/sudoers.d/${UNIT}
WRAPPER_PATH=/usr/local/bin/fileshareSRV
SERVICE_USER=fileshare
SERVICE_GROUP=fileshare

usage() {
  cat <<USAGE
Usage: fileshareSRV {start|stop|restart|status|logs|code|enable|disable|uninstall}

  start      Start the server now
  stop       Stop the server
  restart    Stop and start again
  status     Show current service status
  logs       Tail server logs (Ctrl-C to exit)
  code       Print the enrollment code (only once the server is ready to pair)
  enable     Start automatically on boot
  disable    Do not start automatically on boot
  uninstall  Remove fileshare-company-server from this machine
             (add --purge to also wipe customer data)
USAGE
}

# Pull the enrollment code (and validity line) out of the journal for the
# current service invocation. The interesting log lines are:
#
#   Listening on http://...          → server is paired and running
#   Switching to normal mode         → same; we already have credentials
#   Opening claim WS: ...            → claim WS is connected to central,
#                                      the printed code is hot
#   wiping local credentials         → central disowned us; we'll re-claim
#   ENROLLMENT CODE: XXXX-YYYY       → the code itself
#   Code valid for N minutes.        → printed alongside the code
#
# We only show the code once "Opening claim WS" is the latest state line —
# if we show it earlier, central hasn't seen the server present the code
# yet and pairing from the app fails with "code not found".
cmd_code() {
  if ! "$SYSTEMCTL" is-active --quiet "$UNIT"; then
    echo "fileshare-company-server is not running. Start it with:" >&2
    echo "  fileshareSRV start" >&2
    exit 1
  fi

  # Bound the journal scan to the current service invocation so we don't
  # surface a stale code from a previous boot.
  local active_since
  active_since=$("$SYSTEMCTL" show -p ActiveEnterTimestamp --value "$UNIT" 2>/dev/null || true)
  local since_args=()
  if [ -n "${active_since:-}" ] \
     && [ "$active_since" != "n/a" ] \
     && [ "$active_since" != "0" ]; then
    since_args=(--since="$active_since")
  fi

  local deadline=$(( $(date +%s) + 15 ))
  while : ; do
    local log
    log=$(sudo -n "$JOURNALCTL" -u "$UNIT" "${since_args[@]}" --no-pager -o cat 2>/dev/null || true)

    local state
    state=$(printf '%s\n' "$log" \
            | grep -E "Opening claim WS|Listening on http" \
            | tail -1 || true)

    case "$state" in
      *"Listening on http"*)
        echo "Server is already paired with the FileShare app — no enrollment code is active." >&2
        echo "To re-pair, disconnect this server in the app first, then run:" >&2
        echo "  fileshareSRV code" >&2
        exit 1
        ;;
      *"Opening claim WS"*)
        printf '%s\n' "$log" \
          | grep -E "ENROLLMENT CODE|Code valid" \
          | tail -4
        exit 0
        ;;
    esac

    if [ "$(date +%s)" -ge "$deadline" ]; then
      echo "Server is starting but isn't ready to accept pairing yet." >&2
      echo "Wait a few seconds and retry, or inspect:" >&2
      echo "  fileshareSRV logs" >&2
      exit 1
    fi
    sleep 1
  done
}

cmd_uninstall() {
  shift || true
  local purge=0
  local a
  for a in "$@"; do
    case "$a" in
      --purge) purge=1 ;;
      *) echo "Unknown flag: $a" >&2; exit 64 ;;
    esac
  done

  if [ "$(id -u)" -ne 0 ]; then
    echo "fileshareSRV uninstall must be run as root, e.g.:" >&2
    echo "  sudo fileshareSRV uninstall" >&2
    exit 1
  fi

  echo "This will stop and remove fileshare-company-server from this machine."
  if [ "$purge" -eq 1 ]; then
    echo "Customer data in ${DATA_DIR} and config in ${CONFIG_DIR}"
    echo "will be DELETED, and the '${SERVICE_USER}' system user removed."
  else
    echo "Customer data in ${DATA_DIR} and config in ${CONFIG_DIR}"
    echo "will be PRESERVED. (Pass --purge to also wipe them.)"
  fi
  echo ""

  local answer=""
  printf "Are you sure? [yes/no] "
  read -r answer || answer=""
  case "${answer}" in
    y|Y|yes|YES|Yes) ;;
    *) echo "Aborted."; exit 0 ;;
  esac

  # If installed via dpkg/apt, route through the package manager so its
  # database stays consistent — otherwise apt will still think the
  # package is installed and refuse later upgrades.
  if command -v dpkg-query >/dev/null 2>&1 \
     && dpkg-query -W -f='${Status}' fileshare-company-server 2>/dev/null \
        | grep -q "install ok installed"; then
    if [ "$purge" -eq 1 ]; then
      apt-get -y purge fileshare-company-server
    else
      apt-get -y remove fileshare-company-server
    fi
    echo "Removed."
    exit 0
  fi

  # Manual install layout — mirrors the self-extracting installer's
  # do_uninstall so the two paths stay in sync.
  echo "Stopping service..."
  "$SYSTEMCTL" stop    "${UNIT}.service" >/dev/null 2>&1 || true
  "$SYSTEMCTL" disable "${UNIT}.service" >/dev/null 2>&1 || true

  rm -f "$UNIT_FILE" "$SUDOERS_FILE"
  rm -rf "$INSTALL_DIR"

  if [ "$purge" -eq 1 ]; then
    rm -rf "$DATA_DIR" "$CONFIG_DIR"
    if getent passwd "$SERVICE_USER" >/dev/null; then
      userdel "$SERVICE_USER" >/dev/null 2>&1 || true
    fi
    if getent group "$SERVICE_GROUP" >/dev/null; then
      groupdel "$SERVICE_GROUP" >/dev/null 2>&1 || true
    fi
  fi

  if [ -d /run/systemd/system ]; then
    "$SYSTEMCTL" daemon-reload >/dev/null 2>&1 || true
  fi

  # Removing the wrapper while it's executing is safe on Linux: bash has
  # already loaded the file, and unlink doesn't truncate the inode until
  # the last fd closes.
  rm -f "$WRAPPER_PATH"

  echo "Removed."
  if [ "$purge" -ne 1 ]; then
    echo "Customer data left in ${DATA_DIR} (re-run 'uninstall --purge' to wipe)."
  fi
}

cmd="${1:-status}"
case "$cmd" in
  start|stop|restart|reload|enable|disable)
    exec sudo -n "$SYSTEMCTL" "$cmd" "$UNIT"
    ;;
  status)
    exec "$SYSTEMCTL" status "$UNIT" --no-pager
    ;;
  logs)
    exec sudo -n "$JOURNALCTL" -u "$UNIT" -f
    ;;
  code)
    cmd_code
    ;;
  uninstall)
    cmd_uninstall "$@"
    ;;
  -h|--help|help)
    usage
    ;;
  *)
    usage >&2
    exit 64
    ;;
esac
