#!/bin/sh
set -u
umask 077

RUNNER="/usr/local/sbin/router-egress-emergency-refresh.sh"
PLANNER="/usr/local/sbin/router-egress-hmn-plan-top5.sh"
HELPER="/usr/local/lib/router-egress-recovery-state.sh"
CONF="/etc/router-egress-emergency-refresh.conf"
POOL="/root/hmn/cache/ok-awg1-strict-foreign-latest.tsv"

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

CRON_LOG="/root/hmn/logs/hmn-refresh-pool-cron.log"
EMERGENCY_LOG="/var/log/router-egress-emergency-refresh.log"

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

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

block_file_tail() {
  name="$1"
  path="$2"
  lines="$3"

  echo "__BLOCK_BEGIN__ $name"

  if [ -f "$path" ]; then
    tail -n "$lines" "$path" 2>/dev/null || true
  else
    echo "FILE_NOT_PRESENT=$path"
  fi

  echo "__BLOCK_END__ $name"
}

block_cmd() {
  name="$1"
  shift

  echo "__BLOCK_BEGIN__ $name"
  "$@" 2>&1 || true
  echo "__BLOCK_END__ $name"
}

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

strict_iface() {
  interface="$1"
  attempt=1

  while [ "$attempt" -le 3 ]; do
    if ping \
      -I "$interface" \
      -c 1 \
      -W 3 \
      1.1.1.1 \
      >/dev/null 2>&1
    then
      return 0
    fi

    attempt=$((attempt + 1))
    sleep 1
  done

  return 1
}

routes_all() {
  for table in 201 202 203 204 205; do
    ip route show table "$table" 2>/dev/null |
      grep -q '^default ' ||
      return 1
  done

  return 0
}

state_value() {
  key="$1"
  fallback="$2"

  (
    unset REG_STATE_DIR
    . "$HELPER"
    reg_get_state "$key" "$fallback"
  )
}

repair_counter() {
  (
    unset REG_STATE_DIR
    . "$HELPER"
    reg_daily_repair_get
  )
}

for required in \
  "$RUNNER" \
  "$PLANNER" \
  "$HELPER" \
  "$CONF" \
  "$POOL"
do
  [ -f "$required" ] || {
    echo "__ERROR__ source_missing=$required"
    exit 21
  }
done

echo "__TRACE__ stage=clock_and_schedule"

fact snapshot_epoch "$(date +%s)"
fact vm101_local_time "$(date '+%Y-%m-%dT%H:%M:%S%z')"
fact vm101_utc_time "$(date -u '+%Y-%m-%dT%H:%M:%SZ')"

CRON_LINE="$(
  grep -E \
    '^[[:space:]]*20[[:space:]]+4[[:space:]]+\*[[:space:]]+\*[[:space:]]+\*[[:space:]]+' \
    /etc/crontabs/root \
    2>/dev/null |
  grep -F '/root/hmn/hmn-refresh-pool-safe.sh' |
  head -n1 ||
  true
)"

fact cron_0420_found "$(
  if [ -n "$CRON_LINE" ]; then
    echo true
  else
    echo false
  fi
)"

echo "__BLOCK_BEGIN__ exact_cron_line"
printf '%s\n' "$CRON_LINE"
echo "__BLOCK_END__ exact_cron_line"

echo "__TRACE__ stage=health"

HEALTHY_COUNT=0

for interface in vpn1 vpn2 vpn3 vpn4 vpn5; do
  if strict_iface "$interface"; then
    value=true
    HEALTHY_COUNT=$((HEALTHY_COUNT + 1))
  else
    value=false
  fi

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

fact healthy_vpn_slots "$HEALTHY_COUNT"

fact strict_all "$(
  if [ "$HEALTHY_COUNT" -eq 5 ]; then
    echo true
  else
    echo false
  fi
)"

fact routes_all "$(bool_cmd routes_all)"

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
)"

echo "__TRACE__ stage=planner_and_runtime"

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

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

AMNEZIAWG_BIN="$(
  command -v amneziawg 2>/dev/null ||
  true
)"

fact amneziawg_binary "$(
  if [ -n "$AMNEZIAWG_BIN" ]; then
    printf '%s' "$AMNEZIAWG_BIN"
  else
    printf 'NOT_FOUND'
  fi
)"

if [ -n "$AMNEZIAWG_BIN" ]; then
  echo "__BLOCK_BEGIN__ amneziawg_all_dump"
  "$AMNEZIAWG_BIN" show all dump 2>&1 || true
  echo "__BLOCK_END__ amneziawg_all_dump"

  echo "__BLOCK_BEGIN__ amneziawg_interfaces"

  for interface in vpn1 vpn2 vpn3 vpn4 vpn5; do
    echo "===== $interface ====="
    "$AMNEZIAWG_BIN" show "$interface" 2>&1 || true
  done

  echo "__BLOCK_END__ amneziawg_interfaces"
fi

block_cmd routes_200_205 sh -c '
  for table in 200 201 202 203 204 205; do
    echo "===== table $table ====="
    ip route show table "$table" 2>/dev/null || true
  done
'

echo "__TRACE__ stage=state_and_pool"

fact state_mode "$(state_value mode UNKNOWN)"
fact state_status "$(
  state_value last_emergency_refresh_status UNKNOWN
)"
fact state_epoch "$(
  state_value last_emergency_refresh_epoch 0
)"
fact repair_counter "$(repair_counter)"

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

fact pool_sha256 "$(
  sha256sum "$POOL" |
    sed 's/[[:space:]].*$//'
)"

fact pool_rows "$(
  sed '1d' "$POOL" |
    grep -c . ||
  true
)"

fact pool_mtime_epoch "$(date -r "$POOL" +%s)"

LATEST_GENERATION="$(
  readlink -f /root/hmn/configs/awg1/latest 2>/dev/null ||
  true
)"

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

fact latest_generation "$LATEST_GENERATION"

echo "__TRACE__ stage=logs"

block_file_tail cron_log_tail "$CRON_LOG" 1200
block_file_tail emergency_log_tail "$EMERGENCY_LOG" 1200

block_cmd recent_hmn_files sh -c '
  find /root/hmn \
    -maxdepth 4 \
    -type f \
    -mmin -720 \
    -exec ls -l {} \; \
    2>/dev/null |
  sort
'

block_cmd filesystem_usage df -Pk

fact read_only true
fact refresh_ran false
fact rebalance_ran false
fact network_changed false
fact services_changed false
fact state_changed false
fact timer_changed false
fact plan_changed false
fact direct_failopen_changed false

echo "__TRACE__ stage=complete"
exit 0
