#!/usr/bin/env bash
# reset_anker_usb.sh — unbind+rebind snd-usb-audio for an Anker USB device.
#
# WHY THIS EXISTS
#   The Anker PowerConf A3321 on this Jetson sometimes enumerates with only
#   output USB Audio Class descriptors (no capture interface). PulseAudio
#   then shows the card with only output-only profiles and the dashboard
#   can't expose the mic. Restarting PulseAudio does nothing — UAC
#   descriptors are parsed by snd-usb-audio at probe time, persist in
#   kernel structs, and only get re-parsed on a fresh driver bind.
#
#   `/api/audio/usb-reset` writes directly to
#   /sys/bus/usb/drivers/snd-usb-audio/{unbind,bind} when possible. That
#   path needs root. This script exists as a sudo fallback so the dashboard
#   can recover without Sanad itself running as root.
#
# USAGE
#   reset_anker_usb.sh <bus_id>            — unbind+rebind given device
#                                            (bus_id like "1-3")
#   reset_anker_usb.sh --setup-sudoers     — install one-time NOPASSWD entry
#                                            (must be run via sudo)
#
# Exit codes:
#   0  — unbind + rebind both succeeded
#   1  — bus_id missing or device not present
#   2  — no snd-usb-audio interfaces bound to that device
#   3  — unbind or bind sysfs write failed
#   4  — --setup-sudoers used outside of sudo

set -u

USAGE="usage: $(basename "$0") <bus_id>   or   $(basename "$0") --setup-sudoers"

if [ "$#" -lt 1 ]; then
    echo "$USAGE" >&2
    exit 1
fi

# ───────────────────── --setup-sudoers ─────────────────────
if [ "$1" = "--setup-sudoers" ]; then
    if [ "$(id -u)" -ne 0 ]; then
        echo "❌ --setup-sudoers must run as root (use: sudo $0 --setup-sudoers)" >&2
        exit 4
    fi
    # Install a NOPASSWD entry so the unitree user can invoke THIS exact
    # script path with sudo without typing a password. Scoped to one
    # binary; not a blanket sudo grant.
    SELF_PATH="$(readlink -f "$0")"
    SUDO_FILE="/etc/sudoers.d/sanad-anker-usb-reset"
    cat > "$SUDO_FILE" <<EOF
# Installed by reset_anker_usb.sh --setup-sudoers
# Allows the unitree user to unbind+rebind snd-usb-audio scoped to the
# Anker dongle via this script ONLY — no other sudo privilege granted.
unitree ALL=(root) NOPASSWD: ${SELF_PATH}
EOF
    chmod 0440 "$SUDO_FILE"
    echo "✅ Installed sudoers entry at $SUDO_FILE"
    echo "   Dashboard's /api/audio/usb-reset can now recover the Anker without password."
    exit 0
fi

BUS_ID="$1"

# Validate the device exists.
DEV_PATH="/sys/bus/usb/devices/${BUS_ID}"
if [ ! -d "$DEV_PATH" ]; then
    echo "❌ USB device $BUS_ID not found at $DEV_PATH" >&2
    exit 1
fi

# Discover snd-usb-audio interfaces on this device. Don't unbind anything
# else (some Anker firmwares present HID-Consumer for the mute button on
# a separate interface — we leave those alone).
declare -a IFACES=()
for iface_path in "${DEV_PATH}/${BUS_ID}:"*; do
    [ -e "$iface_path" ] || continue
    driver_link="${iface_path}/driver"
    [ -L "$driver_link" ] || continue
    driver=$(basename "$(readlink "$driver_link")")
    if [ "$driver" = "snd-usb-audio" ]; then
        IFACES+=("$(basename "$iface_path")")
    fi
done

if [ "${#IFACES[@]}" -eq 0 ]; then
    echo "❌ No snd-usb-audio interfaces bound to device $BUS_ID" >&2
    exit 2
fi

echo "ℹ️  Re-binding snd-usb-audio for $BUS_ID (interfaces: ${IFACES[*]})"

UNBIND="/sys/bus/usb/drivers/snd-usb-audio/unbind"
BIND="/sys/bus/usb/drivers/snd-usb-audio/bind"

# Unbind first; on failure exit before rebind so we don't leave the device
# in a half-bound state.
for iface in "${IFACES[@]}"; do
    if ! echo -n "$iface" > "$UNBIND" 2>/dev/null; then
        echo "❌ unbind failed: $iface → $UNBIND" >&2
        exit 3
    fi
    echo "   unbound: $iface"
done

# Brief settle — snd-usb-audio's release path tears down ALSA card N.
sleep 0.5

for iface in "${IFACES[@]}"; do
    if ! echo -n "$iface" > "$BIND" 2>/dev/null; then
        echo "❌ rebind failed: $iface → $BIND" >&2
        exit 3
    fi
    echo "   bound:   $iface"
done

# Let probe complete so callers can pactl list cards right after.
sleep 1.0
echo "✅ snd-usb-audio re-bound for $BUS_ID"
exit 0
