#!/bin/sh
set -u
umask 077

CONF="/etc/router-egress-emergency-refresh.conf"
RUNNER="/usr/local/sbin/router-egress-emergency-refresh.sh"
PLANNER="/usr/local/sbin/router-egress-hmn-plan-top5.sh"
CODE_TEST="/root/hmn/hmn-code-test.sh"

HOOK_INIT="/etc/init.d/router-egress-emergency-decision"
WATCHER_INIT="/etc/init.d/router-egress-health-repair"

fact() {
  printf '__FACT__ %s=%s\n' "$1" "$2"
}

json_block() {
  echo "__JSON_BEGIN__ $1"
  printf '%s\n' "$2"
  echo "__JSON_END__ $1"
}

bool_cmd() {
  if "$@" >/dev/null 2>&1; then
    printf true
  else
    printf false
  fi
}

for required in \
  "$CONF" \
  "$RUNNER" \
  "$PLANNER" \
  "$CODE_TEST"
do
  [ -e "$required" ] || {
    echo "__ERROR__ missing=$required"
    exit 21
  }
done

RAW="$(
  (
    . "$CONF"
    printf '%s' "${EMERGENCY_COMMIT_ENABLED:-UNSET}"
  )
)"

fact commit_raw "$RAW"
fact hook_running "$(bool_cmd "$HOOK_INIT" running)"
fact hook_enabled "$(bool_cmd "$HOOK_INIT" enabled)"
fact watcher_running "$(bool_cmd "$WATCHER_INIT" running)"
fact watcher_enabled "$(bool_cmd "$WATCHER_INIT" enabled)"

fact emergency_lock_present "$(
  bool_cmd test -e /var/lock/router-egress-emergency-refresh.lock
)"

fact refresh_lock_present "$(
  bool_cmd test -e /tmp/hmn-refresh-pool-safe.lock
)"

STRICT_ALL=true
HEALTHY_COUNT=0

for interface in vpn1 vpn2 vpn3 vpn4 vpn5; do
  if ping -I "$interface" -c 1 -W 3 1.1.1.1 >/dev/null 2>&1; then
    value=true
    HEALTHY_COUNT=$((HEALTHY_COUNT + 1))
  else
    value=false
    STRICT_ALL=false
  fi

  fact "strict.${interface}" "$value"
done

fact strict_all "$STRICT_ALL"
fact healthy_vpn_slots "$HEALTHY_COUNT"

ACTIVE_IFACE="$(
  ip route show table 200 2>/dev/null |
    awk '
      $1 == "default" {
        for (i = 1; i < NF; i++) {
          if (
            $i == "dev" &&
            $(i + 1) ~ /^vpn[0-9]+$/
          ) {
            print $(i + 1)
            exit
          }
        }
      }
    '
)"

[ -n "$ACTIVE_IFACE" ] ||
  ACTIVE_IFACE="UNRESOLVED"

fact active_bootstrap_iface "$ACTIVE_IFACE"

if [ "$ACTIVE_IFACE" != "UNRESOLVED" ] &&
   ping      -I "$ACTIVE_IFACE"      -c 1      -W 3      1.1.1.1      >/dev/null 2>&1
then
  ACTIVE_IFACE_STRICT=true
else
  ACTIVE_IFACE_STRICT=false
fi

fact active_bootstrap_strict "$ACTIVE_IFACE_STRICT"

TABLE200="$(
  ip route show table 200 2>&1 ||
  true
)"

echo "__BLOCK_BEGIN__ table_200"
printf '%s\n' "$TABLE200"
echo "__BLOCK_END__ table_200"

ROUTES_ALL=true

for table in 201 202 203 204 205; do
  if ip route show table "$table" 2>/dev/null |
    grep -q '^default '
  then
    value=true
  else
    value=false
    ROUTES_ALL=false
  fi

  fact "route.${table}" "$value"
done

fact routes_all "$ROUTES_ALL"

RUNNER_JSON="$("$RUNNER" --dry-run)"
PLANNER_JSON="$("$PLANNER")"

json_block runner "$RUNNER_JSON"
json_block planner "$PLANNER_JSON"

CODE_RAW="/tmp/step050m07c3-code-test.$$.raw"

set +e
"$CODE_TEST" > "$CODE_RAW" 2>&1
CODE_RC=$?
set -e

fact code_test_rc "$CODE_RC"
fact code_test_size "$(
  wc -c < "$CODE_RAW" |
    tr -d ' '
)"

CODE_SUMMARY="$(
  grep -Ei \
    'pass|success|valid|invalid|fail|error|http|serverlist|download' \
    "$CODE_RAW" |
    tail -n 50 ||
  true
)"

rm -f "$CODE_RAW"

echo "__BLOCK_BEGIN__ code_test_sanitized_summary"
printf '%s\n' "$CODE_SUMMARY" |
  sed \
    -e 's/[Cc][Oo][Dd][Ee]=[^ ]*/code=REDACTED/g' \
    -e 's/[Tt][Oo][Kk][Ee][Nn]=[^ ]*/token=REDACTED/g' \
    -e 's/[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd]=[^ ]*/password=REDACTED/g'
echo "__BLOCK_END__ code_test_sanitized_summary"

CODE_TEST_ACCEPTED=false
CODE_TEST_PARSER_SALVAGED=false

if [ "$CODE_RC" -eq 0 ]; then
  CODE_TEST_ACCEPTED=true

elif printf '%s\n' "$CODE_SUMMARY" |
     grep -Fq        'ERROR: не нашёл active VPN interface в table 200.' &&
     [ "$ACTIVE_IFACE" != "UNRESOLVED" ] &&
     [ "$ACTIVE_IFACE_STRICT" = true ]
then
  CODE_TEST_ACCEPTED=true
  CODE_TEST_PARSER_SALVAGED=true
fi

fact code_test_accepted "$CODE_TEST_ACCEPTED"
fact code_test_parser_salvaged "$CODE_TEST_PARSER_SALVAGED"
fact production_modified false

# Full refresh допустим при четырёх живых слотах:
# пятый слот должен быть восстановлен самим refresh/rebalance.
[ "$RAW" = "1" ]
[ "$HEALTHY_COUNT" -ge 4 ]
[ "$ACTIVE_IFACE" != "UNRESOLVED" ]
[ "$ACTIVE_IFACE_STRICT" = true ]
[ "$ROUTES_ALL" = true ]
[ "$CODE_TEST_ACCEPTED" = true ]
