#!/usr/bin/env bash
# =============================================================================
# onx-user-suspend — Suspend a hosting account
#
# Purpose:
#   Locks Linux password, sets shell to /sbin/nologin, disables Apache vhosts
#   by moving config files to suspended/, and records the suspension reason.
#
# Input (stdin JSON):
#   {
#     "username": "onx_xxxx",       -- required
#     "reason": "non-payment"       -- required; stored to suspension.json
#   }
#
# Output (stdout JSON):
#   {"username":..., "status":"suspended", "suspended_at":"<ISO8601>", "reason":...}
#
# Exit codes: 0=ok 1=invalid-input 2=preflight-fail 3=exec-fail 4=rolled-back 5=rollback-failed
#
# Sudoers entry needed:
#   apache ALL=(root) NOPASSWD: /usr/local/onoxsoft/bin/onx-user-suspend
#   Defaults!/usr/local/onoxsoft/bin/onx-user-suspend !requiretty
#   Defaults!/usr/local/onoxsoft/bin/onx-user-suspend log_output, log_input
#
# Deployed to: /usr/local/onoxsoft/bin/onx-user-suspend
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"

# ── Constants ─────────────────────────────────────────────────────────────────
VHOST_ACTIVE_DIR="/etc/httpd/conf.d/sites"
VHOST_SUSPENDED_DIR="/etc/httpd/suspended"
META_DIR=".onox"

# ── Dependencies ──────────────────────────────────────────────────────────────
command -v jq      >/dev/null 2>&1 || { printf '{"error":"jq required"}\n' >&2; exit 2; }
command -v usermod >/dev/null 2>&1 || { printf '{"error":"usermod required"}\n' >&2; exit 2; }
require_root

# ── Read & parse stdin ────────────────────────────────────────────────────────
INPUT=$(cat)
onx_require_json "${INPUT}"

USERNAME=$(onx_json_get "${INPUT}" "username")
REASON=$(onx_json_get   "${INPUT}" "reason" "suspended by administrator")

# ── Input validation ──────────────────────────────────────────────────────────
onx_validate_username "${USERNAME}"
[[ -z "${REASON}" ]] && onx_die 1 "reason is required"

# ── Preflight ─────────────────────────────────────────────────────────────────
id "${USERNAME}" &>/dev/null || onx_die 2 "Linux user does not exist: ${USERNAME}"
[[ -d "${VHOST_ACTIVE_DIR}" ]]    || onx_die 2 "vhost sites dir not found: ${VHOST_ACTIVE_DIR}"
mkdir -p "${VHOST_SUSPENDED_DIR}" || onx_die 2 "cannot create suspended dir: ${VHOST_SUSPENDED_DIR}"

trap 'onx_rollback_run' ERR

# ── Lock password ─────────────────────────────────────────────────────────────
usermod -L "${USERNAME}"
onx_rollback_register "usermod -U '${USERNAME}' 2>/dev/null || true"
onx_log "password locked: ${USERNAME}"

# ── Disable shell ─────────────────────────────────────────────────────────────
PREV_SHELL=$(getent passwd "${USERNAME}" | cut -d: -f7)
usermod -s /sbin/nologin "${USERNAME}"
onx_rollback_register "usermod -s '${PREV_SHELL}' '${USERNAME}' 2>/dev/null || true"
onx_log "shell set to /sbin/nologin: ${USERNAME}"

# ── Move vhost configs to suspended/ ─────────────────────────────────────────
VHOSTS_MOVED=()
for conf in "${VHOST_ACTIVE_DIR}/${USERNAME}"-*.conf; do
    [[ -f "$conf" ]] || continue
    mv "$conf" "${VHOST_SUSPENDED_DIR}/"
    VHOSTS_MOVED+=("$(basename "$conf")")
    onx_log "vhost disabled: $conf"
done
# Register rollback: move them back
for f in "${VHOSTS_MOVED[@]+"${VHOSTS_MOVED[@]}"}"; do
    onx_rollback_register "mv '${VHOST_SUSPENDED_DIR}/${f}' '${VHOST_ACTIVE_DIR}/' 2>/dev/null || true"
done

# ── Reload Apache ─────────────────────────────────────────────────────────────
systemctl reload httpd || onx_die 3 "systemctl reload httpd failed"
onx_log "httpd reloaded after suspend of ${USERNAME}"

# ── Write suspension.json ─────────────────────────────────────────────────────
SUSPENDED_AT=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
HOME_DIR="/home/${USERNAME}"
mkdir -p "${HOME_DIR}/${META_DIR}"

printf '{"username":"%s","status":"suspended","suspended_at":"%s","reason":"%s"}\n' \
    "${USERNAME}" "${SUSPENDED_AT}" "$(printf '%s' "${REASON}" | sed 's/"/\\"/g')" \
    > "${HOME_DIR}/${META_DIR}/suspension.json"
chmod 600 "${HOME_DIR}/${META_DIR}/suspension.json"
onx_log "suspension.json written"

# ── Output ────────────────────────────────────────────────────────────────────
onx_json_out \
    "username"     "${USERNAME}" \
    "status"       "suspended" \
    "suspended_at" "${SUSPENDED_AT}" \
    "reason"       "${REASON}"
