#!/usr/bin/env bash

set -Eeuo pipefail
export LANG=C
umask 077

EXPECTED_HOSTNAME="sqjcDB01"
EXPECTED_IPV4="10.2.208.106"
EXPECTED_OS="openEuler release 24.03 (LTS-SP1)"
BACKUP_ROOT="/var/backups/zhct-q060"
TARGET_PORTS_RE=':(3306|3308|9201|9202)([[:space:]]|$)'

die() {
  printf 'ERROR: %s\n' "$*" >&2
  exit 1
}

[[ "${EUID}" -eq 0 ]] || die "must run as root"
[[ "$(hostname -s)" == "${EXPECTED_HOSTNAME}" ]] || die "hostname mismatch"
[[ "$(uname -m)" == "x86_64" ]] || die "architecture mismatch"
[[ "$(tr -d '\r' </etc/openEuler-release)" == "${EXPECTED_OS}" ]] || die "OS mismatch"
ip -o -4 addr show scope global | awk '{print $4}' | cut -d/ -f1 |
  grep -Fxq "${EXPECTED_IPV4}" || die "expected IPv4 is not configured"

RUN_ID="$(date '+%Y%m%dT%H%M%S%z')"
EVIDENCE_DIR="${BACKUP_ROOT}/${RUN_ID}"
BASELINE_DIR="${EVIDENCE_DIR}/baseline"
CONFIG_DIR="${EVIDENCE_DIR}/config"
install -d -m 0700 "${BASELINE_DIR}" "${CONFIG_DIR}"

hostnamectl >"${BASELINE_DIR}/hostnamectl.txt" 2>&1
cat /etc/openEuler-release >"${BASELINE_DIR}/openEuler-release.txt"
uname -a >"${BASELINE_DIR}/uname.txt"
lscpu >"${BASELINE_DIR}/lscpu.txt"
free -h >"${BASELINE_DIR}/free.txt"
df -hT >"${BASELINE_DIR}/df-hT.txt"
df -i >"${BASELINE_DIR}/df-inode.txt"
findmnt >"${BASELINE_DIR}/findmnt.txt"
ip -br address >"${BASELINE_DIR}/ip-address.txt"
ip route show table all >"${BASELINE_DIR}/ip-route.txt"
ss -lntup >"${BASELINE_DIR}/listeners.txt"
ps -eo pid,ppid,user,group,cmd >"${BASELINE_DIR}/processes.txt"
systemctl list-units --type=service --all --no-pager >"${BASELINE_DIR}/services-all.txt"
systemctl list-unit-files --type=service --no-pager >"${BASELINE_DIR}/service-unit-files.txt"
systemctl --failed --all --no-pager >"${BASELINE_DIR}/failed-units.txt"
systemctl list-timers --all --no-pager >"${BASELINE_DIR}/timers.txt"
rpm -qa --qf '%{NAME}\t%{EPOCHNUM}:%{VERSION}-%{RELEASE}\t%{ARCH}\n' |
  sort >"${BASELINE_DIR}/rpm-installed.tsv"
dnf history list >"${BASELINE_DIR}/dnf-history.txt" 2>&1
crontab -l >"${BASELINE_DIR}/root-crontab.txt" 2>&1 || true
atq >"${BASELINE_DIR}/atq.txt" 2>&1 || true
getent passwd mysql >"${BASELINE_DIR}/mysql-passwd.txt" 2>&1 || true
getent group mysql >"${BASELINE_DIR}/mysql-group.txt" 2>&1 || true

: >"${BASELINE_DIR}/mysql-paths.tsv"
for path in \
  /opt/mysql /data/mysql56 /data/mysql80 \
  /var/log/mysql56 /var/log/mysql80 \
  /etc/my.cnf /etc/my56.cnf /etc/my80.cnf \
  /etc/systemd/system/mysql56.service /etc/systemd/system/mysql80.service \
  /etc/systemd/system/mysql-health56.service /etc/systemd/system/mysql-health80.service \
  /etc/zhct/templates/mysql /etc/zhct/node.env; do
  if [[ -e "${path}" || -L "${path}" ]]; then
    printf 'PRESENT\t%s\n' "${path}" >>"${BASELINE_DIR}/mysql-paths.tsv"
    cp -a --parents "${path}" "${CONFIG_DIR}/" 2>/dev/null || true
  else
    printf 'ABSENT\t%s\n' "${path}" >>"${BASELINE_DIR}/mysql-paths.tsv"
  fi
done

TARGET_LISTENERS="$(ss -lntupH | grep -E "${TARGET_PORTS_RE}" || true)"
printf '%s\n' "${TARGET_LISTENERS}" >"${BASELINE_DIR}/target-listeners.txt"
[[ -z "${TARGET_LISTENERS}" ]] || die "a target MySQL/health port is already listening"
TARGET_PROCESSES="$(ps -eo pid,ppid,user,group,cmd |
  grep -Ei '[m]ysqld|[m]ysqlrouter|[m]ysqladmin.*ping' || true)"
printf '%s\n' "${TARGET_PROCESSES}" >"${BASELINE_DIR}/target-processes.txt"
[[ -z "${TARGET_PROCESSES}" ]] || die "a MySQL process already exists"
if awk -F'\t' '$1 == "PRESENT" && $2 ~ /^\/(opt\/mysql|data\/mysql56|data\/mysql80)/ {found=1}
  END {exit !found}' "${BASELINE_DIR}/mysql-paths.tsv"; then
  die "a formal MySQL software/data path already exists"
fi

find "${EVIDENCE_DIR}" -type f -print0 | sort -z |
  xargs -0 sha256sum >"${EVIDENCE_DIR}/sha256sums.txt"
{
  printf 'captured_at=%s\n' "$(date --iso-8601=seconds)"
  printf 'run_id=%s\n' "${RUN_ID}"
  printf 'baseline_result=PASS\n'
  printf 'target_listener_check=PASS\n'
  printf 'target_process_check=PASS\n'
  printf 'formal_mysql_paths=ABSENT\n'
  printf 'install_execution=NOT_PERFORMED\n'
  printf 'post_clone_execution=NOT_PERFORMED\n'
} >"${EVIDENCE_DIR}/result.env"
printf '%s\n' "${RUN_ID}" >"${BACKUP_ROOT}/latest-run-id"
chmod 0600 "${EVIDENCE_DIR}/result.env" "${BACKUP_ROOT}/latest-run-id"

printf 'Q060_BASELINE_BACKUP_OK\n'
cat "${EVIDENCE_DIR}/result.env"
