#!/bin/sh
# mesh-speedtest — quick throughput probe across the wg1 mesh.
#
# Default: from current host, pull a chunk from each peer over ssh and report
# Mbps + a streaming verdict. Bytes traverse the wg1 tunnel; ssh adds a thin
# layer of double-encryption, so numbers run a few % below raw wg throughput
# but are stable for "can I stream from here?" decisions.
#
# Usage:
#   mesh-speedtest                  # download from each peer (64 MiB)
#   mesh-speedtest -s 256           # use 256 MiB chunks (slower, more stable)
#   mesh-speedtest -u               # upload (push to each peer) instead
#   mesh-speedtest -p plum,black    # restrict to specific peers
#
# Peers are the wg1 mesh: apricot, black, plum, quinn-vps. Self is skipped.

set -eu

size_mib=64
direction=down
peer_filter=""

while [ $# -gt 0 ]; do
    case $1 in
        -s) size_mib=$2; shift 2 ;;
        -u) direction=up; shift ;;
        -p) peer_filter=$2; shift 2 ;;
        -h|--help) sed -n '2,18p' "$0" | sed 's/^# \{0,1\}//'; exit 0 ;;
        *) echo "unknown arg: $1" >&2; exit 2 ;;
    esac
done

all_peers="apricot black plum quinn-vps"

self=$(hostname -s 2>/dev/null || hostname)
case $self in
    plum|*plum*) self=plum ;;
    apricot*) self=apricot ;;
    black*) self=black ;;
    quinn-vps*|*1984*) self=quinn-vps ;;
esac

verdict() {
    mbps=$1
    awk -v m="$mbps" 'BEGIN{
        if (m >= 40) print "4K HDR ok";
        else if (m >= 25) print "4K ok";
        else if (m >= 12) print "1080p high ok";
        else if (m >= 5)  print "1080p ok";
        else if (m >= 3)  print "720p ok";
        else if (m >= 1.5) print "480p / rsync first for HD";
        else print "rsync only";
    }'
}

# Run one direction against one peer. Echo "<peer> <mbps> <secs>" or "<peer> ERR".
probe() {
    peer=$1
    bytes=$((size_mib * 1024 * 1024))
    start=$(date +%s.%N 2>/dev/null || date +%s)
    if [ "$direction" = down ]; then
        ssh -o ConnectTimeout=5 -o BatchMode=yes "$peer" \
            "dd if=/dev/zero bs=1M count=$size_mib status=none" \
            > /dev/null 2>/tmp/mesh-speedtest.$$.$peer.err || { echo "$peer ERR"; return; }
    else
        dd if=/dev/zero bs=1M count=$size_mib status=none 2>/dev/null \
            | ssh -o ConnectTimeout=5 -o BatchMode=yes "$peer" \
              "dd of=/dev/null bs=1M status=none" \
            2>/tmp/mesh-speedtest.$$.$peer.err || { echo "$peer ERR"; return; }
    fi
    end=$(date +%s.%N 2>/dev/null || date +%s)
    secs=$(awk -v s="$start" -v e="$end" 'BEGIN{d=e-s; if(d<0.001)d=0.001; printf "%.3f",d}')
    mbps=$(awk -v b="$bytes" -v t="$secs" 'BEGIN{printf "%.1f", (b*8)/(t*1000000)}')
    echo "$peer $mbps $secs"
}

# Build peer list.
peers=""
if [ -n "$peer_filter" ]; then
    peers=$(echo "$peer_filter" | tr ',' ' ')
else
    for p in $all_peers; do
        [ "$p" = "$self" ] && continue
        peers="$peers $p"
    done
fi

label=$([ "$direction" = down ] && echo "download from" || echo "upload to")
printf "mesh-speedtest: %s peers, %d MiB chunks (self=%s)\n\n" "$label" "$size_mib" "$self"
printf "%-12s %10s %8s   %s\n" "peer" "Mbps" "secs" "verdict"
printf "%-12s %10s %8s   %s\n" "----" "----" "----" "-------"

# Run probes sequentially; parallel would skew Mbps via shared uplink.
for p in $peers; do
    out=$(probe "$p")
    case $out in
        *ERR)
            err=$(cat /tmp/mesh-speedtest.$$.$p.err 2>/dev/null | head -1)
            printf "%-12s %10s %8s   %s\n" "$p" "-" "-" "ssh failed: ${err:-unreachable}"
            ;;
        *)
            peer_n=$(echo "$out" | awk '{print $1}')
            mbps=$(echo "$out" | awk '{print $2}')
            secs=$(echo "$out" | awk '{print $3}')
            v=$(verdict "$mbps")
            printf "%-12s %10s %8s   %s\n" "$peer_n" "$mbps" "$secs" "$v"
            ;;
    esac
    rm -f /tmp/mesh-speedtest.$$.$p.err
done

# Average across reachable peers (informational only — wildly different paths).
echo ""
