#!/bin/bash
# Stage 3 HDMI audio acceptance probe. All playback goes through PipeWire.
set -euo pipefail

OUTPUT=/tmp/mcom03-stage3-audio
DURATION=600
AAC_INPUT=

usage() {
    cat <<'EOF'
Usage: mcom03-audio-probe [options]

  --aac FILE          Required AAC sample tested at 44100 and 48000 Hz.
  --duration SECONDS  Duration of each tone/AAC test (default: 600).
  --output DIR        Evidence directory (default: /tmp/mcom03-stage3-audio).
EOF
}

while (($#)); do
    case $1 in
        --aac) shift; (($#)) || exit 64; AAC_INPUT=$1 ;;
        --duration) shift; (($#)) || exit 64; DURATION=$1 ;;
        --output) shift; (($#)) || exit 64; OUTPUT=$1 ;;
        -h|--help) usage; exit 0 ;;
        *) echo "Unknown option: $1" >&2; usage >&2; exit 64 ;;
    esac
    shift
done
[[ $DURATION =~ ^[1-9][0-9]*$ ]] || { echo "--duration must be positive." >&2; exit 64; }
[ -n "$AAC_INPUT" ] || { echo "--aac is required for Stage 3 acceptance." >&2; exit 64; }
[ -r "$AAC_INPUT" ] || { echo "AAC input is unreadable." >&2; exit 1; }

for command in date find grep journalctl mcom03-audioctl mkdir pw-dump wpctl; do
    command -v "$command" >/dev/null 2>&1 || { echo "Missing command: $command" >&2; exit 1; }
done
mkdir -p "$OUTPUT"
started=$(date -Is)

capture_state() {
    local label=$1
    wpctl status >"$OUTPUT/wpctl-$label.txt" 2>&1 || true
    wpctl inspect @DEFAULT_AUDIO_SINK@ >"$OUTPUT/default-sink-$label.txt" 2>&1 || true
    pw-dump >"$OUTPUT/pipewire-$label.json" 2>&1 || true
    find /proc/asound -path '*/pcm*/sub*/hw_params' -type f -exec sh -c \
        'printf "== %s ==\\n" "$1"; cat "$1"' sh {} \; \
        >"$OUTPUT/alsa-hw-params-$label.txt" 2>&1 || true
}

run_and_capture() {
    local label=$1
    shift
    mcom03-audioctl "$@" >"$OUTPUT/$label.txt" 2>&1 &
    local playback_pid=$!
    local active=no
    for _ in {1..15}; do
        kill -0 "$playback_pid" 2>/dev/null || break
        if grep -Rqs '^rate: 48000\([[:space:]]\|$\)' /proc/asound/*/pcm*/sub*/hw_params 2>/dev/null; then
            active=yes
            break
        fi
        sleep 1
    done
    capture_state "$label-active"
    wait "$playback_pid"
    [ "$active" = yes ] || return 1
    grep -Eq '^rate: 48000([[:space:]]|$)' "$OUTPUT/alsa-hw-params-$label-active.txt"
    grep -Rqs '^channels: 2$' "$OUTPUT/alsa-hw-params-$label-active.txt"
    grep -Rqs '^format: S16_LE$' "$OUTPUT/alsa-hw-params-$label-active.txt"
}

capture_state before
mcom03-audioctl hdmi >"$OUTPUT/select-hdmi.txt" 2>&1
tone_44100=pass
run_and_capture tone-44100 test-tone 44100 "$DURATION" || tone_44100=fail
tone_48000=pass
run_and_capture tone-48000 test-tone 48000 "$DURATION" || tone_48000=fail
aac_44100=pass
run_and_capture aac-44100 test-aac "$AAC_INPUT" 44100 "$DURATION" || aac_44100=fail
aac_48000=pass
run_and_capture aac-48000 test-aac "$AAC_INPUT" 48000 "$DURATION" || aac_48000=fail

journalctl --user --since "$started" -u pipewire -u wireplumber \
    >"$OUTPUT/pipewire-journal.txt" 2>&1 || true
journalctl -k --since "$started" >"$OUTPUT/kernel-journal.txt" 2>&1 || true
xruns=$(grep -Eic 'xrun|underrun' "$OUTPUT/pipewire-journal.txt" || true)
alsa_errors=$(grep -Eic 'snd_soc_dai_startup|audio.*error|underrun|underflow|mali.?dp.*error' \
    "$OUTPUT/kernel-journal.txt" || true)

result=PASS
[ "$xruns" -eq 0 ] || result=FAIL
[ "$alsa_errors" -eq 0 ] || result=FAIL
[ "$tone_44100" = pass ] || result=FAIL
[ "$tone_48000" = pass ] || result=FAIL
[ "$aac_44100" = pass ] || result=FAIL
[ "$aac_48000" = pass ] || result=FAIL

cat >"$OUTPUT/verification.txt" <<EOF
stage3_audio_result=$result
started=$started
duration_per_test_seconds=$DURATION
pipewire_only=yes
hdmi_format=S16LE
hdmi_rate=48000
hdmi_channels=2
hdmi_volume=${MCOM03_SINK_VOLUME:-1.0}
tone_44100=$tone_44100
tone_48000=$tone_48000
aac_44100=$aac_44100
aac_48000=$aac_48000
pipewire_xruns=$xruns
kernel_audio_errors=$alsa_errors
EOF
cat "$OUTPUT/verification.txt"
[ "$result" = PASS ]
