#!/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:-}
CONFIRM=${2:-}
EVIDENCE_DIR="/var/backups/zhct-q070/evidence/${RUN_ID}"
PACKAGE_ROOT=/opt/zhct-deploy/packages
BUILD_ROOT="/var/tmp/zhct-redis-build-wrapv-${RUN_ID}"
STAGE_ROOT="/var/tmp/zhct-redis-stage-wrapv-${RUN_ID}"
RESULT_FILE="${EVIDENCE_DIR}/q071-redis-build-wrapv-result.env"
LOG_FILE="${EVIDENCE_DIR}/q071-redis-build-wrapv.log"
STATUS_FILE="${EVIDENCE_DIR}/q071-redis-build-wrapv-status.env"
FIRST_LOG="${EVIDENCE_DIR}/q071-redis-build.log"
FIRST_STATUS="${EVIDENCE_DIR}/q071-redis-build-status.env"

versions=(5.0.14 7.2.14)
expected_sha=(
  3ea5024766d983249e80d4aa9457c897a9f079957d0fb1f35682df233f997f32
  21326da3f66c0aead4c8204c0ac52ff905337a77cadd169f75ac22835ea30025
)

committed=0
installation_started=0
die() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
target_listener_present() {
  ss -lntupH |
    grep -Eq ':(6379|6387|26379|26387|3000|10008|16379|16387|36379|36387)([[:space:]]|$)'
}
write_status() {
  local state=$1 detail=$2 tmp
  tmp=$(mktemp "${EVIDENCE_DIR}/.q071-redis-build-status.XXXXXX")
  {
    printf 'state=%s\n' "${state}"
    printf 'detail=%s\n' "${detail}"
    printf 'run_id=%s\n' "${RUN_ID}"
    date --iso-8601=seconds | sed 's/^/updated_at=/'
  } >"${tmp}"
  install -o root -g root -m 0600 "${tmp}" "${STATUS_FILE}"
  rm -f -- "${tmp}"
}
on_error() {
  local rc=$?
  trap - ERR
  set +e
  if [[ "${installation_started}" -eq 1 && "${committed}" -eq 0 ]]; then
    rm -rf -- /opt/redis/5.0.14 /opt/redis/7.2.14
  fi
  write_status FAIL "build_or_validation_rc_${rc}"
  rm -rf -- "${BUILD_ROOT}" "${STAGE_ROOT}"
  printf 'ERROR: Redis build/install failed; inspect %s\n' "${LOG_FILE}" >&2
  exit "${rc}"
}
trap on_error ERR

[[ "${EUID}" -eq 0 ]] || die 'must run as root'
[[ "${RUN_ID}" =~ ^q070-[0-9]{8}T[0-9]{6}[+]0800$ ]] || die 'invalid Q070 run id'
[[ "${CONFIRM}" == --execute-q071-redis-build-install ]] ||
  die 'explicit Redis build/install flag is required'
[[ "$(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'

for file in \
  "${EVIDENCE_DIR}/q071-install-result.env" \
  "${EVIDENCE_DIR}/q071-dnf-transaction-id.txt" \
  "${EVIDENCE_DIR}/q071-installed-nevra.txt" \
  "${FIRST_LOG}" "${FIRST_STATUS}"; do
  [[ -s "${file}" ]] || die "required RPM receipt missing: ${file}"
done
grep -Fxq 'install_result=PASS_RPM_INSTALLED' \
  "${EVIDENCE_DIR}/q071-install-result.env" || die 'RPM receipt is not PASS'
grep -Fxq "run_id=${RUN_ID}" "${EVIDENCE_DIR}/q071-install-result.env" ||
  die 'RPM receipt run id mismatch'
grep -Fxq 'dnf_transaction_id=2' "${EVIDENCE_DIR}/q071-install-result.env" ||
  die 'RPM transaction id mismatch'
[[ "$(cat "${EVIDENCE_DIR}/q071-dnf-transaction-id.txt")" == 2 ]] ||
  die 'RPM transaction file mismatch'
grep -Fxq 'state=FAIL' "${FIRST_STATUS}" ||
  die 'first Redis build status is not preserved as FAIL'
grep -Fq 'BITFIELD overflow wrap fuzzing' "${FIRST_LOG}" ||
  die 'first Redis build failure evidence is missing'
for command in gcc make tclsh tar sha256sum; do
  command -v "${command}" >/dev/null || die "required build command missing: ${command}"
done
for path in /opt/redis/5.0.14 /opt/redis/7.2.14 \
  "${BUILD_ROOT}" "${STAGE_ROOT}" "${RESULT_FILE}" "${LOG_FILE}" "${STATUS_FILE}"; do
  [[ ! -e "${path}" && ! -L "${path}" ]] || die "target already exists: ${path}"
done
for unit in orchestrator redis5 redis7 sentinel5 sentinel7; do
  ! systemctl is-active --quiet "${unit}.service" ||
    die "target unit is active before build: ${unit}"
done
! target_listener_present || die 'target listener exists before build'

for index in "${!versions[@]}"; do
  version=${versions[$index]}
  archive="${PACKAGE_ROOT}/redis-${version}.tar.gz"
  [[ -f "${archive}" ]] || die "Redis archive missing: ${archive}"
  printf '%s  %s\n' "${expected_sha[$index]}" "${archive}" |
    sha256sum -c - >/dev/null || die "Redis archive SHA256 mismatch: ${version}"
  if tar -tzf "${archive}" |
    awk 'BEGIN {bad=0} /^\// {bad=1} $0 ~ /(^|\/)\.\.(\/|$)/ {bad=1} END {exit bad}'; then
    :
  else
    die "unsafe archive member detected: ${version}"
  fi
done

install -d -o root -g root -m 0700 "${BUILD_ROOT}" "${STAGE_ROOT}"
write_status RUNNING preflight_passed
exec > >(tee -a "${LOG_FILE}") 2>&1
printf 'REDIS_BUILD_STARTED=%s\n' "$(date --iso-8601=seconds)"
printf 'BUILD_JOBS=%s\n' "$(nproc)"

for index in "${!versions[@]}"; do
  version=${versions[$index]}
  archive="${PACKAGE_ROOT}/redis-${version}.tar.gz"
  printf '=== EXTRACT REDIS %s ===\n' "${version}"
  tar -xzf "${archive}" -C "${BUILD_ROOT}"
  source_dir="${BUILD_ROOT}/redis-${version}"
  [[ -d "${source_dir}" ]] || die "source directory missing: ${version}"
  make_args=()
  if [[ "${version}" == 5.0.14 ]]; then
    make_args=('CFLAGS=-fwrapv')
    printf 'REDIS_5_CFLAGS=-fwrapv\n'
  else
    printf 'REDIS_7_CFLAGS=DEFAULT\n'
  fi
  printf '=== BUILD REDIS %s ===\n' "${version}"
  make -C "${source_dir}" -j"$(nproc)" "${make_args[@]}"
  printf '=== TEST REDIS %s ===\n' "${version}"
  make -C "${source_dir}" test "${make_args[@]}"
  printf '=== STAGE REDIS %s ===\n' "${version}"
  make -C "${source_dir}" install PREFIX="${STAGE_ROOT}/${version}" "${make_args[@]}"
  "${STAGE_ROOT}/${version}/bin/redis-server" --version
  "${STAGE_ROOT}/${version}/bin/redis-cli" --version
done

install -d -o root -g root -m 0755 /opt/redis
installation_started=1
mv "${STAGE_ROOT}/5.0.14" /opt/redis/5.0.14
mv "${STAGE_ROOT}/7.2.14" /opt/redis/7.2.14
for version in "${versions[@]}"; do
  chown -R root:root "/opt/redis/${version}"
  find "/opt/redis/${version}" -type d -exec chmod 0755 {} +
  find "/opt/redis/${version}/bin" -type f -exec chmod 0755 {} +
  "/opt/redis/${version}/bin/redis-server" --version
  "/opt/redis/${version}/bin/redis-cli" --version
done
for unit in orchestrator redis5 redis7 sentinel5 sentinel7; do
  ! systemctl is-active --quiet "${unit}.service" ||
    die "target unit became active after build: ${unit}"
done
! target_listener_present || die 'target listener appeared after build'

result_tmp=$(mktemp "${EVIDENCE_DIR}/.q071-redis-build-result.XXXXXX")
{
  printf 'build_result=PASS_REDIS_BINARIES_INSTALLED\n'
  printf 'run_id=%s\n' "${RUN_ID}"
  printf 'redis5_version=5.0.14\n'
  printf 'redis5_cflags=-fwrapv\n'
  printf 'redis7_version=7.2.14\n'
  printf 'redis7_cflags=DEFAULT\n'
  printf 'install_root=/opt/redis\n'
  printf 'target_units=INACTIVE\n'
  printf 'target_listeners=NONE\n'
} >"${result_tmp}"
install -o root -g root -m 0600 "${result_tmp}" "${RESULT_FILE}"
rm -f -- "${result_tmp}"
committed=1
write_status PASS redis_binaries_installed
rm -rf -- "${BUILD_ROOT}" "${STAGE_ROOT}"
trap - ERR
printf 'Q071_REDIS_BUILD_INSTALL=PASS_REDIS_BINARIES_INSTALLED\n'
cat "${RESULT_FILE}"
