#!/usr/bin/env bash
echo 'CANCELLED_DO_NOT_EXECUTE: superseded by fixed-IP Q200 policy' >&2
exit 1
set -Eeuo pipefail
umask 077

BEGIN_MARK='# BEGIN SANQUAN_Q200_MANAGED'
END_MARK='# END SANQUAN_Q200_MANAGED'
HOSTS_FILE=/etc/hosts
BACKUP_ROOT=/var/backups/zhct-q200-mysql-hosts
ACTION=${1:-run}
CHANGED=0
BACKUP=
TEMP=

now() {
  date --iso-8601=seconds 2>/dev/null || date -Iseconds 2>/dev/null || date '+%Y-%m-%dT%H:%M:%S%z'
}

finish() {
  local rc=$?
  trap - EXIT
  [[ -z "$TEMP" || ! -e "$TEMP" ]] || rm -f -- "$TEMP"
  printf 'finished_at=%s\nQ200_MYSQL_HOSTS_RC=%s\n' "$(now)" "$rc"
  if [[ "$rc" -eq 0 ]]; then
    echo 'Q200_MYSQL_HOSTS_ROLLBACK_STATE=NOT_REQUIRED'
  elif [[ "$CHANGED" -eq 0 ]]; then
    echo 'Q200_MYSQL_HOSTS_ROLLBACK_STATE=NO_WRITE_PERFORMED'
  fi
  echo 'END Q200_MYSQL_HOSTS_MANAGED_BLOCK'
  exit "$rc"
}
trap finish EXIT

static_validate() {
  bash -n "$0"
  command -v awk cat chcon chmod chown cp date getent grep hostname id install ip mktemp mv restorecon sha256sum stat tail tee wc >/dev/null
  grep -Fq "$BEGIN_MARK" "$0"
  grep -Fq "$END_MARK" "$0"
  echo Q200_MYSQL_HOSTS_STATIC_VALIDATE_PASS
}

if [[ "$ACTION" == --static-validate ]]; then
  static_validate
  exit 0
fi
[[ "$ACTION" == run ]] || { echo 'ERROR: usage: script --static-validate|run'; exit 2; }
[[ $(id -u) -eq 0 ]] || { echo 'ERROR: root is required'; exit 1; }

actual_host=$(hostname -s)
case "$actual_host" in
  sqjcDB01) expected_ip=10.2.208.106; node=mysql01 ;;
  sqjcDB02) expected_ip=10.2.208.107; node=mysql02 ;;
  *) echo "ERROR: wrong hostname: $actual_host"; exit 1 ;;
esac
ip -o -4 addr show scope global | awk -v ip="$expected_ip" '{split($4,a,"/"); if(a[1]==ip) ok=1} END{exit !ok}' || {
  echo "ERROR: expected IP not present: $expected_ip"
  exit 1
}

run_id="q200-hosts-${node}-$(date '+%Y%m%dT%H%M%S%z')"
evidence="$BACKUP_ROOT/$run_id"
install -d -m 0700 -o root -g root "$evidence"
exec > >(tee -a "$evidence/operator.log") 2>&1

echo 'BEGIN Q200_MYSQL_HOSTS_MANAGED_BLOCK'
printf 'started_at=%s\nnode=%s\ntarget_hostname=%s\ntarget_ip=%s\nhosts_file=%s\n' \
  "$(now)" "$node" "$actual_host" "$expected_ip" "$HOSTS_FILE"
echo 'Q200_MYSQL_HOSTS_IDENTITY_GATE=PASS'

[[ -f "$HOSTS_FILE" && ! -L "$HOSTS_FILE" ]] || { echo 'ERROR: /etc/hosts is not a regular non-symlink file'; exit 1; }
begin_count=$(grep -Fxc "$BEGIN_MARK" "$HOSTS_FILE" || true)
end_count=$(grep -Fxc "$END_MARK" "$HOSTS_FILE" || true)
[[ "$begin_count" -le 1 && "$end_count" -le 1 && "$begin_count" -eq "$end_count" ]] || {
  echo "ERROR: managed block marker count invalid: begin=$begin_count end=$end_count"
  exit 1
}
if [[ "$begin_count" -eq 1 ]]; then
  awk -v b="$BEGIN_MARK" -v e="$END_MARK" '
    $0==b {if(inblock) exit 2; inblock=1; seenb=1; next}
    $0==e {if(!inblock) exit 3; inblock=0; seene=1; next}
    END {if(inblock || !seenb || !seene) exit 4}
  ' "$HOSTS_FILE" || { echo 'ERROR: malformed managed block'; exit 1; }
fi

mapping=$(mktemp /var/tmp/q200-mysql-hosts-map.XXXXXX)
TEMP=$mapping
cat >"$mapping" <<'MAP'
10.2.203.102 sqjcnginx01
10.2.203.103 sqjcnginx02
10.2.203.104 sqjcapp01
10.2.203.105 sqjcapp02
10.2.208.106 sqjcDB01
10.2.208.107 sqjcDB02
10.2.203.108 sqjcmqtt01
10.2.203.109 sqjcmqtt02
10.2.203.110 sqjcmqtt03
10.2.203.112 sqjcredis01
10.2.203.113 sqjcredis02
MAP

if ! awk -v b="$BEGIN_MARK" -v e="$END_MARK" '
  NR==FNR {want[$2]=$1; next}
  $0==b {managed=1; next}
  $0==e {managed=0; next}
  managed || /^[[:space:]]*#/ || NF<2 {next}
  {
    ip=$1
    for(i=2;i<=NF;i++) {
      name=$i
      sub(/#.*/,"",name)
      if(name in want && ip != want[name]) {
        printf "CONFLICT hostname=%s expected_ip=%s existing_ip=%s line=%d\n", name,want[name],ip,FNR
        bad=1
      }
    }
  }
  END {exit bad}
  ' "$mapping" "$HOSTS_FILE"; then
  echo 'ERROR: unmanaged hostname/IP conflict detected; no write performed'
  exit 1
fi
echo Q200_MYSQL_HOSTS_CONFLICT_GATE=PASS

BACKUP="$evidence/hosts.before"
cp -a -- "$HOSTS_FILE" "$BACKUP"
chmod 0600 "$BACKUP"
sha256sum "$BACKUP" | sed 's#  .*#  hosts.before#'

mode=$(stat -c '%a' "$HOSTS_FILE")
TEMP=$(mktemp /etc/hosts.q200.XXXXXX)
awk -v b="$BEGIN_MARK" -v e="$END_MARK" '
  $0==b {managed=1; next}
  $0==e {managed=0; next}
  !managed {print}
' "$HOSTS_FILE" >"$TEMP"
[[ ! -s "$TEMP" || $(tail -c 1 "$TEMP" | wc -l) -eq 1 ]] || printf '\n' >>"$TEMP"
{
  echo "$BEGIN_MARK"
  cat "$mapping"
  echo "$END_MARK"
} >>"$TEMP"
chown root:root "$TEMP"
chmod "$mode" "$TEMP"
chcon --reference="$HOSTS_FILE" "$TEMP" 2>/dev/null || true
mv -f -- "$TEMP" "$HOSTS_FILE"
TEMP=$mapping
restorecon "$HOSTS_FILE" >/dev/null 2>&1 || true
CHANGED=1

rollback() {
  cp -a -- "$BACKUP" "$HOSTS_FILE"
  restorecon "$HOSTS_FILE" >/dev/null 2>&1 || true
  CHANGED=0
  echo Q200_MYSQL_HOSTS_AUTOMATIC_ROLLBACK=PASS
}

verify_failed=0
while read -r expected name; do
  resolved=$(getent ahostsv4 "$name" | awk 'NR==1{print $1}')
  printf 'HOST_RESOLUTION name=%s expected=%s actual=%s\n' "$name" "$expected" "${resolved:-ABSENT}"
  [[ "$resolved" == "$expected" ]] || verify_failed=1
done <"$mapping"
if [[ "$verify_failed" -ne 0 ]]; then
  rollback
  echo 'ERROR: post-write resolution verification failed; backup restored'
  exit 1
fi

[[ $(grep -Fxc "$BEGIN_MARK" "$HOSTS_FILE") -eq 1 && $(grep -Fxc "$END_MARK" "$HOSTS_FILE") -eq 1 ]] || {
  rollback
  echo 'ERROR: post-write managed block marker verification failed; backup restored'
  exit 1
}
stat -c 'mode=%a owner=%U:%G label=%C path=%n' "$HOSTS_FILE"
echo Q200_MYSQL_HOSTS_MANAGED_BLOCK_PASS
echo 'Q200_DNS_ROUTE_FIREWALL_SERVICES=NOT_MODIFIED'
echo "backup=$BACKUP"
