#!/usr/bin/env bash
# ============================================================================
# xo-multiroom — Umschalter Einzelraum (bit-perfekt) <-> Gruppe (Snapcast-Sync)
# ============================================================================
# Einzelraum (Default): MPD -> ALSA hw:0,0 -> XMOS-DAC (bit-perfekt).
# Gruppe:               MPD -> FIFO -> snapserver -> snapclient -> DAC (synchron).
#
# Portiert aus dem Fedora-setup-device.sh (configure_multiroom) auf Debian:
#  - snapclient-Defaults unter /etc/default/snapclient (statt /etc/sysconfig).
#  - kein harter source der Fedora-lib; MPD_PORT/Card werden lokal ermittelt.
# ============================================================================
set -euo pipefail

source /opt/x-odos/lib/xodos-common.sh 2>/dev/null || true
MPD_PORT="${MPD_PORT:-6600}"
MPC="mpc -h 127.0.0.1 -p ${MPD_PORT}"
FIFO_MATCH="Snapcast"   # Name-Substring des FIFO-Outputs in mpd.conf

# Persistierter Modus: Beim Boot regeneriert mpd-reconfig.sh die mpd.conf
# (FIFO 'enabled no') und snapclient wird nur per start/stop geschaltet —
# ohne Persistenz "vergisst" das Gerät seinen Modus nach jedem Neustart
# und spielt nichts, bis manuell wieder umgeschaltet wird.
MODE_FILE="${XODOS_SETTINGS:-/opt/settings}/multiroom.mode"

save_mode() {
    mkdir -p "$(dirname "$MODE_FILE")" 2>/dev/null || true
    echo "$*" > "$MODE_FILE" 2>/dev/null || true
}

# USB-XMOS-ALSA-Card ermitteln (Fallback: Card 0).
detect_card() {
    if declare -F detect_usb_alsa_card >/dev/null 2>&1; then
        detect_usb_alsa_card 2>/dev/null || true
    else
        awk '/USB|XMOS|DAC/ {gsub(/[^0-9]/,"",$1); print $1; exit}' /proc/asound/cards 2>/dev/null || true
    fi
}

# ✅ FIX: snapclient-Optionen in ALLE vorhandenen Defaults-Dateien
# schreiben. Auf manchen Geräten existieren /etc/default/snapclient UND
# /etc/sysconfig/snapclient — das Skript schrieb nur die erste, die
# systemd-Unit las aber die andere: Der snapclient startete dann mit
# einem VERALTETEN Master-Host neu (Join wirkungslos, "passiert nichts").
# ✅ FIX v2: Fehlende Dateien werden ANGELEGT statt übersprungen. Die
# Fedora-Unit liest EnvironmentFile=-/etc/default/snapclient — auf F43
# existierte nur /etc/sysconfig/snapclient: SNAPCLIENT_OPTS blieb leer,
# snapclient startete ohne -h/-s und verband sich per mDNS mit einem
# beliebigen (fremden/toten) snapserver im Netz → Raum "Nicht verbunden",
# DAC blieb auf der alten Rate, kein Ton.
set_snapclient_opts() {
    local opts="$1" f
    for f in /etc/default/snapclient /etc/sysconfig/snapclient; do
        mkdir -p "$(dirname "$f")" 2>/dev/null || true
        if [[ -f "$f" ]] && grep -q '^SNAPCLIENT_OPTS=' "$f" 2>/dev/null; then
            sed -i "s|^SNAPCLIENT_OPTS=.*|SNAPCLIENT_OPTS=\"${opts}\"|" "$f" 2>/dev/null || true
        else
            echo "SNAPCLIENT_OPTS=\"${opts}\"" >> "$f" 2>/dev/null \
                || echo "⚠ ${f} nicht schreibbar" >&2
        fi
    done
}

# IDs der MPD-Outputs ermitteln
fifo_id()  { $MPC outputs 2>/dev/null | awk -v m="$FIFO_MATCH" '$0 ~ m {gsub(/[^0-9]/,"",$2); print $2; exit}'; }
local_ids(){ $MPC outputs 2>/dev/null | awk -v m="$FIFO_MATCH" '/^Output/ && $0 !~ m && $0 !~ /HTTP/ {gsub(/[^0-9]/,"",$2); print $2}'; }

# Ist mindestens ein lokaler (nicht-FIFO, nicht-HTTP) Output aktiv?
local_enabled() {
    $MPC outputs 2>/dev/null \
        | awk -v m="$FIFO_MATCH" '$0 !~ m && tolower($0) !~ /http/' \
        | grep -q "is enabled"
}

mode_single() {
    echo "→ Einzelraum (bit-perfekt am DAC)"
    # disable: darf nach Reboot nicht automatisch starten (belegt sonst den DAC)
    systemctl disable --now snapclient.service 2>/dev/null || true

    # Reihenfolge: ERST lokale Outputs an, DANN FIFO aus. Vorher war es
    # umgekehrt — ein Status-Poll in der Lücke sah "kein Output aktiv"
    # und die UIs zeigten 'unknown' (kein Modus markiert).
    # Mit Retry: MPD kann direkt nach Dienst-Restarts kurz beschäftigt sein.
    local i ok=0
    for i in 1 2 3; do
        for id in $(local_ids); do $MPC enable "$id" >/dev/null 2>&1 || true; done
        if local_enabled; then ok=1; break; fi
        sleep 1
    done
    if [[ "$ok" != "1" ]]; then
        echo "✗ Einzelraum: kein lokaler Output aktivierbar — FIFO bleibt an" >&2
        exit 1
    fi

    local fid; fid="$(fifo_id || true)"
    [[ -n "$fid" ]] && $MPC disable "$fid" >/dev/null 2>&1 || true

    # snapclient wieder auf dieses Gerät zeigen lassen — ein stehen
    # gebliebener Join-Host würde das Gerät beim nächsten snapclient-Start
    # (z. B. nach Reboot) stillschweigend wieder fremd zuordnen.
    local card dev
    card="$(detect_card || true)"
    if [[ -n "$card" ]]; then dev="hw:${card},0"; else dev="hw:0,0"; fi
    set_snapclient_opts "-h 127.0.0.1 -s ${dev}"
    save_mode single
    echo "✓ Einzelraum aktiv"
}

mode_group() {
    echo "→ Gruppe (synchron über Snapcast)"
    local card dev
    card="$(detect_card || true)"
    if [[ -n "$card" ]]; then dev="hw:${card},0"; else dev="hw:0,0"; fi

    # snapclient auf die lokale Soundkarte zeigen lassen
    set_snapclient_opts "-h 127.0.0.1 -s ${dev}"

    systemctl restart snapserver.service 2>/dev/null || true

    # FIFO-Output finden — mit Retry (MPD kann kurz beschäftigt sein).
    # WICHTIG: Wenn der FIFO nicht gefunden/aktiviert wird, ABBRECHEN,
    # bevor lokale Outputs deaktiviert werden. Vorher wurden sie blind
    # deaktiviert → gar KEIN Output aktiv → Modus dauerhaft 'unknown'
    # ("steht auf nichts") und keine Wiedergabe.
    local fid="" i
    for i in 1 2 3 4 5; do
        fid="$(fifo_id || true)"
        [[ -n "$fid" ]] && break
        sleep 1
    done
    if [[ -z "$fid" ]]; then
        echo "✗ Gruppen-Modus: FIFO-Output ('${FIFO_MATCH}') nicht gefunden — lokale Outputs bleiben aktiv" >&2
        exit 1
    fi

    # Erst FIFO an (und verifizieren), DANN lokale Outputs aus.
    $MPC enable "$fid" >/dev/null 2>&1 || true
    if ! $MPC outputs 2>/dev/null | grep "$FIFO_MATCH" | grep -q "is enabled"; then
        echo "✗ Gruppen-Modus: FIFO-Output ließ sich nicht aktivieren — lokale Outputs bleiben aktiv" >&2
        exit 1
    fi
    for id in $(local_ids); do $MPC disable "$id" >/dev/null 2>&1 || true; done
    # enable: muss nach Reboot automatisch starten, sonst ist die Gruppe stumm
    systemctl enable snapclient.service 2>/dev/null || true
    systemctl restart snapclient.service 2>/dev/null || true
    save_mode group
    echo "✓ Gruppen-Modus aktiv (Soundkarte: ${dev})"
}

mode_join() {
    # ✅ NEU: Diesem Gerät den snapserver eines ANDEREN Geräts (Master)
    # zuweisen. Vorher zeigte snapclient IMMER auf 127.0.0.1 — jedes Gerät
    # war eine Insel und der Master sah nie die anderen Räume!
    local master="${1:-}"
    if [[ -z "$master" ]]; then
        echo "Usage: xo-multiroom join <master-host>"; exit 1
    fi
    echo "→ Beitritt zur Gruppe von ${master}"
    local card dev
    card="$(detect_card || true)"
    if [[ -n "$card" ]]; then dev="hw:${card},0"; else dev="hw:0,0"; fi

    # snapclient auf den Master zeigen lassen
    set_snapclient_opts "-h ${master} -s ${dev}"

    # Lokaler snapserver wird als beigetretener Raum nicht gebraucht
    systemctl stop snapserver.service 2>/dev/null || true
    # FIFO aus, lokale ALSA-Outputs aus → DAC frei für snapclient
    local fid; fid="$(fifo_id || true)"
    [[ -n "$fid" ]] && $MPC disable "$fid" >/dev/null 2>&1 || true
    for id in $(local_ids); do $MPC disable "$id" >/dev/null 2>&1 || true; done
    # enable: der Raum muss nach Reboot automatisch wieder beim Master hängen
    systemctl enable snapclient.service 2>/dev/null || true
    systemctl restart snapclient.service 2>/dev/null || true
    save_mode join "$master"
    echo "✓ Raum beigetreten (Master: ${master}, Soundkarte: ${dev})"
}

mode_restore() {
    # Beim Boot aufgerufen (xo-startup.sh, nach MPD-Start): stellt den zuletzt
    # gewählten Modus wieder her. mpd-reconfig.sh hat die mpd.conf frisch
    # geschrieben (FIFO aus, ALSA an) — ohne Restore stand das Gerät nach
    # jedem Neustart effektiv auf "nichts", bis manuell umgeschaltet wurde.
    local saved mode arg
    saved="$(cat "$MODE_FILE" 2>/dev/null || true)"
    mode="${saved%% *}"
    arg="${saved#* }"
    case "$mode" in
        group)  echo "→ Restore: Gruppen-Modus";  mode_group ;;
        join)   [[ -n "$arg" && "$arg" != "$saved" ]] \
                    && { echo "→ Restore: Join ${arg}"; mode_join "$arg"; } \
                    || { echo "→ Restore: Join ohne Master — Fallback Einzelraum"; mode_single; } ;;
        single) echo "→ Restore: Einzelraum";     mode_single ;;
        *)      echo "→ Restore: kein gespeicherter Modus — Default Einzelraum"; mode_single ;;
    esac
}

mode_status() {
    echo "── MPD-Outputs ──"; $MPC outputs 2>/dev/null || echo "  (MPD nicht erreichbar)"
    echo; echo "── Dienste ──"
    for s in snapserver snapclient; do
        printf "  %-12s %s\n" "$s" "$(systemctl is-active ${s}.service 2>/dev/null || echo inactive)"
    done
    local sc
    echo; echo "── snapclient ──"
    for sc in /etc/default/snapclient /etc/sysconfig/snapclient; do
        [[ -f "$sc" ]] || continue
        printf "  %s: " "$sc"
        grep '^SNAPCLIENT_OPTS=' "$sc" 2>/dev/null || echo "(keine SNAPCLIENT_OPTS)"
    done
}

case "${1:-status}" in
    single|local)  mode_single ;;
    group|multi)   mode_group  ;;
    join)          mode_join "${2:-}" ;;
    restore)       mode_restore ;;
    status)        mode_status ;;
    *) echo "Usage: xo-multiroom {single|group|join <master-host>|restore|status}"; exit 1 ;;
esac
