#!/usr/bin/env bash
set -Eeuo pipefail
umask 077
export LC_ALL=C

EXPECTED_HOSTNAME=sqjcredis01
EXPECTED_IPV4=10.2.203.112
RUN_ID=${1:-}
ROOT="/var/tmp/zhct-redis01-verify/${RUN_ID}"
REDIS5=/opt/redis/5.0.14/bin
REDIS7=/opt/redis/7.2.14/bin

die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
cleanup() {
  set +e
  for pid_file in "${ROOT}"/run/*.pid; do
    [[ -s "${pid_file}" ]] || continue
    pid=$(cat "${pid_file}")
    [[ "${pid}" =~ ^[0-9]+$ ]] && kill -TERM "${pid}" 2>/dev/null
  done
  for _ in $(seq 1 20); do
    pgrep -f "${ROOT}" >/dev/null 2>&1 || break
    sleep 0.2
  done
  if pgrep -f "${ROOT}" >/dev/null 2>&1; then
    printf 'ERROR: temporary Redis verification process remains; evidence retained at %s\n' "${ROOT}" >&2
    return 1
  fi
  find "${ROOT}" -xdev -mindepth 1 -delete 2>/dev/null
  rmdir "${ROOT}" 2>/dev/null
}
trap cleanup EXIT

[[ "${EUID}" -eq 0 ]] || die 'must run as root'
[[ "${RUN_ID}" =~ ^q071-[0-9]{8}T[0-9]{6}[+]0800$ ]] || die 'invalid Q071 run id'
[[ "$(hostname -s)" == "${EXPECTED_HOSTNAME}" ]] || die 'hostname mismatch'
ip -o -4 addr show scope global | awk '{print $4}' | cut -d/ -f1 |
  grep -Fxq "${EXPECTED_IPV4}" || die 'expected IPv4 is not configured'
[[ "$(sysctl -n vm.overcommit_memory)" == 1 ]] || die 'overcommit gate failed'
grep -Fq '[never]' /sys/kernel/mm/transparent_hugepage/enabled || die 'THP gate failed'
id redis >/dev/null 2>&1 || die 'redis account is missing'
[[ ! -e "${ROOT}" ]] || die 'temporary verification root already exists'

for unit in redis5 redis7 sentinel5 sentinel7 orchestrator; do
  systemctl is-active --quiet "${unit}.service" && die "formal unit is active: ${unit}"
done
for port in 6379 6387 26379 26387 3000 10008 16379 16387 36379 36387; do
  ss -H -lnt "sport = :${port}" | grep -q . && die "port is already listening: ${port}"
done

"${REDIS5}/redis-server" --version | grep -Fq 'v=5.0.14' || die 'Redis5 version mismatch'
"${REDIS7}/redis-server" --version | grep -Fq 'v=7.2.14' || die 'Redis7 version mismatch'
ldd "${REDIS5}/redis-server" | grep -Fq 'not found' && die 'Redis5 has a missing library'
ldd "${REDIS7}/redis-server" | grep -Fq 'not found' && die 'Redis7 has a missing library'
rpm -q --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' percona-orchestrator |
  grep -Fxq 'percona-orchestrator-3.2.6-22.el8.x86_64' || die 'Orchestrator RPM mismatch'
command -v orchestrator >/dev/null || die 'Orchestrator command is missing'

install -d -m 0750 -o redis -g redis "${ROOT}"/{conf,data5,data7,sentinel5,sentinel7,run,log}
{
  printf 'bind 127.0.0.1\nport 16379\nprotected-mode yes\ndaemonize yes\n'
  printf 'pidfile %s/run/redis5.pid\n' "${ROOT}"
  printf 'dir %s/data5\nlogfile %s/log/redis5.log\nsave ""\nappendonly no\n' "${ROOT}" "${ROOT}"
} >"${ROOT}/conf/redis5.conf"
{
  printf 'bind 127.0.0.1\nport 16387\nprotected-mode yes\ndaemonize yes\n'
  printf 'pidfile %s/run/redis7.pid\n' "${ROOT}"
  printf 'dir %s/data7\nlogfile %s/log/redis7.log\nsave ""\nappendonly no\n' "${ROOT}" "${ROOT}"
} >"${ROOT}/conf/redis7.conf"
{
  printf 'bind 127.0.0.1\nport 36379\ndaemonize yes\n'
  printf 'pidfile %s/run/sentinel5.pid\nlogfile %s/log/sentinel5.log\n' "${ROOT}" "${ROOT}"
  printf 'sentinel monitor temp-redis5 127.0.0.1 16379 1\n'
  printf 'sentinel down-after-milliseconds temp-redis5 30000\n'
} >"${ROOT}/conf/sentinel5.conf"
{
  printf 'bind 127.0.0.1\nport 36387\ndaemonize yes\n'
  printf 'pidfile %s/run/sentinel7.pid\nlogfile %s/log/sentinel7.log\n' "${ROOT}" "${ROOT}"
  printf 'sentinel monitor temp-redis7 127.0.0.1 16387 1\n'
  printf 'sentinel down-after-milliseconds temp-redis7 30000\n'
} >"${ROOT}/conf/sentinel7.conf"
chown -R redis:redis "${ROOT}"

runuser -u redis -- "${REDIS5}/redis-server" "${ROOT}/conf/redis5.conf"
runuser -u redis -- "${REDIS7}/redis-server" "${ROOT}/conf/redis7.conf"
runuser -u redis -- "${REDIS5}/redis-sentinel" "${ROOT}/conf/sentinel5.conf"
runuser -u redis -- "${REDIS7}/redis-sentinel" "${ROOT}/conf/sentinel7.conf"

for port in 16379 16387 36379 36387; do
  for _ in $(seq 1 30); do
    ss -H -lnt "sport = :${port}" | grep -q . && break
    sleep 0.2
  done
  ss -H -lnt "sport = :${port}" | grep -q . || die "temporary port did not listen: ${port}"
done

key="q071:${RUN_ID}:probe"
"${REDIS5}/redis-cli" -h 127.0.0.1 -p 16379 SET "${key}" redis5 | grep -Fxq OK
"${REDIS5}/redis-cli" -h 127.0.0.1 -p 16379 GET "${key}" | grep -Fxq redis5
"${REDIS7}/redis-cli" -h 127.0.0.1 -p 16387 SET "${key}" redis7 | grep -Fxq OK
"${REDIS7}/redis-cli" -h 127.0.0.1 -p 16387 GET "${key}" | grep -Fxq redis7
"${REDIS5}/redis-cli" -h 127.0.0.1 -p 36379 SENTINEL get-master-addr-by-name temp-redis5 |
  grep -Fxq 127.0.0.1
"${REDIS7}/redis-cli" -h 127.0.0.1 -p 36387 SENTINEL get-master-addr-by-name temp-redis7 |
  grep -Fxq 127.0.0.1
cleanup
trap - EXIT
for port in 6379 6387 26379 26387 3000 10008 16379 16387 36379 36387; do
  ss -H -lnt "sport = :${port}" | grep -q . && die "port remains listening after cleanup: ${port}"
done
for unit in redis5 redis7 sentinel5 sentinel7 orchestrator; do
  systemctl is-active --quiet "${unit}.service" && die "formal unit became active: ${unit}"
done
printf 'REDIS01_TEMPORARY_VERIFY_OK\n'
