#!/usr/bin/env bash
# amux-up — one command to ENSURE a session is started and ATTACH to it.
# Solves the "amux-remote start only started it but never connected me" footgun:
# over amux-remote, `start` != `attach`. This does start (idempotent) then attach.
#
# Picks the right lane automatically:
#   - if this box's LOCAL amux knows the session -> `amux start` (which attaches)
#   - else, on a configured box                  -> `amux-remote <box> start` then `… attach`
#
# The remote lane ALWAYS names its machine — a box is never inferred (no default
# remote, no "the only configured box"). The machine goes FIRST, exactly as in
# `amux-remote <machine> <cmd>`, so both commands read the same way:
#   amux-up <name>              LOCAL sessions only; errors if not found locally
#   amux-up <machine> <name>    remote — same word order as amux-remote
#
# In the two-word form the machine interpretation WINS: if $1 names a configured
# machine and $2 is a session name (not a flag), it is <machine> <name> even when
# a local session shares the machine's name. With ONE argument a local session
# still resolves locally.
#
# Flags after the name go to the remote `start` (one-shot), except --cc/--plain
# which go to `attach`. For claude sessions resume is AUTOMATIC (the server
# auto-resumes the newest conversation on start), so --continue is rarely
# needed — but it is forwarded and honored.
#
# Usage: amux-up [<machine>] <name> [extra claude/amux flags]
#   e.g. amux-up mattermost
#        amux-up desktop myproject --continue
#
# The older `amux-up <machine>:<name>` colon form still works, so existing scripts
# and keybindings keep running, but the two-word form is the documented one.
case "${1:-}" in -h|--help)
  awk 'NR==1&&/^#!/{next} /^[[:space:]]*#/{sub(/^[[:space:]]*#[[:space:]]?/,"");print;next} {exit}' "$0"; exit 0 ;;
esac
set -uo pipefail

raw="${1:-}"
[ -z "$raw" ] && { echo "usage: amux-up [<machine>] <name> [flags]   (-h for details)"; exit 2; }
shift || true

remdir="${CC_HOME:-$HOME/.amux}/remotes"
box=""; name="$raw"; box_explicit=0

# Legacy colon form: <machine>:<name>.
case "$raw" in
  *:*) box="${raw%%:*}"; name="${raw#*:}" ;;
  *)
    # Two-word form: treat the FIRST word as a machine only when it actually names
    # a configured one AND a second non-flag word follows. That keeps
    # `amux-up myproject --continue` local (--continue is a flag, not a name) and
    # avoids inventing a machine out of an ordinary session name. ONLY in this
    # form does the machine interpretation beat a same-named local session.
    if [ -n "${1:-}" ] && [ -f "$remdir/$raw.env" ]; then
      case "$1" in
        -*) ;;                                   # a flag: $raw was the session name
        *)  box="$raw"; name="$1"; box_explicit=1; shift ;;   # <machine> <name>
      esac
    fi ;;
esac

known_local=0
if [ "$box_explicit" = 1 ]; then
  : # machine named explicitly (two-word form) — go remote, skip the local lane
elif command -v amux >/dev/null 2>&1; then
  if amux ls -c 2>/dev/null | grep -qE "(^|[[:space:]])${name}([[:space:]]|\$)"; then
    known_local=1
  fi
fi

if [ "$known_local" = 1 ]; then
  # local: `amux start` starts if stopped (auto-resumes newest) and attaches; if
  # already running it short-circuits to attach. Either way you end up inside it.
  exec amux start "$name" "$@"
fi

# Remote lane: the session is not local. A MACHINE IS NEVER INFERRED — you name it
# first, as `amux-up <machine> <name>`. No "the only configured box" shortcut:
# guessing which machine to drive is how you start a session on the wrong one.
# Use the amux-remote from THIS checkout, not whatever is first on $PATH.
# Upstream amux ships its own amux-remote, and an older copy may also be
# installed; either would read config differently and render differently, so
# a command from this repo must drive the amux-remote from this repo.
_resolve_amux_remote() {
  local self dir real
  self="${BASH_SOURCE[0]}"
  dir=$(cd "$(dirname "$self")" && pwd)
  if [ -x "$dir/amux-remote" ]; then printf '%s\n' "$dir/amux-remote"; return; fi
  real=$(readlink "$self" 2>/dev/null || printf '%s' "$self")
  case "$real" in /*) ;; *) real="$dir/$real" ;; esac
  dir=$(cd "$(dirname "$real")" 2>/dev/null && pwd)
  if [ -n "$dir" ] && [ -x "$dir/amux-remote" ]; then printf '%s\n' "$dir/amux-remote"; return; fi
  printf 'amux-remote\n'   # last resort: whatever is on PATH
}
AMUX_REMOTE=$(_resolve_amux_remote)

if [ -z "$box" ]; then
  echo "amux-up: '$name' is not a local session, and no box was named." >&2
  echo "  name the machine first, like amux-remote does:  amux-up <machine> $name" >&2
  boxes="$(ls "$remdir" 2>/dev/null | sed -n 's/\.env$//p' | tr '\n' ' ')"
  [ -n "$boxes" ] && echo "  boxes: $boxes" >&2
  exit 2
fi

if [ -x "$AMUX_REMOTE" ] || command -v amux-remote >/dev/null 2>&1 && [ -f "$remdir/$box.env" ]; then
  # Route flags: --cc/--plain belong to `attach`; everything else (--continue,
  # --provider …) is a one-shot launch flag for `start`.
  start_flags=(); attach_flags=()
  for a in "$@"; do
    case "$a" in
      --cc|--plain) attach_flags+=("$a") ;;
      *)            start_flags+=("$a") ;;
    esac
  done
  echo "· starting '$name' on box '$box' (if not already up)…"
  # A failed start must NOT be swallowed — attaching after one just drops you
  # into a missing/dead tmux target. AMUX_NO_HINT=1: we attach right after, so
  # amux-remote's "attach: amux-up …" next-step hint would be noise here.
  if ! AMUX_NO_HINT=1 "$AMUX_REMOTE" "$box" start "$name" ${start_flags[@]+"${start_flags[@]}"}; then
    echo "amux-up: starting '$name' on '$box' FAILED — not attaching." >&2
    exit 1
  fi
  exec "$AMUX_REMOTE" "$box" attach "$name" ${attach_flags[@]+"${attach_flags[@]}"}
fi

echo "amux-up: '$name' not found locally and no box resolved." >&2
boxes="$(ls "$remdir"/*.env 2>/dev/null | sed -E 's#.*/##; s/\.env$//' | tr '\n' ' ')"
[ -n "$boxes" ] && echo "  machines: ${boxes} — try 'amux-up <machine> $name'" >&2
echo "  local sessions:" >&2
amux ls -c 2>/dev/null | sed 's/^/    /' >&2
exit 1
