#!/usr/bin/env bash
echo Q200_APP01_HOSTS_SCRIPT=CANCELLED_DO_NOT_EXECUTE >&2
exit 125
set -Eeuo pipefail
umask 077

EXPECTED_HOST=sqjcapp01
EXPECTED_IP=10.2.203.104
HOSTS_FILE=/etc/hosts
BEGIN_MARK='# BEGIN SANQUAN_Q200_MANAGED'
END_MARK='# END SANQUAN_Q200_MANAGED'
MUTATED=0
BACKUP=''
TMP=''

finish() {
  local rc=$? rollback=NOT_REQUIRED
  set +e
  if [[ $rc -ne 0 && $MUTATED -eq 1 && -n $BACKUP && -f $BACKUP ]]; then
    rollback_tmp=$(mktemp /etc/.hosts.q200.rollback.XXXXXX)
    cp -a "$BACKUP" "$rollback_tmp" && mv -f "$rollback_tmp" "$HOSTS_FILE"
    rollback_rc=$?
    [[ $rollback_rc -eq 0 ]] && rollback=PASS || rollback=FAIL
    getent ahostsv4 "$EXPECTED_HOST" >/dev/null 2>&1 || true
  fi
  [[ -z $TMP || ! -e $TMP ]] || rm -f "$TMP"
  echo Q200_APP01_HOSTS_ROLLBACK_STATE=$rollback
  echo Q200_APP01_HOSTS_RC=$rc
  [[ $rc -eq 0 ]] && echo Q200_APP01_HOSTS_RESULT=PASS || echo Q200_APP01_HOSTS_RESULT=BLOCKED
  echo Q200_APP01_HOSTS_END
  exit "$rc"
}
trap finish EXIT

echo Q200_APP01_HOSTS_BEGIN

if [[ ${1:-} == --static-validate && $# -eq 1 ]]; then
  echo Q200_APP01_HOSTS_STATIC_VALIDATE=PASS
  exit 0
fi
[[ ${1:-} == --execute && $# -eq 1 ]] || { echo 'ERROR: use --execute' >&2; exit 2; }
[[ $(id -u) -eq 0 ]] || { echo 'ERROR: root required' >&2; exit 3; }
actual_host=$(hostname -s)
[[ ${actual_host,,} == ${EXPECTED_HOST,,} ]] || { echo "ERROR: hostname expected=$EXPECTED_HOST actual=$actual_host" >&2; exit 4; }
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 missing: $EXPECTED_IP" >&2; exit 5;
}
[[ -f $HOSTS_FILE && ! -L $HOSTS_FILE ]] || { echo 'ERROR: /etc/hosts unsafe' >&2; exit 6; }
[[ $(stat -c '%U:%G' "$HOSTS_FILE") == root:root ]] || { echo 'ERROR: /etc/hosts owner unsafe' >&2; exit 7; }

run_id="q200-app01-hosts-$(date '+%Y%m%dT%H%M%S%z')"
evidence_dir="/var/backups/zhct-q200-app/hosts/$run_id"
install -d -m 0700 -o root -g root "$evidence_dir"
log="$evidence_dir/operator.log"
exec > >(tee -a "$log") 2>&1
echo "Q200_APP01_HOSTS_RUN_ID=$run_id"
echo "Q200_APP01_HOSTS_TARGET=$EXPECTED_HOST/$EXPECTED_IP"
echo "Q200_APP01_HOSTS_INPUT=$HOSTS_FILE"

begin_count=$(grep -Fxc "$BEGIN_MARK" "$HOSTS_FILE" || true)
end_count=$(grep -Fxc "$END_MARK" "$HOSTS_FILE" || true)
[[ $begin_count -eq $end_count && $begin_count -le 1 ]] || {
  echo "ERROR: managed block count begin=$begin_count end=$end_count" >&2; exit 8;
}

base="$evidence_dir/hosts.nonmanaged"
awk -v b="$BEGIN_MARK" -v e="$END_MARK" '
  $0==b {inside=1; next}
  $0==e {inside=0; next}
  !inside {print}
' "$HOSTS_FILE" >"$base"

conflict=0
while read -r ip names; do
  [[ -n ${ip:-} ]] || continue
  case "$ip" in \#*) continue ;; esac
  names=${names%%#*}
  for name in $names; do
    case "$ip:$name" in
      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) ;;
      10.2.203.102:*|10.2.203.103:*|10.2.203.104:*|10.2.203.105:*|10.2.208.106:*|10.2.208.107:*|10.2.203.108:*|10.2.203.109:*|10.2.203.110:*|10.2.203.112:*|10.2.203.113:*) echo "CONFLICT ip=$ip hostname=$name"; conflict=1 ;;
      *:sqjcnginx01|*:sqjcnginx02|*:sqjcapp01|*:sqjcapp02|*:sqjcDB01|*:sqjcDB02|*:sqjcmqtt01|*:sqjcmqtt02|*:sqjcmqtt03|*:sqjcredis01|*:sqjcredis02) echo "CONFLICT ip=$ip hostname=$name"; conflict=1 ;;
    esac
  done
done <"$base"
[[ $conflict -eq 0 ]] || { echo 'ERROR: unmanaged hosts conflict detected' >&2; exit 9; }

BACKUP="$evidence_dir/hosts.before"
cp -a "$HOSTS_FILE" "$BACKUP"
sha256sum "$BACKUP"
orig_mode=$(stat -c '%a' "$HOSTS_FILE")
orig_context=$(stat -c '%C' "$HOSTS_FILE" 2>/dev/null || true)

TMP=$(mktemp /etc/.hosts.q200.XXXXXX)
cp -a "$HOSTS_FILE" "$TMP"
{
  cat "$base"
  tail -c 1 "$base" | read -r _ || echo
  echo "$BEGIN_MARK"
  cat <<'EOF'
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
EOF
  echo "$END_MARK"
} >"$TMP"
chown root:root "$TMP"
chmod "$orig_mode" "$TMP"
if command -v chcon >/dev/null 2>&1 && [[ -n $orig_context && $orig_context != '?' ]]; then chcon "$orig_context" "$TMP"; fi
mv -f "$TMP" "$HOSTS_FILE"
TMP=''
MUTATED=1

[[ $(stat -c '%U:%G' "$HOSTS_FILE") == root:root ]]
[[ $(stat -c '%a' "$HOSTS_FILE") == "$orig_mode" ]]
[[ $(grep -Fxc "$BEGIN_MARK" "$HOSTS_FILE") -eq 1 && $(grep -Fxc "$END_MARK" "$HOSTS_FILE") -eq 1 ]]

while read -r ip name; do
  resolved=$(getent ahostsv4 "$name" | awk 'NR==1{print $1}')
  echo "GETENT name=$name expected=$ip actual=${resolved:-ABSENT}"
  [[ $resolved == "$ip" ]]
done <<'EOF'
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
EOF

echo "Q200_APP01_HOSTS_BACKUP=$BACKUP"
echo Q200_APP01_HOSTS_MANAGED_BLOCK=PASS
echo Q200_APP01_HOSTS_DURABLE_CHANGE=ETC_HOSTS_ONLY
echo Q200_APP01_HOSTS_OTHER_CONFIG_CHANGE=NONE
