#!/usr/bin/env bash
# supervise_fleetview_tui — bucle supervisor que mantiene viva la TUI fleetview.
#
# Lanza el binario fleetview y, si sale (crash, panic, kill de su proceso o de su
# pane), lo relanza tras un pequeno backoff. Asi el panel de control de la flota
# NUNCA se pierde por un fallo puntual: es la pieza que hace resiliente al pane
# izquierdo de la sesion tmux FleetView (lo invoca launch_fleetclaude).
#
# Dos valvulas de escape para no hacer respawn infinito:
#   - Sentinel file: si tras una salida existe el fichero centinela, se borra y
#     el bucle termina (parada voluntaria solicitada por el usuario). El default
#     es $HOME/.claude/fleet/tui_stop_<socket>; pararla a mano: `touch <sentinel>`
#     y dejar que la TUI salga (o matar su proceso).
#   - Crash-loop guard: si la TUI sale demasiado rapido (uptime < min_uptime
#     segundos) muchas veces seguidas (>= max_fast_exits), el supervisor se rinde
#     y devuelve != 0, para no quemar CPU relanzando un binario roto en caliente.
#     Un arranque que dura >= min_uptime resetea el contador.
#
# Funcion IMPURA: lanza un proceso en bucle y lee/escribe un fichero centinela.
#
# Overrides de entorno (testabilidad, no para uso normal):
#   FLEET_SOCKET   socket del perfil; fija el nombre del sentinel por defecto.
set -euo pipefail
IFS=$' \t\n'

supervise_fleetview_tui() {
    local bin="" socket="" sentinel="" backoff=1 min_uptime=2 max_fast_exits=5

    while [[ $# -gt 0 ]]; do
        case "$1" in
            --bin)            shift; bin="${1:-}" ;;
            --socket)         shift; socket="${1:-}" ;;
            --sentinel)       shift; sentinel="${1:-}" ;;
            --backoff)        shift; backoff="${1:-1}" ;;
            --min-uptime)     shift; min_uptime="${1:-2}" ;;
            --max-fast-exits) shift; max_fast_exits="${1:-5}" ;;
            -h|--help)
                cat <<'USAGE'
Uso: supervise_fleetview_tui --bin <path> [opciones]

Bucle supervisor: corre el binario fleetview y lo relanza si sale, para que el
panel de la flota nunca se pierda por un crash/kill puntual.

Opciones:
  --bin <path>          Ruta al binario fleetview (obligatorio).
  --socket <s>          Socket del perfil FleetView. Default: $FLEET_SOCKET o "fleet".
  --sentinel <path>     Fichero centinela de parada voluntaria.
                        Default: $HOME/.claude/fleet/tui_stop_<socket>.
  --backoff <s>         Segundos de espera antes de relanzar. Default: 1.
  --min-uptime <s>      Umbral (s) para considerar una salida "rapida". Default: 2.
  --max-fast-exits <n>  Salidas rapidas seguidas tras las que el supervisor se
                        rinde (crash-loop guard). Default: 5.
  -h, --help            Esta ayuda.

Parar el bucle a mano: `touch <sentinel>` y dejar que la TUI salga (o matar su
proceso); en el siguiente ciclo el supervisor ve el sentinel, lo borra y termina.

Salida: 0 parada voluntaria (sentinel); 1 binario no ejecutable / uso incorrecto;
3 el supervisor se rindio por crash-loop (demasiadas salidas rapidas seguidas).
USAGE
                return 0 ;;
            --*)
                echo "supervise_fleetview_tui: opcion desconocida '$1' (usa -h)" >&2
                return 1 ;;
            *)
                if [[ -z "$bin" ]]; then
                    bin="$1"
                else
                    echo "supervise_fleetview_tui: argumento extra '$1' (bin ya es '$bin')" >&2
                    return 1
                fi ;;
        esac
        shift
    done

    [[ -z "$bin" ]] && {
        echo "supervise_fleetview_tui: falta --bin <path> al binario fleetview. Usa -h." >&2
        return 1
    }
    [[ -z "$socket" ]] && socket="${FLEET_SOCKET:-fleet}"
    [[ -z "$sentinel" ]] && sentinel="$HOME/.claude/fleet/tui_stop_${socket}"
    mkdir -p "$(dirname "$sentinel")" 2>/dev/null || true

    if [[ ! -x "$bin" ]]; then
        echo "supervise_fleetview_tui: binario '$bin' no es ejecutable. Compila la TUI: cd apps/fleetview && go build -o fleetview ." >&2
        return 1
    fi

    # Limpiar un sentinel huerfano de una sesion anterior, para no parar al arrancar.
    [[ -f "$sentinel" ]] && rm -f "$sentinel" 2>/dev/null || true

    local fast_exits=0
    while true; do
        local start end uptime code
        start=$(date +%s)
        set +e
        "$bin"
        code=$?
        set -e
        end=$(date +%s)
        uptime=$(( end - start ))

        # Valvula 1 — parada voluntaria por sentinel.
        if [[ -f "$sentinel" ]]; then
            rm -f "$sentinel" 2>/dev/null || true
            echo "[fleetview: parada solicitada via sentinel ($sentinel) — fin del supervisor]"
            return 0
        fi

        # Valvula 2 — crash-loop guard.
        if [[ "$uptime" -lt "$min_uptime" ]]; then
            fast_exits=$(( fast_exits + 1 ))
        else
            fast_exits=0
        fi
        if [[ "$fast_exits" -ge "$max_fast_exits" ]]; then
            echo "[fleetview: $fast_exits salidas rapidas seguidas (ultimo code=$code) — el supervisor se rinde para no hacer respawn infinito. Inspecciona el binario y relanza.]" >&2
            return 3
        fi

        echo "[fleetview salio (code=$code, uptime=${uptime}s) — relanzando en ${backoff}s. Para parar: touch $sentinel, o Ctrl-C.]"
        sleep "$backoff"
    done
}

# Permitir ejecutar el archivo directamente (no solo como funcion sourced).
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    supervise_fleetview_tui "$@"
fi
