#!/bin/bash
set -uo pipefail

# wan_status: checks internet connectivity and prints a human-readable report
# Usage: ./wan_status [TEST]
#   TEST: ping | tls | dns | ntp  (default: run all)
# Exit: 0 = all checked tests passed, 1 = one or more failed

PING_TARGET="${PING_TARGET:-8.8.8.8}"
TLS_TARGET="${TLS_TARGET:-https://signalytic.ca}"
DNS_TARGET="${DNS_TARGET:-signalytic.ca}"

# ---- checks -----------------------------------------------------------------

check_ping() {
  echo "Checking connectivity..."
  local output exit_code=0
  output=$(ping -c 3 -W 2 "$PING_TARGET" 2>&1) || exit_code=$?

  local latency packet_loss
  latency=$(echo "$output" | grep -oP 'rtt min/avg/max/mdev = \d+(?:\.\d+)?/\K\d+(?:\.\d+)?' || echo "null")
  packet_loss=$(echo "$output" | grep -oP '\d+(?:\.\d+)?(?=% packet loss)' || echo "null")

  if [[ "$exit_code" -eq 0 ]]; then
    echo "status: OK"
  else
    echo "status: FAIL"
  fi
  echo "latency: ${latency}ms"
  echo "packet loss: ${packet_loss}%"
  echo ""
  return "$exit_code"
}

check_tls() {
  echo "Checking TLS..."
  if curl -s --max-time 5 "$TLS_TARGET" &>/dev/null; then
    echo "status: OK"
    echo ""
    return 0
  else
    echo "status: FAIL"
    echo ""
    return 1
  fi
}

check_dns() {
  echo "Checking DNS..."
  if timeout 5 getent hosts "$DNS_TARGET" &>/dev/null; then
    echo "status: OK"
    echo ""
    return 0
  else
    echo "status: FAIL"
    echo ""
    return 1
  fi
}

check_ntp() {
  echo "Checking NTP..."
  local ntp_sync
  ntp_sync=$(timedatectl show --property=NTPSynchronized --value 2>/dev/null || echo "no")

  if [[ "$ntp_sync" == "yes" ]]; then
    echo "status: OK"
    echo ""
    return 0
  else
    echo "status: FAIL"
    echo ""
    return 1
  fi
}

check_wan_routes() {
  echo "Checking WAN routes..."
  ip -4 route show default \
    | awk '{
        iface=""; metric=32767
        for (i=1; i<=NF; i++) {
          if ($i == "dev")    iface=$(i+1)
          if ($i == "metric") metric=$(i+1)+0
        }
        if (iface) print metric, iface
      }' \
    | sort -n \
    | awk '{print "route: " $2}'
  echo ""
}

# ---- usage ------------------------------------------------------------------

usage() {
  echo "Usage: $(basename "$0") [TEST]"
  echo "  TEST: ping | tls | dns | ntp  (default: all)"
  exit 1
}

# ---- main -------------------------------------------------------------------

main() {
  local test="${1:-all}"
  local failed=0

  case "$test" in
    ping)   check_ping       || failed=1 ;;
    tls)    check_tls        || failed=1 ;;
    dns)    check_dns        || failed=1 ;;
    ntp)    check_ntp        || failed=1 ;;
    routes) check_wan_routes             ;;
    all)
      check_ping       || failed=1
      check_tls        || failed=1
      check_dns        || failed=1
      check_ntp        || failed=1
      check_wan_routes
      ;;
    *) usage ;;
  esac

  return $failed
}

main "${@}"
