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

REMOTE_HOST="${REMOTE_HOST:-${VPS_HOST:-}}"
REMOTE_USER="${REMOTE_USER:-${VPS_USER:-}}"
if [ -z "$REMOTE_HOST" ]; then
  echo "Set REMOTE_HOST to the SSH host or IP address, for example a local NAS hostname." >&2
  exit 2
fi
if [ -z "$REMOTE_USER" ]; then
  echo "Set REMOTE_USER to the non-root sudo SSH user." >&2
  exit 2
fi
APP_USER="${APP_USER:-mailcat}"
SERVICE_NAME="${SERVICE_NAME:-mailcat-sort-backup}"
ACCOUNT="${ACCOUNT:-backup}"
DAILY_REPORT_TO="${DAILY_REPORT_TO:-hans@australius.nl}"
WEB_HOST="${WEB_HOST:-0.0.0.0}"
WEB_PORT="${WEB_PORT:-4321}"
REMOTE_PATH="${REMOTE_PATH:-/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin}"
SERVICE_MANAGER="${SERVICE_MANAGER:-systemd}"
MAILCAT_HOME="${MAILCAT_HOME:-/share/homes/$APP_USER}"
SUDO="${SUDO:-/usr/bin/sudo}"
USERADD="${USERADD:-/usr/local/bin/useradd}"
INSTALL="${INSTALL:-/usr/bin/install}"
SED="${SED:-/bin/sed}"
TAR="${TAR:-/bin/tar}"
MKDIR="${MKDIR:-/bin/mkdir}"
CHOWN="${CHOWN:-/bin/chown}"
CHMOD="${CHMOD:-/bin/chmod}"
RM="${RM:-/bin/rm}"
SYSTEMCTL="${SYSTEMCTL:-/bin/systemctl}"
if [ -z "${APP_DIR:-}" ]; then
  if [ "$SERVICE_MANAGER" = "plain" ]; then
    APP_DIR="$MAILCAT_HOME/mailcat"
  else
    APP_DIR="/opt/mailcat"
  fi
fi
if [ "$SERVICE_MANAGER" = "plain" ]; then
  STATE_DIR="${STATE_DIR:-$APP_DIR/state}"
  LOG_DIR="${LOG_DIR:-$APP_DIR/log}"
  RUN_DIR="${RUN_DIR:-$APP_DIR/run}"
  PID_FILE="${PID_FILE:-$RUN_DIR/mailcat.pid}"
  WEB_PID_FILE="${WEB_PID_FILE:-$RUN_DIR/mailcat_web.pid}"
  WEB_CONFIG="${WEB_CONFIG:-$APP_DIR/web_config.json}"
  PYTHON="${PYTHON:-/opt/bin/python3}"
else
  STATE_DIR="${STATE_DIR:-/var/lib/mailcat}"
  LOG_DIR="${LOG_DIR:-/var/log/mailcat}"
  RUN_DIR="${RUN_DIR:-/run/mailcat}"
  PID_FILE="${PID_FILE:-$RUN_DIR/mailcat.pid}"
  WEB_PID_FILE="${WEB_PID_FILE:-$RUN_DIR/mailcat_web.pid}"
  WEB_CONFIG="${WEB_CONFIG:-$APP_DIR/web_config.json}"
  PYTHON="${PYTHON:-/usr/bin/python3}"
fi

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ARCHIVE="$(mktemp -t mailcat-deploy.XXXXXX.tar.gz)"
REMOTE_SCRIPT="$(mktemp -t mailcat-remote-deploy.XXXXXX.sh)"

cleanup() {
  rm -f "$ARCHIVE"
  rm -f "$REMOTE_SCRIPT"
}
trap cleanup EXIT

tar \
  --exclude ".git" \
  --exclude "__pycache__" \
  --exclude "mailbox" \
  --exclude "config.json" \
  --exclude "web_config.json" \
  --exclude "*.log" \
  --exclude "backup_log.json" \
  --exclude "verplaats_log*.json" \
  --exclude "sort_mail_daemon_state.json" \
  --exclude "mailing_lists_cache*.json" \
  --exclude "*.pyc" \
  -C "$ROOT_DIR" \
  -czf "$ARCHIVE" .

cat > "$REMOTE_SCRIPT" <<'REMOTE'
set -eu

export PATH="$REMOTE_PATH:$PATH"
"$SUDO" -v

find_command() {
  name="$1"
  shift
  if command -v "$name" >/dev/null 2>&1; then
    command -v "$name"
    return 0
  fi
  for candidate in "$@"; do
    if [ -x "$candidate" ]; then
      printf '%s\n' "$candidate"
      return 0
    fi
  done
  return 1
}

if ! id "$APP_USER" >/dev/null 2>&1; then
  if [ -x "$USERADD" ] || USERADD="$(find_command useradd /usr/local/bin/useradd /usr/local/sbin/useradd /usr/sbin/useradd /sbin/useradd)"; then
    NOLOGIN="$(find_command nologin /usr/local/bin/nologin /usr/local/sbin/nologin /usr/sbin/nologin /sbin/nologin || true)"
    if [ -n "$NOLOGIN" ]; then
      "$SUDO" "$USERADD" -d "$MAILCAT_HOME" -s "$NOLOGIN" "$APP_USER"
    else
      "$SUDO" "$USERADD" -d "$MAILCAT_HOME" "$APP_USER"
    fi
  else
    APP_USER="$(id -un)"
    echo "useradd not found on remote host; using existing SSH user '$APP_USER' for the service." >&2
  fi
fi
APP_GROUP="$(id -gn "$APP_USER")"

"$SUDO" "$MKDIR" -p "$APP_DIR" "$STATE_DIR" "$LOG_DIR" "$RUN_DIR" "$APP_DIR/bin"
"$SUDO" "$TAR" -xzf /tmp/mailcat-deploy.tar.gz -C "$APP_DIR"
"$SUDO" "$CHOWN" -R "$APP_USER:$APP_GROUP" "$MAILCAT_HOME" "$APP_DIR" "$STATE_DIR" "$LOG_DIR" "$RUN_DIR"
"$SUDO" "$CHMOD" 750 "$APP_DIR"

if [ ! -f "$APP_DIR/config.json" ]; then
  echo "Missing $APP_DIR/config.json on remote host. Create it with mode 600 before starting the service." >&2
fi
"$SUDO" "$CHMOD" 600 "$APP_DIR/web_config.json" 2>/dev/null || true
"$SUDO" "$CHOWN" "$APP_USER:$APP_GROUP" "$APP_DIR/web_config.json" 2>/dev/null || true
if [ ! -f "$APP_DIR/web_config.json" ]; then
  echo "Missing $APP_DIR/web_config.json on remote host. Create it with mode 600 before starting the web UI." >&2
fi
"$SUDO" "$CHMOD" 600 "$APP_DIR/config.json" 2>/dev/null || true
"$SUDO" "$CHOWN" "$APP_USER:$APP_GROUP" "$APP_DIR/config.json" 2>/dev/null || true

if [ "$SERVICE_MANAGER" = "plain" ]; then
  cat > /tmp/mailcat-start.sh <<START_SCRIPT
#!/bin/sh
set -eu
APP_DIR="$APP_DIR"
ACCOUNT="$ACCOUNT"
PYTHON="$PYTHON"
STATE_DIR="$STATE_DIR"
LOG_DIR="$LOG_DIR"
RUN_DIR="$RUN_DIR"
PID_FILE="$PID_FILE"
MKDIR="$MKDIR"

"\$MKDIR" -p "\$STATE_DIR" "\$LOG_DIR" "\$RUN_DIR"
if [ -f "\$PID_FILE" ]; then
  old_pid=""
  IFS= read -r old_pid < "\$PID_FILE" || true
  if [ -n "\$old_pid" ] && kill -0 "\$old_pid" 2>/dev/null; then
    echo "mailcat already running: \$old_pid"
    exit 0
  fi
fi

cd "\$APP_DIR"
"\$PYTHON" "\$APP_DIR/sort_mail_daemon.py" --account "\$ACCOUNT" --folder INBOX --state-file "\$STATE_DIR/sort_mail_daemon_state.json" --log-file "\$LOG_DIR/sort_mail_daemon.log" >> "\$LOG_DIR/daemon.out" 2>&1 &
pid="\$!"
echo "\$pid" > "\$PID_FILE"
echo "mailcat started: \$pid"
START_SCRIPT

  cat > /tmp/mailcat-stop.sh <<STOP_SCRIPT
#!/bin/sh
set -eu
PID_FILE="$PID_FILE"
RM="$RM"

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

pid=""
IFS= read -r pid < "\$PID_FILE" || true
if [ -z "\$pid" ]; then
  "\$RM" -f "\$PID_FILE"
  echo "mailcat not running: empty pid file removed"
  exit 0
fi

if kill -0 "\$pid" 2>/dev/null; then
  kill "\$pid"
  timeout=20
  while [ "\$timeout" -gt 0 ] && kill -0 "\$pid" 2>/dev/null; do
    sleep 1
    timeout=\$((timeout - 1))
  done
  if kill -0 "\$pid" 2>/dev/null; then
    echo "mailcat still running after SIGTERM, sending SIGKILL: \$pid"
    kill -KILL "\$pid" 2>/dev/null || true
    timeout=5
    while [ "\$timeout" -gt 0 ] && kill -0 "\$pid" 2>/dev/null; do
      sleep 1
      timeout=\$((timeout - 1))
    done
    if kill -0 "\$pid" 2>/dev/null; then
      echo "mailcat still running after SIGKILL: \$pid"
      exit 1
    fi
  fi
fi
"\$RM" -f "\$PID_FILE"
echo "mailcat stopped"
STOP_SCRIPT

  cat > /tmp/mailcat-status.sh <<STATUS_SCRIPT
#!/bin/sh
set -eu
PID_FILE="$PID_FILE"
LOG_DIR="$LOG_DIR"

if [ -f "\$PID_FILE" ]; then
  pid=""
  IFS= read -r pid < "\$PID_FILE" || true
  if [ -n "\$pid" ] && kill -0 "\$pid" 2>/dev/null; then
    echo "mailcat running: \$pid"
    exit 0
  fi
  echo "mailcat not running: stale pid file (\$pid)"
  exit 1
fi
echo "mailcat not running"
echo "logs: \$LOG_DIR"
exit 1
STATUS_SCRIPT

  cat > /tmp/mailcat-daily-report.sh <<REPORT_SCRIPT
#!/bin/sh
set -eu
APP_DIR="$APP_DIR"
ACCOUNT="$ACCOUNT"
PYTHON="$PYTHON"
LOG_DIR="$LOG_DIR"
MAIL_TO="$DAILY_REPORT_TO"
MKDIR="$MKDIR"

"\$MKDIR" -p "\$LOG_DIR"
cd "\$APP_DIR"
"\$PYTHON" "\$APP_DIR/dagelijks_overzicht.py" --account "\$ACCOUNT" --mail-to "\$MAIL_TO" >> "\$LOG_DIR/daily_report.out" 2>&1
REPORT_SCRIPT

  cat > /tmp/mailcat-web-start.sh <<WEB_START_SCRIPT
#!/bin/sh
set -eu
APP_DIR="$APP_DIR"
PYTHON="$PYTHON"
LOG_DIR="$LOG_DIR"
RUN_DIR="$RUN_DIR"
WEB_PID_FILE="$WEB_PID_FILE"
WEB_HOST="$WEB_HOST"
WEB_PORT="$WEB_PORT"
WEB_CONFIG="$WEB_CONFIG"
MKDIR="$MKDIR"

if [ ! -f "\$WEB_CONFIG" ]; then
  echo "missing web config: \$WEB_CONFIG"
  exit 1
fi

"\$MKDIR" -p "\$LOG_DIR" "\$RUN_DIR"
if [ -f "\$WEB_PID_FILE" ]; then
  old_pid=""
  IFS= read -r old_pid < "\$WEB_PID_FILE" || true
  if [ -n "\$old_pid" ] && kill -0 "\$old_pid" 2>/dev/null; then
    echo "mailcat web already running: \$old_pid"
    exit 0
  fi
fi

cd "\$APP_DIR"
"\$PYTHON" "\$APP_DIR/manage_routes_web.py" --host "\$WEB_HOST" --port "\$WEB_PORT" --config "\$WEB_CONFIG" >> "\$LOG_DIR/web.out" 2>&1 &
pid="\$!"
echo "\$pid" > "\$WEB_PID_FILE"
echo "mailcat web started: \$pid"
WEB_START_SCRIPT

  cat > /tmp/mailcat-web-stop.sh <<WEB_STOP_SCRIPT
#!/bin/sh
set -eu
WEB_PID_FILE="$WEB_PID_FILE"
RM="$RM"

if [ ! -f "\$WEB_PID_FILE" ]; then
  echo "mailcat web not running: no pid file"
  exit 0
fi

pid=""
IFS= read -r pid < "\$WEB_PID_FILE" || true
if [ -z "\$pid" ]; then
  "\$RM" -f "\$WEB_PID_FILE"
  echo "mailcat web not running: empty pid file removed"
  exit 0
fi

if kill -0 "\$pid" 2>/dev/null; then
  kill "\$pid"
  timeout=20
  while [ "\$timeout" -gt 0 ] && kill -0 "\$pid" 2>/dev/null; do
    sleep 1
    timeout=\$((timeout - 1))
  done
  if kill -0 "\$pid" 2>/dev/null; then
    echo "mailcat web still running after SIGTERM, sending SIGKILL: \$pid"
    kill -KILL "\$pid" 2>/dev/null || true
    timeout=5
    while [ "\$timeout" -gt 0 ] && kill -0 "\$pid" 2>/dev/null; do
      sleep 1
      timeout=\$((timeout - 1))
    done
    if kill -0 "\$pid" 2>/dev/null; then
      echo "mailcat web still running after SIGKILL: \$pid"
      exit 1
    fi
  fi
fi
"\$RM" -f "\$WEB_PID_FILE"
echo "mailcat web stopped"
WEB_STOP_SCRIPT

  cat > /tmp/mailcat-web-status.sh <<WEB_STATUS_SCRIPT
#!/bin/sh
set -eu
WEB_PID_FILE="$WEB_PID_FILE"
WEB_HOST="$WEB_HOST"
WEB_PORT="$WEB_PORT"
LOG_DIR="$LOG_DIR"

if [ -f "\$WEB_PID_FILE" ]; then
  pid=""
  IFS= read -r pid < "\$WEB_PID_FILE" || true
  if [ -n "\$pid" ] && kill -0 "\$pid" 2>/dev/null; then
    echo "mailcat web running: \$pid"
    echo "url: http://\$WEB_HOST:\$WEB_PORT/"
    exit 0
  fi
  echo "mailcat web not running: stale pid file (\$pid)"
  exit 1
fi
echo "mailcat web not running"
echo "logs: \$LOG_DIR/web.out"
exit 1
WEB_STATUS_SCRIPT

  "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-start.sh "$APP_DIR/bin/start_mailcat.sh"
  "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-stop.sh "$APP_DIR/bin/stop_mailcat.sh"
  "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-status.sh "$APP_DIR/bin/status_mailcat.sh"
  "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-daily-report.sh "$APP_DIR/bin/run_daily_report.sh"
  "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-web-start.sh "$APP_DIR/bin/start_web.sh"
  "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-web-stop.sh "$APP_DIR/bin/stop_web.sh"
  "$SUDO" "$INSTALL" -m 0755 /tmp/mailcat-web-status.sh "$APP_DIR/bin/status_web.sh"
  "$SUDO" "$CHOWN" "$APP_USER:$APP_GROUP" "$APP_DIR/bin/start_mailcat.sh" "$APP_DIR/bin/stop_mailcat.sh" "$APP_DIR/bin/status_mailcat.sh" "$APP_DIR/bin/run_daily_report.sh" "$APP_DIR/bin/start_web.sh" "$APP_DIR/bin/stop_web.sh" "$APP_DIR/bin/status_web.sh"
  "$RM" -f /tmp/mailcat-start.sh /tmp/mailcat-stop.sh /tmp/mailcat-status.sh /tmp/mailcat-daily-report.sh /tmp/mailcat-web-start.sh /tmp/mailcat-web-stop.sh /tmp/mailcat-web-status.sh
else
  "$SUDO" "$INSTALL" -m 0644 "$APP_DIR/systemd/mailcat-sort.service" "/etc/systemd/system/$SERVICE_NAME.service"
  "$SUDO" "$SED" -i \
    -e "s#__APP_USER__#$APP_USER#g" \
    -e "s#__APP_GROUP__#$APP_GROUP#g" \
    -e "s#__APP_DIR__#$APP_DIR#g" \
    -e "s#__ACCOUNT__#$ACCOUNT#g" \
    -e "s#__PYTHON__#$PYTHON#g" \
    -e "s#__STATE_DIR__#$STATE_DIR#g" \
    -e "s#__LOG_DIR__#$LOG_DIR#g" \
    "/etc/systemd/system/$SERVICE_NAME.service"

  "$SUDO" "$SYSTEMCTL" daemon-reload
  "$SUDO" "$SYSTEMCTL" enable "$SERVICE_NAME.service"
fi
"$RM" -f /tmp/mailcat-deploy.tar.gz /tmp/mailcat-remote-deploy.sh

echo "Deployment complete."
echo "Create/check $APP_DIR/config.json, then run:"
if [ "$SERVICE_MANAGER" = "plain" ]; then
  echo "  sudo -u $APP_USER $APP_DIR/bin/start_mailcat.sh"
  echo "  sudo -u $APP_USER $APP_DIR/bin/status_mailcat.sh"
  echo "  sudo -u $APP_USER $APP_DIR/bin/run_daily_report.sh"
  echo "  sudo -u $APP_USER $APP_DIR/bin/start_web.sh"
  echo "  sudo -u $APP_USER $APP_DIR/bin/status_web.sh"
  echo "  tail -f $LOG_DIR/sort_mail_daemon.log"
else
  echo "  sudo systemctl start $SERVICE_NAME.service"
  echo "  sudo journalctl -u $SERVICE_NAME.service -f"
fi
REMOTE

scp "$ARCHIVE" "$REMOTE_USER@$REMOTE_HOST:/tmp/mailcat-deploy.tar.gz"
scp "$REMOTE_SCRIPT" "$REMOTE_USER@$REMOTE_HOST:/tmp/mailcat-remote-deploy.sh"

REMOTE_COMMAND=$(printf "APP_USER=%q APP_DIR=%q SERVICE_NAME=%q ACCOUNT=%q DAILY_REPORT_TO=%q WEB_HOST=%q WEB_PORT=%q REMOTE_PATH=%q SERVICE_MANAGER=%q MAILCAT_HOME=%q STATE_DIR=%q LOG_DIR=%q RUN_DIR=%q PID_FILE=%q WEB_PID_FILE=%q WEB_CONFIG=%q PYTHON=%q SUDO=%q USERADD=%q INSTALL=%q SED=%q TAR=%q MKDIR=%q CHOWN=%q CHMOD=%q RM=%q SYSTEMCTL=%q /bin/sh /tmp/mailcat-remote-deploy.sh" "$APP_USER" "$APP_DIR" "$SERVICE_NAME" "$ACCOUNT" "$DAILY_REPORT_TO" "$WEB_HOST" "$WEB_PORT" "$REMOTE_PATH" "$SERVICE_MANAGER" "$MAILCAT_HOME" "$STATE_DIR" "$LOG_DIR" "$RUN_DIR" "$PID_FILE" "$WEB_PID_FILE" "$WEB_CONFIG" "$PYTHON" "$SUDO" "$USERADD" "$INSTALL" "$SED" "$TAR" "$MKDIR" "$CHOWN" "$CHMOD" "$RM" "$SYSTEMCTL")
ssh -tt "$REMOTE_USER@$REMOTE_HOST" "$REMOTE_COMMAND"
