#!/bin/bash
set -uo pipefail

# log_wan_status: runs wan_status (all checks), parses the
# human-readable output, assembles a JSON payload, and logs it as a
# datalog item via bgsystemlog.
# Intended to be called periodically via cron or systemd timer.

WAN_STATUS_BIN="${WAN_STATUS_BIN:-/var/signalytic/bin/wan_status}"
BGSYSTEMLOG="${BGSYSTEMLOG:-bgsystemlog}"
STDOUT_ONLY=false

usage() {
  echo "Usage: log_wan_status [-h|--help] [-c|--stdout]"
  echo ""
  echo "Options:"
  echo "  -h, --help    Print usage and exit"
  echo "  -c, --stdout  Write to stdout only, not blockgraph"
}

for arg in "$@"; do
  case "$arg" in
    -h|--help) usage; exit 0 ;;
    -c|--stdout) STDOUT_ONLY=true ;;
    *) echo "Invalid argument \"$arg\""; usage >&2; exit 1 ;;
  esac
done

# parse_field BLOCK FIELD
# Extracts the value of a "key: value" line from a labelled output block.
# BLOCK is the section header (e.g. "connectivity", "tls").
# FIELD is the key to look for within that block (e.g. "status", "latency").
parse_field() {
  local block="$1" field="$2"
  echo "$output" \
    | awk -v section="Checking ${block}..." -v key="${field}:" '
        $0 == section        { in_section=1; next }
        in_section && /^$/   { in_section=0 }
        in_section && index($0, key) == 1 {
          sub(/^[^:]+: /, ""); print; exit
        }
      '
}

# status_to_int STATUS  →  1 (OK) or 0 (FAIL/anything else)
status_to_int() { [[ "$1" == "OK" ]] && echo 1 || echo 0; }

# parse_routes  →  JSON array of interface names ordered by metric
parse_routes() {
  echo "$output" \
    | awk '
        $0 == "Checking WAN routes..." { in_section=1; next }
        in_section && /^$/             { in_section=0 }
        in_section && /^route: /       { sub(/^route: /, ""); print }
      ' \
    | awk 'BEGIN { printf "[" } NR>1 { printf "," } { printf "\"%s\"", $0 } END { printf "]" }'
}

# strip trailing unit suffixes for numeric fields (e.g. "150ms" → "150")
strip_unit() { echo "${1%%[^0-9.]*}"; }

main() {
  local output exit_code=0
  output=$("$WAN_STATUS_BIN" 2>&1) || exit_code=$?

  # -- parse each section -----------------------------------------------------
  local ping_status tls_status dns_status ntp_status
  ping_status=$(parse_field "connectivity" "status")
  tls_status=$(parse_field "TLS" "status")
  dns_status=$(parse_field "DNS" "status")
  ntp_status=$(parse_field "NTP" "status")

  local latency_raw packet_loss_raw
  latency_raw=$(parse_field "connectivity" "latency")
  packet_loss_raw=$(parse_field "connectivity" "packet loss")

  local latency_ms packet_loss_pct
  latency_ms="${latency_raw:-null}"
  [[ "$latency_ms" != "null" ]] && latency_ms=$(strip_unit "$latency_ms")
  packet_loss_pct="${packet_loss_raw:-null}"
  [[ "$packet_loss_pct" != "null" ]] && packet_loss_pct=$(strip_unit "$packet_loss_pct")

  local routes_json
  routes_json=$(parse_routes)

  # -- assemble JSON ----------------------------------------------------------
  local json
  json=$(printf '{"ping":%s,"tls":%s,"dns":%s,"ntp":%s,"latency_ms":%s,"packet_loss_pct":%s,"routes":%s}' \
    "$(status_to_int "$ping_status")" \
    "$(status_to_int "$tls_status")" \
    "$(status_to_int "$dns_status")" \
    "$(status_to_int "$ntp_status")" \
    "$latency_ms" \
    "$packet_loss_pct" \
    "$routes_json")

  if [[ "$STDOUT_ONLY" == true ]]; then
    echo "time: {\"ts\": \"$(date '+%Y-%m-%d %H:%M:%S.%6N')\"}"
    echo "wan: $json"
  else
    "$BGSYSTEMLOG" -j wan -m "$json"
  fi
  return "$exit_code"
}

main
