#!/bin/sh
# Install as root:root 0755 at /usr/local/sbin/han-message-safety-mode.
set -eu

MODE_FILE=/etc/han-chat/message-safety-mode.env
COMPOSE=/usr/local/sbin/han-vm2-compose
LOCK=/run/lock/han-message-safety-mode.lock
MODE_GROUP=han-message-safety

if [ "$#" -eq 1 ] && [ "$1" = standard ]; then
    mock=false
    text=false
    file=false
elif [ "$#" -eq 5 ] &&
  [ "$1" = mock ] &&
  [ "$2" = --text-free ] &&
  { [ "$3" = true ] || [ "$3" = false ]; } &&
  [ "$4" = --file-free ] &&
  { [ "$5" = true ] || [ "$5" = false ]; }; then
    mock=true
    text=$3
    file=$5
else
    echo "usage: han-message-safety-mode standard | mock --text-free true|false --file-free true|false" >&2
    exit 64
fi

[ "$(id -u)" -eq 0 ] || {
  echo "must run through approved sudo rule" >&2
  exit 77
}
[ -x "$COMPOSE" ] || {
  echo "fixed compose launcher is unavailable" >&2
  exit 69
}

exec 9>"$LOCK"
/usr/bin/flock -n 9 || {
  echo "another mode transition is active" >&2
  exit 75
}

directory=$(dirname "$MODE_FILE")
/usr/bin/install -d -o root -g root -m 0700 "$directory"
temporary=$(/usr/bin/mktemp "$directory/.message-safety-mode.XXXXXX")
backup=$(/usr/bin/mktemp "$directory/.message-safety-mode.backup.XXXXXX")
cleanup() {
  /usr/bin/rm -f "$temporary" "$backup"
}
trap cleanup EXIT HUP INT TERM

if [ -f "$MODE_FILE" ]; then
  /usr/bin/cp --preserve=mode,ownership "$MODE_FILE" "$backup"
else
  : >"$backup"
  /usr/bin/chmod 0600 "$backup"
fi
old_mode=$(/usr/bin/awk -F= '
  $1 == "MESSAGE_SAFETY_MOCK_ENABLED" {mock=$2}
  $1 == "MESSAGE_SAFETY_MOCK_TEXT_FREE" {text=$2}
  $1 == "MESSAGE_SAFETY_MOCK_FILE_FREE" {file=$2}
  END {printf "mock=%s,text=%s,file=%s", mock, text, file}
' "$backup")

{
  printf 'MESSAGE_SAFETY_MOCK_ENABLED=%s\n' "$mock"
  printf 'MESSAGE_SAFETY_MOCK_TEXT_FREE=%s\n' "$text"
  printf 'MESSAGE_SAFETY_MOCK_FILE_FREE=%s\n' "$file"
} >"$temporary"
/usr/bin/chown root:"$MODE_GROUP" "$temporary"
/usr/bin/chmod 0640 "$temporary"
/usr/bin/mv -fT "$temporary" "$MODE_FILE"

restart_api() {
  "$COMPOSE" config --quiet &&
    "$COMPOSE" up -d --no-deps --force-recreate message-safety-api
}

healthy=false
if restart_api; then
  attempt=0
  while [ "$attempt" -lt 30 ]; do
    container=$("$COMPOSE" ps -q message-safety-api)
    if [ -n "$container" ]; then
      status=$(/usr/bin/docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' "$container")
      if [ "$status" = healthy ]; then
        healthy=true
        break
      fi
    fi
    attempt=$((attempt + 1))
    /usr/bin/sleep 2
  done
fi

if [ "$healthy" != true ]; then
  if [ -s "$backup" ]; then
    /usr/bin/cp "$backup" "$temporary"
  else
    printf '%s\n' \
      'MESSAGE_SAFETY_MOCK_ENABLED=false' \
      'MESSAGE_SAFETY_MOCK_TEXT_FREE=false' \
      'MESSAGE_SAFETY_MOCK_FILE_FREE=false' >"$temporary"
  fi
  /usr/bin/chown root:"$MODE_GROUP" "$temporary"
  /usr/bin/chmod 0640 "$temporary"
  /usr/bin/mv -fT "$temporary" "$MODE_FILE"
  restart_api || true
  /usr/bin/logger -p authpriv.err -t han-message-safety-mode "transition failed; previous policy restored"
  exit 1
fi

/usr/bin/logger -p authpriv.notice -t han-message-safety-mode \
  "transition succeeded old=$old_mode new=mock=$mock,text=$text,file=$file actor=${SUDO_USER:-root}"
