#!/usr/bin/env bash
# spawn_fleet_agent — lanza un Claude como window nueva dentro de la sesion tmux
# de un perfil FleetView (socket aislado), opcionalmente en modo orquestador
# (skill embebida) y marcado con un role en su goal.json.
#
# Es la forma de que un ejecutor —o el propio orquestador— VIVA en la flota tmux
# (visible en la TUI fleetview, conmutable con /fleet focus), en vez de en una
# kitty suelta. Reemplaza a launch_claude_agent_kitty cuando se opera dentro de
# un perfil fleet ya montado.
#
# Funcion IMPURA: crea procesos (tmux window + claude) y, si se pide --role,
# marca el goal.json del nuevo Claude via mark_claude_role (en background, porque
# el sessionId no existe hasta que Claude escribe sessions/<PID>.json).
set -euo pipefail
IFS=$' \t\n'

spawn_fleet_agent() {
    local socket="" session="" cwd="" prompt_file="" skill="" role="" parent="" title="claude"

    while [[ $# -gt 0 ]]; do
        case "$1" in
            --socket)      shift; socket="${1:-}" ;;
            --session)     shift; session="${1:-}" ;;
            --cwd)         shift; cwd="${1:-}" ;;
            --prompt-file) shift; prompt_file="${1:-}" ;;
            --skill)       shift; skill="${1:-}" ;;
            --role)        shift; role="${1:-}" ;;
            --parent)      shift; parent="${1:-}" ;;
            --title)       shift; title="${1:-claude}" ;;
            -h|--help)
                cat <<'USAGE'
Uso: spawn_fleet_agent [--socket <s>] [--session <s>] [--cwd <dir>] [opciones]

Lanza un Claude como window nueva en la sesion tmux <session> del socket <socket>
(un perfil FleetView ya montado). Imprime el window_id creado.

--socket/--session son OPCIONALES: si no se pasan, se auto-detectan del contexto
tmux actual ($TMUX) via detect_fleet_context. Los valores explicitos tienen
prioridad. Aborta solo si tras auto-detectar siguen vacios (no hay tmux).

Opciones:
  --prompt-file <f>  Primer prompt del Claude = contenido del archivo (prompt
                     autocontenido del ejecutor). El cat lo hace el shell del
                     pane, asi que admite prompts multi-linea.
  --skill <name>     Primer prompt = "/<name>" (invoca un skill al arrancar, ej.
                     --skill orquestador para arrancar en modo orquestador).
  --role <r>         Marca el goal.json del nuevo Claude: orchestrator|executor
                     (via mark_claude_role, en background). Sin esto, executor
                     implicito.
  --parent <sid>     sessionId del orquestador que lanza este ejecutor. Si se
                     pasa, escribe parent_orchestrator en el goal.json del nuevo
                     Claude (via mark_claude_parent, en background) para que el
                     watcher de fleetview rutee sus avisos al orquestador padre.
  --title <t>        Nombre de la window tmux. Default: claude.

Ejemplos:
  # Orquestador en la flota actual:
  spawn_fleet_agent --socket fleet2 --session fleet2 --cwd ~/fn_registry \
    --skill orquestador --role orchestrator --title orquestador
  # Ejecutor con tarea autocontenida, atribuido a su orquestador padre:
  spawn_fleet_agent --socket fleet2 --session fleet2 --cwd ~/fn_registry \
    --prompt-file /tmp/orq_health.md --title "kanban-health" \
    --parent 32945650-a4e1-472b-90c9-5b38ef60a463
USAGE
                return 0 ;;
            *)
                echo "spawn_fleet_agent: opcion desconocida '$1' (usa -h)" >&2
                return 2 ;;
        esac
        shift
    done

    # Auto-detectar socket/session del contexto tmux ($TMUX) cuando no se pasan
    # explicitos. Los --socket/--session explicitos SIEMPRE tienen prioridad.
    # Esto evita el bug de caer a kitty cuando $FLEET_SOCKET viene vacia pese a
    # estar dentro de una window de la flota (ver detect_fleet_context).
    if [[ -z "$socket" || -z "$session" ]]; then
        local _detector ctx det_socket="" det_session=""
        _detector="$(dirname "${BASH_SOURCE[0]}")/detect_fleet_context.sh"
        if [[ -f "$_detector" ]]; then
            ctx="$(bash "$_detector" 2>/dev/null || true)"
            # Parseo minimo sin depender de jq: extraer "socket":"..." / "session":"...".
            det_socket="$(printf '%s' "$ctx" | sed -n 's/.*"socket":"\([^"]*\)".*/\1/p')"
            det_session="$(printf '%s' "$ctx" | sed -n 's/.*"session":"\([^"]*\)".*/\1/p')"
            [[ -z "$socket" ]]  && socket="$det_socket"
            [[ -z "$session" ]] && session="$det_session"
        fi
    fi

    [[ -z "$socket" || -z "$session" ]] && {
        echo "spawn_fleet_agent: no se detecto contexto tmux (\$TMUX vacia) y no se pasaron --socket/--session. Lanza desde dentro de la flota o pasa el socket/session explicito." >&2
        return 2
    }
    [[ -z "$cwd" ]] && cwd="$PWD"

    command -v tmux >/dev/null 2>&1 || {
        echo "spawn_fleet_agent: tmux no esta instalado" >&2
        return 1
    }
    if ! tmux -L "$socket" has-session -t "$session" 2>/dev/null; then
        echo "spawn_fleet_agent: la sesion '$session' no existe en el socket '$socket' (lanza la flota primero)" >&2
        return 1
    fi

    # Window nueva detached + claude. send-keys con exec para que el pane_pid sea
    # el de claude (no el del shell), necesario para mark_claude_role.
    local win_pane win_id
    win_pane=$(tmux -L "$socket" new-window -d -t "$session" -n "$title" -c "$cwd" -P -F '#{pane_id}')

    if [[ -n "$skill" ]]; then
        # Skill como primer prompt: "/<skill>". Claude Code lo interpreta como
        # invocacion de slash command al arrancar.
        tmux -L "$socket" send-keys -t "$win_pane" \
            "exec claude --dangerously-skip-permissions '/$skill'" C-m
    elif [[ -n "$prompt_file" ]]; then
        [[ -f "$prompt_file" ]] || {
            echo "spawn_fleet_agent: --prompt-file '$prompt_file' no existe" >&2
            return 1
        }
        # El cat lo ejecuta el shell del pane: admite prompts multi-linea.
        tmux -L "$socket" send-keys -t "$win_pane" \
            "exec claude --dangerously-skip-permissions \"\$(cat $(printf '%q' "$prompt_file"))\"" C-m
    else
        tmux -L "$socket" send-keys -t "$win_pane" \
            "exec claude --dangerously-skip-permissions" C-m
    fi

    # Marcar role y/o parent_orchestrator en background (no-fatal). El sleep da
    # tiempo a que el `exec claude` reemplace al shell antes de leer el pane_pid;
    # mark_claude_role / mark_claude_parent luego esperan a que aparezca
    # sessions/<PID>.json para resolver el sessionId. Se encadenan SECUENCIALMENTE
    # en el mismo subshell (primero role, luego parent) para que el segundo lea el
    # goal ya con la primera clave escrita y no haya carrera de
    # lectura-modificacion-escritura entre ambos.
    if [[ -n "$role" || -n "$parent" ]]; then
        local repo_root fn_bin
        repo_root="$(git -C "$(dirname "${BASH_SOURCE[0]}")" rev-parse --show-toplevel 2>/dev/null || echo "${FN_REGISTRY_ROOT:-$HOME/fn_registry}")"
        fn_bin="$repo_root/fn"
        if [[ -x "$fn_bin" ]]; then
            ( sleep 1
              pid=$(tmux -L "$socket" display-message -p -t "$win_pane" '#{pane_pid}' 2>/dev/null || true)
              if [[ -n "$pid" ]]; then
                  [[ -n "$role" ]]   && "$fn_bin" run mark_claude_role   "$pid" "$role"   >/dev/null 2>&1
                  [[ -n "$parent" ]] && "$fn_bin" run mark_claude_parent "$pid" "$parent" >/dev/null 2>&1
              fi
            ) >/dev/null 2>&1 &
            disown 2>/dev/null || true
        fi
    fi

    win_id=$(tmux -L "$socket" display-message -p -t "$win_pane" '#{window_id}' 2>/dev/null || true)
    echo "$win_id"
    return 0
}

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