#!/bin/sh
set -u
umask 077

RUNNER="/usr/local/sbin/router-egress-emergency-refresh.sh"
APPLY="/usr/local/sbin/router-egress-hmn-rebalance-top5-apply.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"

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

EXPECTED_TABLE200_HASH="a03a7a5738c031c280e4a3147e9f7c5feb4af524f4d7ea427871b3b6cafd4691"

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

block_file() {
  name="$1"
  path="$2"

  echo "__FILE_BEGIN__ $name path=$path"

  if [ -f "$path" ]; then
    cat "$path"
  else
    echo "__ERROR__ source_missing=$path"
  fi

  echo "__FILE_END__ $name"
}

block_text() {
  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
}

strict_all() {
  for interface in vpn1 vpn2 vpn3 vpn4 vpn5; do
    strict_iface "$interface" ||
      return 1
  done

  return 0
}

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
}

table200_hash() {
  ip route show table 200 2>/dev/null |
    sort |
    sha256sum |
    sed 's/[[:space:]].*$//'
}

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

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

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

echo "__TRACE__ stage=current_baseline"

fact read_only true
fact refresh_ran false
fact rebalance_ran false
fact direct_failopen_changed false
fact plan_changed false

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

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

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

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

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

fact baseline_strict_all "$(bool_cmd strict_all)"
fact baseline_routes_all "$(bool_cmd routes_all)"

TABLE200_HASH="$(table200_hash)"
fact table200_hash "$TABLE200_HASH"

if [ "$TABLE200_HASH" = "$EXPECTED_TABLE200_HASH" ]; then
  fact table200_baseline_match true
else
  fact table200_baseline_match false
fi

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 commit_raw "$(
  (
    . "$CONF"
    printf '%s' "${EMERGENCY_COMMIT_ENABLED:-UNSET}"
  )
)"

block_text table200 \
  ip route show table 200

block_text routes_201_205 sh -c '
  for table in 201 202 203 204 205; do
    echo "=== table $table ==="
    ip route show table "$table"
  done
'

block_text wireguard_endpoints sh -c '
  for interface in vpn1 vpn2 vpn3 vpn4 vpn5; do
    echo "=== $interface ==="
    wg show "$interface" endpoints 2>/dev/null || true
  done
'

block_text current_planner "$PLANNER"
block_text current_runner "$RUNNER" --dry-run

echo "__TRACE__ stage=exact_sources"

block_file runner "$RUNNER"
block_file rebalance_apply "$APPLY"
block_file planner "$PLANNER"

echo "__TRACE__ stage=adapter_discovery"

ADAPTER_PATHS="$(
  grep -Eo \
    '/[^"'"'"'[:space:]]*(adapter|replace|egress)[^"'"'"'[:space:]]*\.sh' \
    "$APPLY" |
  sort -u ||
  true
)"

echo "__BLOCK_BEGIN__ discovered_adapter_paths"
printf '%s\n' "$ADAPTER_PATHS"
echo "__BLOCK_END__ discovered_adapter_paths"

for adapter_path in $ADAPTER_PATHS; do
  case "$adapter_path" in
    /usr/local/*|/root/*|/etc/*)
      if [ -f "$adapter_path" ]; then
        echo "__ADAPTER_FILE_BEGIN__ path=$adapter_path"
        cat "$adapter_path"
        echo "__ADAPTER_FILE_END__ path=$adapter_path"
      fi
      ;;
  esac
done

echo "__TRACE__ stage=source_excerpts"

block_text runner_contract_excerpt sh -c "
  grep -nE \
    'REBALANCE_APPLY|refresh_ok_rebalance_ok|refresh_ok_rebalance_failed|commit|decision|apply_ok|exit' \
    '$RUNNER'
"

block_text apply_contract_excerpt sh -c "
  grep -nE \
    'commit_ok|commit_failed|slot_apply_failed|apply_ok|decision|adapter|rollback|strict|exit|return' \
    '$APPLY'
"

block_text planner_contract_excerpt sh -c "
  grep -nE \
    'changes_count|plan_ok|current|target|quarantine|exit|return' \
    '$PLANNER'
"

echo "__TRACE__ stage=failure_artifacts"

block_text recent_recovery_files sh -c '
  find /var/lib/router-egress-recovery \
    -maxdepth 5 \
    -type f \
    -mmin -240 \
    -exec ls -l {} \; \
    2>/dev/null |
  sort
'

block_text recent_tmp_files sh -c '
  find /tmp \
    -maxdepth 3 \
    -type f \
    -mmin -240 \
    \( \
      -name "*egress1*" \
      -o -name "*rebalance*" \
      -o -name "*step050m07c5*" \
      -o -name "*rollback*" \
    \) \
    -exec ls -l {} \; \
    2>/dev/null |
  sort
'

block_text recent_hmn_logs sh -c '
  find /root/hmn/logs \
    -maxdepth 2 \
    -type f \
    -mmin -240 \
    -exec ls -l {} \; \
    2>/dev/null |
  sort
'

block_text relevant_log_lines sh -c '
  grep -RniE \
    "slot_apply_failed_egress1|commit_failed|egress1|vpn1|strict.*fail|rollback" \
    /var/lib/router-egress-recovery \
    /root/hmn/logs \
    2>/dev/null |
  tail -n 500
'

block_text recent_small_artifact_contents sh -c '
  find /var/lib/router-egress-recovery /tmp \
    -maxdepth 5 \
    -type f \
    -mmin -240 \
    -size -128k \
    \( \
      -name "*egress1*" \
      -o -name "*rebalance*" \
      -o -name "*rollback-egress*" \
      -o -name "*step050m07c5*" \
    \) \
    2>/dev/null |
  sort |
  while IFS= read -r path; do
    echo "===== FILE $path ====="
    sed -n "1,500p" "$path" 2>/dev/null || true
  done
'

echo "__TRACE__ stage=storage"

block_text filesystem_usage df -Pk

block_text relevant_directory_sizes sh -c '
  du -sk \
    /root/hmn/cache \
    /root/hmn/configs/awg1 \
    /root/hmn/runs \
    /root/hmn/backups \
    /var/lib/router-egress-recovery \
    /tmp/step050m07c5-* \
    2>/dev/null |
  sort -n
'

block_text latest_links sh -c '
  ls -ld \
    /root/hmn/configs/awg1/latest \
    /root/hmn/cache/*latest* \
    2>/dev/null || true

  readlink -f \
    /root/hmn/configs/awg1/latest \
    2>/dev/null || true
'

echo "__TRACE__ stage=complete"

[ "$(bool_cmd strict_all)" = true ] || exit 31
[ "$(bool_cmd routes_all)" = true ] || exit 32
[ "$(table200_hash)" = "$EXPECTED_TABLE200_HASH" ] || exit 33

exit 0
