#!/usr/bin/env bash
set +e
set +u
umask 077

STEP="STEP_050M07R09A_AUDIT_PREINSTALL_HEALTH_STOP"

TOKEN="e94a0859747d7b96f29c7fdafc2d0351ba603bb0a7e9e5a4"
ROOT="/opt/router-ops"
PUBROOT="$ROOT/public/r/$TOKEN"
PUBLIC_BASE="https://helena-background-beam-harry.trycloudflare.com/r/$TOKEN"

EXPECTED_SOURCE="bb047e820196c4c5cb263499ed890c782190293257a2033568015c6b19230682"
EXPECTED_RUNTIME="1fd8d8b9258f7ca1d711323b7652f0b46991e1d17346b59e1d8ff5d71ba471d9"

TS="$(date -u +%Y%m%d-%H%M%S)"
SLUG="${TS}_step050m07r09a_audit_preinstall_health_stop"
REPORT_DIR="$PUBROOT/$SLUG"

TRYCF_REPORT="$PUBLIC_BASE/$SLUG/"
REPORT_TXT="${TRYCF_REPORT}report.txt"
FACTS_JSON="${TRYCF_REPORT}facts.json"

mkdir -p "$REPORT_DIR"
cp -a "$0" "$REPORT_DIR/step.sh"
chmod 600 "$REPORT_DIR/step.sh"

REMOTE_OUT="$REPORT_DIR/vm101-audit.env"
SSH_ERR="$REPORT_DIR/ssh.stderr"

ssh -T \
  -o BatchMode=yes \
  -o ConnectTimeout=10 \
  pve-mgts \
  "ssh -T \
    -o BatchMode=yes \
    -o ConnectTimeout=10 \
    -o StrictHostKeyChecking=yes \
    -i /root/.ssh/pve_to_openwrt_mgts_ed25519 \
    root@10.71.100.2 \
    'sh -s -- $EXPECTED_SOURCE $EXPECTED_RUNTIME'" \
  >"$REMOTE_OUT" 2>"$SSH_ERR" <<'REMOTE'
set -u

EXPECTED_SOURCE="$1"
EXPECTED_RUNTIME="$2"

TARGET="/root/hmn/hmn-refresh-pool-safe.sh"
LIB="/usr/local/lib/router-egress-vm101-runtime.sh"

hash_file() {
  sha256sum "$1" 2>/dev/null |
    awk '{print $1}'
}

TARGET_HASH="$(hash_file "$TARGET")"

if [ -e "$LIB" ]; then
  LIB_STATE="PRESENT"
  LIB_HASH="$(hash_file "$LIB")"
else
  LIB_STATE="ABSENT"
  LIB_HASH="ABSENT"
fi

echo "host=$(cat /proc/sys/kernel/hostname 2>/dev/null)"
echo "target_sha256=$TARGET_HASH"
echo "target_is_original=$(
  [ "$TARGET_HASH" = "$EXPECTED_SOURCE" ] &&
    echo true || echo false
)"
echo "runtime_library_state=$LIB_STATE"
echo "runtime_library_sha256=$LIB_HASH"
echo "runtime_library_is_absent=$(
  [ "$LIB_STATE" = "ABSENT" ] &&
    echo true || echo false
)"

pass=1

while [ "$pass" -le 3 ]; do
  healthy=0
  routes=0
  slot=1

  echo "pass_${pass}_begin=true"

  while [ "$slot" -le 5 ]; do
    iface="vpn$slot"
    table="$((200 + slot))"

    endpoint="$(
      /usr/bin/amneziawg show "$iface" dump 2>/dev/null |
        awk 'NR == 2 {print $3; exit}'
    )"

    [ -n "$endpoint" ] || endpoint="NONE"

    if ip route show table "$table" 2>/dev/null |
       grep -E "^default .*dev ${iface}([[:space:]]|$)" \
       >/dev/null
    then
      route_ok=true
      routes="$((routes + 1))"
    else
      route_ok=false
    fi

    ping1_rc=1
    ping2_rc=1
    ping3_rc=1

    ping -I "$iface" -c 1 -W 2 1.1.1.1 \
      >/dev/null 2>&1
    ping1_rc=$?

    ping -I "$iface" -c 1 -W 2 8.8.8.8 \
      >/dev/null 2>&1
    ping2_rc=$?

    ping -I "$iface" -c 1 -W 2 9.9.9.9 \
      >/dev/null 2>&1
    ping3_rc=$?

    if [ "$ping1_rc" -eq 0 ] ||
       [ "$ping2_rc" -eq 0 ] ||
       [ "$ping3_rc" -eq 0 ]
    then
      strict_ok=true
      healthy="$((healthy + 1))"
    else
      strict_ok=false
    fi

    echo "pass_${pass}_${iface}_endpoint=$endpoint"
    echo "pass_${pass}_${iface}_route_ok=$route_ok"
    echo "pass_${pass}_${iface}_ping_1_1_1_1_rc=$ping1_rc"
    echo "pass_${pass}_${iface}_ping_8_8_8_8_rc=$ping2_rc"
    echo "pass_${pass}_${iface}_ping_9_9_9_9_rc=$ping3_rc"
    echo "pass_${pass}_${iface}_healthy=$strict_ok"

    slot="$((slot + 1))"
  done

  echo "pass_${pass}_route_count=$routes"
  echo "pass_${pass}_healthy_count=$healthy"
  echo "pass_${pass}_end=true"

  [ "$pass" -lt 3 ] && sleep 2
  pass="$((pass + 1))"
done

echo "vm101_modified=false"
echo "installation_performed=false"
echo "refresh_ran=false"
echo "rebalance_ran=false"
REMOTE

SSH_RC=$?

if [ "$SSH_RC" -eq 0 ]; then
  MAX_HEALTHY="$(
    sed -n \
      's/^pass_[123]_healthy_count=//p' \
      "$REMOTE_OUT" |
    sort -nr |
    head -n1
  )"

  MIN_HEALTHY="$(
    sed -n \
      's/^pass_[123]_healthy_count=//p' \
      "$REMOTE_OUT" |
    sort -n |
    head -n1
  )"

  TARGET_ORIGINAL="$(
    sed -n 's/^target_is_original=//p' \
      "$REMOTE_OUT" |
    tail -n1
  )"

  LIB_ABSENT="$(
    sed -n 's/^runtime_library_is_absent=//p' \
      "$REMOTE_OUT" |
    tail -n1
  )"

  if [ "$TARGET_ORIGINAL" != "true" ] ||
     [ "$LIB_ABSENT" != "true" ]
  then
    DECISION="STOP_${STEP}_UNEXPECTED_LIVE_CHANGE"
    CLASSIFICATION="UNEXPECTED_LIVE_CHANGE"

  elif [ "$MAX_HEALTHY" = "5" ]; then
    DECISION="PASS_${STEP}"
    CLASSIFICATION="TRANSIENT_OR_SINGLE_PROBE_FAILURE"

  else
    DECISION="STOP_${STEP}_EGRESS_HEALTH_NOT_RECOVERED"
    CLASSIFICATION="CURRENT_EGRESS_HEALTH_FAILURE"
  fi
else
  MAX_HEALTHY=0
  MIN_HEALTHY=0
  TARGET_ORIGINAL="UNKNOWN"
  LIB_ABSENT="UNKNOWN"
  DECISION="STOP_${STEP}_SSH_FAILED"
  CLASSIFICATION="SSH_TRANSPORT_FAILURE"
fi

cat > "$REPORT_DIR/report.txt" <<EOF
=== ${STEP} RESULT ===
step=${STEP}
decision=${DECISION}
classification=${CLASSIFICATION}
ssh_rc=${SSH_RC}

r09_install_state:
  target_is_original=${TARGET_ORIGINAL}
  runtime_library_is_absent=${LIB_ABSENT}
  installation_performed=false
  rollback_required=false

health:
  min_healthy_count=${MIN_HEALTHY}
  max_healthy_count=${MAX_HEALTHY}
  passes=3
  probes_per_interface=3

safety:
  read_only=true
  vm101_modified=false
  installation_performed=false
  refresh_ran=false
  rebalance_ran=false

next_step=$(
  if [ "$MAX_HEALTHY" = "5" ] &&
     [ "$TARGET_ORIGINAL" = "true" ] &&
     [ "$LIB_ABSENT" = "true" ]
  then
    echo "RETRY_INSTALL_WITH_THREE_PROBE_HEALTH_GATE"
  else
    echo "AUDIT_CURRENT_VPN_EGRESS_HEALTH"
  fi
)

TRYCF_REPORT=${TRYCF_REPORT}
REPORT_TXT=${REPORT_TXT}
FACTS_JSON=${FACTS_JSON}
EOF

python3 - \
  "$REPORT_DIR/facts.json" \
  "$REMOTE_OUT" \
  "$STEP" \
  "$DECISION" \
  "$CLASSIFICATION" \
  "$SSH_RC" \
  "$MIN_HEALTHY" \
  "$MAX_HEALTHY" \
  "$TARGET_ORIGINAL" \
  "$LIB_ABSENT" \
  "$TRYCF_REPORT" \
  "$REPORT_TXT" \
  "$FACTS_JSON" <<'PY'
import json
import sys
from pathlib import Path

(
    output,
    remote_path,
    step,
    decision,
    classification,
    ssh_rc,
    minimum,
    maximum,
    target_original,
    library_absent,
    report,
    report_txt,
    facts,
) = sys.argv[1:]

remote = {}

path = Path(remote_path)

if path.is_file():
    for line in path.read_text(
        encoding="utf-8",
        errors="replace",
    ).splitlines():
        if "=" in line:
            key, value = line.split("=", 1)
            remote[key] = value

data = {
    "schema": "router-step-facts-v1",
    "step": step,
    "assessment": {
        "decision": decision,
        "classification": classification,
        "all_ok": decision.startswith("PASS_"),
    },
    "r09_install_state": {
        "target_is_original":
            target_original == "true",
        "runtime_library_is_absent":
            library_absent == "true",
        "installation_performed": False,
        "rollback_required": False,
    },
    "health": {
        "passes": 3,
        "probes_per_interface": 3,
        "min_healthy_count": int(minimum),
        "max_healthy_count": int(maximum),
        "remote": remote,
    },
    "transport": {
        "ssh_rc": int(ssh_rc),
    },
    "safety": {
        "read_only": True,
        "vm101_modified": False,
        "installation_performed": False,
        "refresh_ran": False,
        "rebalance_ran": False,
    },
    "next_step": (
        "RETRY_INSTALL_WITH_THREE_PROBE_HEALTH_GATE"
        if (
            maximum == "5"
            and target_original == "true"
            and library_absent == "true"
        )
        else "AUDIT_CURRENT_VPN_EGRESS_HEALTH"
    ),
    "publish": {
        "trycf_report": report,
        "report_txt": report_txt,
        "facts_json": facts,
    },
}

Path(output).write_text(
    json.dumps(
        data,
        ensure_ascii=False,
        indent=2,
    ) + "\n",
    encoding="utf-8",
)
PY

cat > "$REPORT_DIR/index.html" <<EOF
<!doctype html>
<html lang="ru">
<head><meta charset="utf-8"><title>${STEP}</title></head>
<body style="font-family:system-ui;max-width:1000px;margin:40px auto">
<h1>${STEP}</h1>
<ul>
<li><a href="report.txt">report.txt</a></li>
<li><a href="facts.json">facts.json</a></li>
<li><a href="vm101-audit.env">vm101-audit.env</a></li>
<li><a href="ssh.stderr">ssh.stderr</a></li>
<li><a href="step.sh">step.sh</a></li>
</ul>
</body>
</html>
EOF

find "$REPORT_DIR" \
  -type f \
  ! -name SHA256SUMS \
  -print0 |
sort -z |
xargs -0 sha256sum \
  > "$REPORT_DIR/SHA256SUMS"

chmod -R a+rX "$REPORT_DIR"

echo "decision=$DECISION"
echo "classification=$CLASSIFICATION"
echo "target_is_original=$TARGET_ORIGINAL"
echo "runtime_library_is_absent=$LIB_ABSENT"
echo "min_healthy_count=$MIN_HEALTHY"
echo "max_healthy_count=$MAX_HEALTHY"
echo "installation_performed=false"
echo "rollback_required=false"

echo
echo "TRYCF_REPORT=$TRYCF_REPORT"
echo "REPORT_TXT=$REPORT_TXT"
echo "FACTS_JSON=$FACTS_JSON"

true
