#!/usr/bin/env bash

set -Eeuo pipefail
umask 077

readonly EXPECTED_HOSTNAME='sqjcmqtt01'
readonly EXPECTED_IP='10.2.203.108'
readonly EXPECTED_NODE_ENV_SHA='6185d5b1780e5f9673c3eb8d6a40526afb2732f41f2532a7664eed1e8c8d5a6b'
readonly EXPECTED_TEMPLATE_SHA='9ffed09e41e384092d469b3c1e39fe5b05aee160c32eda69c80e5af87ce01441'
readonly EXPECTED_ACTIVATE_SHA='e637ca657a897c6d0b689bbd6347f04516baf5c9f32350cd1e8a2071c211a0a5'
readonly EXPECTED_PROVISIONER_SHA='eda667a180add2a54decd6b5bc9f47529ca8f742eaa98c6bf278ebbf6aa3c712'
readonly EXPECTED_ROLE_ACTION_SHA='e3eae16aa5c87f43b56495fc71de378a947578cabe18b507e8fed01ac1f32025'
readonly EXPECTED_RUNTIME_SHA='4c06e4ad325de7241607b06d93c99c2f35f3422bfcbdbeeb43b530f2053f4bb6'
readonly EXPECTED_ROLE_ENV_SHA='c9e325c7e6d27e13e9b59d6e3e28b25ab110af2ae646e29b1a67ea4aa01bc90f'
readonly EXPECTED_HOOKS_SHA='306ff3ad73d393920cd3641d6772e64e121a4e9e42a7ce82ce5902ef2e9501b2'
readonly EXPECTED_NODES_SHA='4cdabace93d432d2ad8a66c4963e4a441fcd0c68e1a5c32d388cfcc1172d4852'
readonly EXPECTED_UNITS_SHA='a1bd2d394fbd5cfb50ba4a808441ff6445b5933ed98a41c6b70d8dffffc000e8'
readonly BUNDLE_ROOT='/opt/zhct-deploy'
readonly TEMPLATE='/etc/zhct/templates/emqx/nodes/emqx01/emqx.conf'
readonly CONFIG='/etc/emqx/emqx.conf'
readonly COOKIE='/etc/zhct/secrets/emqx.cluster-cookie'
readonly COOKIE_TRANSFER='/root/emqx.cluster-cookie.transfer'
readonly AUDIT_LOG='/root/q141-emqx01-activate-and-verify.log'
readonly TARGET_PORT_RE=':(1883|8083|18083|4370|5370|8883|8084)([[:space:]]|$)'

q141_success=0
q141_mutation_started=0
q141_sub_output=''
q141_run_id="q141-$(date +%Y%m%dT%H%M%S%z)"
q141_evidence_dir="/root/q141-143-evidence/${q141_run_id}"

install -d -m 0700 /root/q141-143-evidence
test ! -e "${q141_evidence_dir}"
install -d -m 0700 "${q141_evidence_dir}"
exec > >(tee "${AUDIT_LOG}" "${q141_evidence_dir}/terminal.log") 2>&1

q141_finish() {
  q141_rc=$?
  trap - EXIT
  set +e

  if test -n "${q141_sub_output}"; then
    rm -f "${q141_sub_output}"
  fi

  if test "${q141_success}" -ne 1 && test "${q141_mutation_started}" -eq 1; then
    printf '%s\n' 'Q141_ROLLBACK_BEGIN'
    systemctl disable --now emqx.service >/dev/null 2>&1 || true
    rm -f "${CONFIG}" "${COOKIE}" "${COOKIE_TRANSFER}"
    find /var/lib/emqx /var/log/emqx -mindepth 1 -delete 2>/dev/null || true
    systemctl daemon-reload >/dev/null 2>&1 || true

    q141_rollback_ok=1
    test ! -e "${CONFIG}" || q141_rollback_ok=0
    test ! -e "${COOKIE}" || q141_rollback_ok=0
    test ! -e "${COOKIE_TRANSFER}" || q141_rollback_ok=0
    test "$(systemctl is-enabled emqx.service 2>&1 || true)" = 'disabled' ||
      q141_rollback_ok=0
    test "$(systemctl is-active emqx.service 2>&1 || true)" = 'inactive' ||
      q141_rollback_ok=0
    if ss -lntupH | grep -E "${TARGET_PORT_RE}" >/dev/null; then
      q141_rollback_ok=0
    fi

    if test "${q141_rollback_ok}" -eq 1; then
      printf '%s\n' 'Q141_ROLLBACK_STATUS=PASS_PRE_ACTIVATION_STATE_RESTORED'
    else
      printf '%s\n' 'Q141_ROLLBACK_STATUS=FAIL_MANUAL_REVIEW_REQUIRED'
    fi
  elif test "${q141_success}" -eq 1; then
    printf '%s\n' 'Q141_ROLLBACK_STATUS=NOT_REQUIRED'
  else
    printf '%s\n' 'Q141_ROLLBACK_STATUS=NOT_REQUIRED_NO_MUTATION'
  fi

  printf '%s\n' 'Q141_EMQX01_ACTIVATE_VERIFY_END'
  printf 'Q141_EMQX01_ACTIVATE_VERIFY_RC=%s\n' "${q141_rc}"
  exit "${q141_rc}"
}
trap q141_finish EXIT

printf '%s\n' 'Q141_EMQX01_ACTIVATE_VERIFY_BEGIN'
printf 'RUN_ID=%s\n' "${q141_run_id}"

test "${EUID}" -eq 0
exec 9>/run/lock/zhct-emqx-q141.lock
flock -n 9

printf '%s\n' '=== TARGET IDENTITY ==='
hostname -s | grep -Fx "${EXPECTED_HOSTNAME}"
ip -br -4 addr show ens192
ip -br -4 addr show ens192 | grep -F "${EXPECTED_IP}/24"
test "$(uname -m)" = 'x86_64'

printf '%s\n' '=== PACKAGES AND COMMANDS ==='
rpm -q emqx-5.8.9-1.el8.x86_64
rpm -q mosquitto libatomic cjson libwebsockets
for q141_command in \
  emqx flock mosquitto_pub mosquitto_sub openssl python3 sha256sum ss systemctl timeout; do
  command -v "${q141_command}" >/dev/null
  printf 'COMMAND_PRESENT=%s\n' "${q141_command}"
done

printf '%s\n' '=== LOCKED ASSETS ==='
printf '%s  %s\n' "${EXPECTED_NODE_ENV_SHA}" '/etc/zhct/node.env' |
  sha256sum -c -
printf '%s  %s\n' "${EXPECTED_TEMPLATE_SHA}" "${TEMPLATE}" |
  sha256sum -c -
printf '%s  %s\n' \
  "${EXPECTED_ACTIVATE_SHA}" \
  "${BUNDLE_ROOT}/common/scripts/activate-role.sh" | sha256sum -c -
printf '%s  %s\n' \
  "${EXPECTED_PROVISIONER_SHA}" \
  '/usr/local/sbin/provision-emqx-cookie.sh' | sha256sum -c -
printf '%s  %s\n' \
  "${EXPECTED_ROLE_ACTION_SHA}" \
  "${BUNDLE_ROOT}/common/bin/role-action.sh" | sha256sum -c -
printf '%s  %s\n' \
  "${EXPECTED_RUNTIME_SHA}" \
  "${BUNDLE_ROOT}/common/lib/runtime.sh" | sha256sum -c -
printf '%s  %s\n' \
  "${EXPECTED_ROLE_ENV_SHA}" \
  "${BUNDLE_ROOT}/roles/emqx/role.env" | sha256sum -c -
printf '%s  %s\n' \
  "${EXPECTED_HOOKS_SHA}" \
  "${BUNDLE_ROOT}/roles/emqx/hooks.sh" | sha256sum -c -
printf '%s  %s\n' \
  "${EXPECTED_NODES_SHA}" \
  "${BUNDLE_ROOT}/roles/emqx/manifests/nodes.tsv" | sha256sum -c -
printf '%s  %s\n' \
  "${EXPECTED_UNITS_SHA}" \
  "${BUNDLE_ROOT}/roles/emqx/manifests/systemd-units.tsv" | sha256sum -c -
test "$(stat -c '%U:%G:%a' /etc/zhct/node.env)" = 'root:root:640'
test "$(stat -c '%U:%G:%a' /usr/local/sbin/provision-emqx-cookie.sh)" = \
  'root:root:750'
grep -Fxq 'ROLE=emqx' /etc/zhct/node.env
grep -Fxq 'NODE_KEY=emqx01' /etc/zhct/node.env
grep -Fxq 'NODE_IP=10.2.203.108' /etc/zhct/node.env
grep -Fxq 'NODE_NAME=sqjcmqtt01' /etc/zhct/node.env
printf '%s\n' 'LOCKED_ASSETS_PASS'

printf '%s\n' '=== PRE-ACTIVATION QUIET GATE ==='
test ! -e "${CONFIG}"
test ! -e "${COOKIE}"
test ! -e "${COOKIE_TRANSFER}"
for q141_unit in emqx.service mosquitto.service; do
  q141_enabled=$(systemctl is-enabled "${q141_unit}" 2>&1 || true)
  q141_active=$(systemctl is-active "${q141_unit}" 2>&1 || true)
  printf '%s enabled=%s active=%s\n' \
    "${q141_unit}" "${q141_enabled}" "${q141_active}"
  test "${q141_enabled}" = 'disabled'
  test "${q141_active}" = 'inactive'
done
if pgrep -x beam.smp >/dev/null || pgrep -x mosquitto >/dev/null; then
  printf '%s\n' 'TARGET_PROCESS_UNEXPECTED'
  exit 1
fi
if ss -lntupH | grep -E "${TARGET_PORT_RE}"; then
  printf '%s\n' 'TARGET_LISTENER_UNEXPECTED'
  exit 1
fi
if find /var/lib/emqx /var/log/emqx -mindepth 1 -print -quit 2>/dev/null |
  grep -q .; then
  printf '%s\n' 'PREEXISTING_RUNTIME_STATE_UNEXPECTED'
  exit 1
fi
printf '%s\n' 'PRE_ACTIVATION_CONFIG_ABSENT'
printf '%s\n' 'PRE_ACTIVATION_COOKIE_ABSENT'
printf '%s\n' 'PRE_ACTIVATION_PROCESSES_ZERO'
printf '%s\n' 'PRE_ACTIVATION_LISTENERS_ZERO'
printf '%s\n' 'PRE_ACTIVATION_RUNTIME_EMPTY'
printf '%s\n' 'POST_CLONE_NOT_RUN_BY_THIS_SCRIPT'

q141_mutation_started=1

printf '%s\n' '=== MATERIALIZE TEMPLATE AND COOKIE ==='
install -m 0600 -o emqx -g emqx "${TEMPLATE}" "${CONFIG}"
grep -Fq '__EMQX_CLUSTER_COOKIE__' "${CONFIG}"
grep -Fq 'name = "emqx@10.2.203.108"' "${CONFIG}"
/usr/local/sbin/provision-emqx-cookie.sh
test -s "${COOKIE}"
test "$(stat -c '%U:%G:%a' "${COOKIE}")" = 'root:root:600'
q141_cookie_size=$(stat -c '%s' "${COOKIE}")
q141_cookie_sha=$(sha256sum "${COOKIE}" | awk '{print $1}')
printf 'COOKIE_PRESENT=PASS\n'
printf 'COOKIE_OWNER_MODE=root:root:600\n'
printf 'COOKIE_SIZE=%s\n' "${q141_cookie_size}"
printf 'COOKIE_SHA256=%s\n' "${q141_cookie_sha}"
install -m 0600 -o root -g root "${COOKIE}" "${COOKIE_TRANSFER}"
test "$(sha256sum "${COOKIE_TRANSFER}" | awk '{print $1}')" = \
  "${q141_cookie_sha}"
printf '%s\n' 'COOKIE_TRANSFER_OWNER_MODE=root:root:600'
printf 'COOKIE_TRANSFER_SHA256=%s\n' "${q141_cookie_sha}"
printf '%s\n' 'COOKIE_VALUE_NOT_OUTPUT'

printf '%s\n' '=== CONFIG CHECK AND ACTIVATION ==='
emqx check_config
printf '%s\n' 'PRE_ACTIVATE_CHECK_CONFIG_RC=0'
"${BUNDLE_ROOT}/common/scripts/activate-role.sh" \
  --role emqx --bundle-root "${BUNDLE_ROOT}"
emqx check_config
printf '%s\n' 'POST_ACTIVATE_CHECK_CONFIG_RC=0'
if grep -Fq '__EMQX_CLUSTER_COOKIE__' "${CONFIG}"; then
  printf '%s\n' 'CONFIG_PLACEHOLDER_UNEXPECTED'
  exit 1
fi
grep -Fq 'name = "emqx@10.2.203.108"' "${CONFIG}"
printf '%s\n' 'NODE_NAME_UNIQUE=emqx@10.2.203.108'

for q141_attempt in $(seq 1 30); do
  if systemctl is-active --quiet emqx.service &&
    ss -lntH | grep -Eq '(^|[[:space:]])(127\.0\.0\.1|0\.0\.0\.0|\*):1883([[:space:]]|$)'; then
    break
  fi
  sleep 1
done
test "$(systemctl is-enabled emqx.service)" = 'enabled'
test "$(systemctl is-active emqx.service)" = 'active'
test "$(systemctl is-enabled mosquitto.service 2>&1 || true)" = 'disabled'
test "$(systemctl is-active mosquitto.service 2>&1 || true)" = 'inactive'

printf '%s\n' '=== LOCAL UNIQUE PUBSUB ==='
q141_topic_suffix=${q141_run_id//+/_}
if ! printf '%s' "${q141_topic_suffix}" | grep -Eq '^[A-Za-z0-9_-]+$'; then
  printf '%s\n' 'PUBSUB_TOPIC_SUFFIX_UNSAFE'
  exit 1
fi
q141_topic="sanquan/q141/emqx01/${q141_topic_suffix}"
q141_payload="Q141_EMQX01_$(openssl rand -hex 16)"
q141_payload_sha=$(printf '%s' "${q141_payload}" | sha256sum | awk '{print $1}')
q141_sub_output=$(mktemp /var/tmp/q141-emqx01-sub.XXXXXX)
timeout 15 mosquitto_sub \
  -h 127.0.0.1 -p 1883 -t "${q141_topic}" -C 1 -W 12 \
  >"${q141_sub_output}" &
q141_sub_pid=$!
sleep 1
mosquitto_pub \
  -h 127.0.0.1 -p 1883 -t "${q141_topic}" -m "${q141_payload}"
wait "${q141_sub_pid}"
q141_received=$(<"${q141_sub_output}")
rm -f "${q141_sub_output}"
q141_sub_output=''
test "${q141_received}" = "${q141_payload}"
printf 'PUBSUB_TOPIC=%s\n' "${q141_topic}"
printf 'PUBSUB_PAYLOAD_SHA256=%s\n' "${q141_payload_sha}"
printf '%s\n' 'PUBSUB_MATCH=PASS'
unset q141_payload q141_received

printf '%s\n' '=== POST-ACTIVATION STATE ==='
printf 'EMQX_UNIT_ENABLED=%s\n' "$(systemctl is-enabled emqx.service)"
printf 'EMQX_UNIT_ACTIVE=%s\n' "$(systemctl is-active emqx.service)"
printf 'MOSQUITTO_UNIT_ENABLED=%s\n' \
  "$(systemctl is-enabled mosquitto.service 2>&1 || true)"
printf 'MOSQUITTO_UNIT_ACTIVE=%s\n' \
  "$(systemctl is-active mosquitto.service 2>&1 || true)"
printf '%s\n' 'NODE_STATUS_BEGIN'
emqx ctl status
printf '%s\n' 'NODE_STATUS_END'
printf '%s\n' 'CLUSTER_STATUS_OBSERVATION_BEGIN'
emqx ctl cluster status || true
printf '%s\n' 'CLUSTER_STATUS_OBSERVATION_END'
printf '%s\n' 'LISTENERS_BEGIN'
ss -lntupH | grep -E "${TARGET_PORT_RE}" || true
printf '%s\n' 'LISTENERS_END'
printf '%s\n' 'LOG_FILES_BEGIN'
find /var/log/emqx -maxdepth 2 -type f \
  -printf '%p\t%U:%G\t%m\t%s\n' | sort
printf '%s\n' 'LOG_FILES_END'
printf '%s\n' 'JOURNAL_ERRORS_BEGIN'
journalctl -u emqx.service -p err -n 50 --no-pager |
  sed -E '/cookie|secret|password|token/Id' || true
printf '%s\n' 'JOURNAL_ERRORS_END'
printf '%s\n' 'JOURNAL_SECRET_FILTER_APPLIED=YES'
printf '%s\n' 'Q200_NETWORK_GATE=NOT_PERFORMED'
printf '%s\n' 'Q240_FORMAL_CLUSTER_ACCEPTANCE=NOT_PERFORMED'
printf '%s\n' 'KEEPALIVED_VIP=OUT_OF_SCOPE'

q141_success=1
printf '%s\n' 'Q141_EMQX01_ACTIVATION_PASS'
