#!/usr/bin/env bash

set -Eeuo pipefail

EXPECTED_HOSTNAME="sqjcnginx01"
EXPECTED_IPV4="10.2.203.102"
EXPECTED_OS="openEuler release 24.03 (LTS-SP1)"
BUNDLE_ROOT="/opt/zhct-deploy"
PACKAGE_ROOT="${BUNDLE_ROOT}/packages"
EVIDENCE_DIR="/var/backups/zhct-q040/20260722T203557+0800"
VIP_RE='10\.2\.203\.(115|116|117)'
CONSERVATIVE_INSTALL_BYTES=$((22 * 1024 * 1024 * 1024))
MIN_PROJECTED_FREE_BYTES=9448928051

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

capture() {
  local name=$1
  shift
  {
    printf '# captured_at=%s\n' "$(date --iso-8601=seconds)"
    printf '# command='
    printf '%q ' "$@"
    printf '\n'
    "$@" || true
  } >"${EVIDENCE_DIR}/${name}.txt" 2>&1
}

[[ "${EUID}" -eq 0 ]] || die "must run as root"
[[ "$(hostname -s)" == "${EXPECTED_HOSTNAME}" ]] || die "hostname 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"
[[ -d "${BUNDLE_ROOT}" ]] || die "bundle root is missing"
[[ -d "${PACKAGE_ROOT}/rpms" ]] || die "minimal RPM closure is missing"
[[ -s "${PACKAGE_ROOT}/rpms.sha256" ]] || die "RPM manifest is missing"
[[ -s "${EVIDENCE_DIR}/nginx-role-install-dry-run.log" ]] || die "role dry-run log is missing"
grep -Fq 'install completed for role=nginx dry_run=1' \
  "${EVIDENCE_DIR}/nginx-role-install-dry-run.log" || die "role dry-run did not complete"
grep -Eiq 'Transaction Summary|事务摘要' "${EVIDENCE_DIR}/dnf-minimal-closure-assumeno.log" || \
  die "offline DNF dry-run has no transaction summary"
if grep -Eiq '(^|[[:space:]])(Upgrading|Downgrading|Removing|Reinstalling|Obsoleting)(:|[[:space:]])|^[[:space:]]*(Upgrade|Downgrade|Remove|Reinstall|Obsolete)[[:space:]]+[0-9]+' \
  "${EVIDENCE_DIR}/dnf-minimal-closure-assumeno.log"; then
  die "offline DNF transaction contains an action other than Install"
fi

umask 077
capture filesystems-after-download df -hT
capture inodes-after-download df -hi
capture package-size du -sh "${PACKAGE_ROOT}"
capture q040-backup-size du -sh "${EVIDENCE_DIR}"
capture listening-ports-after-download ss -lntup
capture ipv4-after-download ip -4 -br addr
capture running-services-after-download systemctl list-units --type=service --state=running --all --no-pager
capture failed-units-after-download systemctl --failed --all --no-pager
capture rpm-target-after-download rpm -q nginx keepalived haproxy percona-orchestrator percona-orchestrator-cli percona-orchestrator-client redis
capture gpg-keys-after-download rpm -qa 'gpg-pubkey*'

(cd "${BUNDLE_ROOT}" && sha256sum -c roles/nginx/manifests/packages.sha256) \
  >"${EVIDENCE_DIR}/nginx-packages-sha256-check.txt"
(cd "${PACKAGE_ROOT}" && sha256sum -c rpms.sha256) \
  >"${EVIDENCE_DIR}/minimal-rpms-sha256-recheck.txt"

target_ports=$(awk -F'\t' 'NR>1 && $1 ~ /^[0-9]+$/ {ports[++count]=$1} END {for (i=1; i<=count; i++) printf "%s%s", (i>1 ? "|" : ""), ports[i]}' \
  "${BUNDLE_ROOT}/roles/nginx/manifests/ports.tsv")
[[ -n "${target_ports}" ]] || die "Nginx port manifest is empty"
target_listeners=$(ss -lntupH | grep -E ":(${target_ports})([[:space:]]|$)" || true)
target_processes=$(ps -eo pid,ppid,user,group,lstart,cmd --sort=pid | \
  grep -Ei '[n]ginx|[k]eepalived|[h]aproxy|[o]rchestrator|[r]edis-(server|sentinel)' || true)
target_units=$(find /etc/systemd/system /usr/lib/systemd/system -maxdepth 2 -type f \
  \( -name 'nginx.service' -o -name 'keepalived.service' -o -name 'haproxy.service' \
     -o -name 'orchestrator.service' -o -name 'sentinel5.service' -o -name 'sentinel7.service' \) \
  -print 2>/dev/null || true)
vip_addresses=$(ip -o -4 addr show | grep -E "${VIP_RE}" || true)
target_rpms=$(rpm -q nginx keepalived haproxy percona-orchestrator \
  percona-orchestrator-cli percona-orchestrator-client redis 2>/dev/null || true)
target_rpms=$(printf '%s\n' "${target_rpms}" | grep -Ev 'is not installed|未安装' || true)

[[ -z "${target_listeners}" ]] || die "target port is listening"
[[ -z "${target_processes}" ]] || die "target process is running"
[[ -z "${target_units}" ]] || die "target systemd unit was installed"
[[ -z "${vip_addresses}" ]] || die "target VIP is announced"
[[ -z "${target_rpms}" ]] || die "target RPM was installed"

root_available_bytes=$(df -B1 --output=avail / | tail -n 1 | tr -d ' ')
root_total_bytes=$(df -B1 --output=size / | tail -n 1 | tr -d ' ')
root_twenty_percent_bytes=$((root_total_bytes / 5))
if ((root_twenty_percent_bytes > MIN_PROJECTED_FREE_BYTES)); then
  minimum_required_bytes=${root_twenty_percent_bytes}
else
  minimum_required_bytes=${MIN_PROJECTED_FREE_BYTES}
fi
projected_free_bytes=$((root_available_bytes - CONSERVATIVE_INSTALL_BYTES))
((projected_free_bytes >= minimum_required_bytes)) || \
  die "projected root free space is below 8.8 GiB or 20 percent"

baseline_keys=$(mktemp)
current_keys=$(mktemp)
key_diff=$(mktemp)
trap 'rm -f "${baseline_keys}" "${current_keys}" "${key_diff}"' EXIT
sed '/^#/d;/^[[:space:]]*$/d' "${EVIDENCE_DIR}/baseline/rpm-keys.txt" | sort -u >"${baseline_keys}"
rpm -qa 'gpg-pubkey*' | sort -u >"${current_keys}"
diff -u "${baseline_keys}" "${current_keys}" >"${key_diff}" || true
unexpected_key_changes=$(grep -E '^[+-]' "${key_diff}" | \
  grep -Ev '^---|^\+\+\+|^\+gpg-pubkey-b675600b-' || true)
[[ -z "${unexpected_key_changes}" ]] || die "unexpected RPM keyring change during Q040"
cp "${key_diff}" "${EVIDENCE_DIR}/rpm-keyring-before-after.diff"

{
  printf 'captured_at=%s\n' "$(date --iso-8601=seconds)"
  printf 'root_available_bytes=%s\n' "${root_available_bytes}"
  printf 'root_total_bytes=%s\n' "${root_total_bytes}"
  printf 'conservative_install_bytes=%s\n' "${CONSERVATIVE_INSTALL_BYTES}"
  printf 'projected_free_bytes=%s\n' "${projected_free_bytes}"
  printf 'minimum_projected_free_bytes=%s\n' "${MIN_PROJECTED_FREE_BYTES}"
  printf 'minimum_required_bytes=%s\n' "${minimum_required_bytes}"
  printf 'space_check=PASS\n'
  printf 'nginx_package_asset_check=PASS\n'
  printf 'minimal_rpm_asset_check=PASS\n'
  printf 'dnf_transaction_actions=INSTALL_ONLY\n'
  printf 'rpm_keyring_change=EXPECTED_OPENEULER_B675600B_ONLY\n'
  printf 'target_listener_count=0\n'
  printf 'target_process_count=0\n'
  printf 'target_unit_count=0\n'
  printf 'target_rpm_count=0\n'
  printf 'vip_announcement_count=0\n'
  printf 'install_execution=NOT_PERFORMED\n'
  printf 'target_service_start=NOT_PERFORMED\n'
} >"${EVIDENCE_DIR}/post-download-check-result.env"

chmod 0600 "${EVIDENCE_DIR}"/*-after-download.txt \
  "${EVIDENCE_DIR}/package-size.txt" \
  "${EVIDENCE_DIR}/q040-backup-size.txt" \
  "${EVIDENCE_DIR}/nginx-packages-sha256-check.txt" \
  "${EVIDENCE_DIR}/minimal-rpms-sha256-recheck.txt" \
  "${EVIDENCE_DIR}/rpm-keyring-before-after.diff" \
  "${EVIDENCE_DIR}/post-download-check-result.env"

printf 'Q040_POST_DOWNLOAD_CHECK_OK\n'
cat "${EVIDENCE_DIR}/post-download-check-result.env"
