#!/usr/bin/env bash
set -euo pipefail

# team-launch.sh — split the CURRENT tmux window into panes, each running
# an interactive Copilot CLI agent session.
#
# Usage:
#   team-launch.sh --session <name> --lanes <lanes.json>
#
# Flow:
#   1. Split panes and launch agent CLI in each
#   2. Wait for each agent to be ready (auto-accept folder trust prompts)
#   3. Send lane prompts via send-keys
#   4. Monitor until all agents finish, then print summary

SESSION=""
LANES_FILE=""
NO_MONITOR=""

while [[ $# -gt 0 ]]; do
  case "$1" in
    --session)    SESSION="$2"; shift 2 ;;
    --lanes)      LANES_FILE="$2"; shift 2 ;;
    --no-monitor) NO_MONITOR=1; shift ;;
    *) echo "Unknown arg: $1" >&2; exit 1 ;;
  esac
done

if [[ -z "$SESSION" || -z "$LANES_FILE" ]]; then
  echo "Usage: team-launch.sh --session <name> --lanes <lanes.json>" >&2
  exit 1
fi

if [[ ! "$SESSION" =~ ^[A-Za-z0-9._-]+$ || "$SESSION" == "." || "$SESSION" == ".." || ${#SESSION} -gt 128 ]]; then
  echo "Invalid session: use 1-128 letters, digits, dots, underscores, or hyphens" >&2
  exit 1
fi

if [[ ! -f "$LANES_FILE" ]]; then
  echo "Lanes file not found: $LANES_FILE" >&2
  exit 1
fi

if ! command -v tmux &>/dev/null; then
  echo "tmux not found" >&2; exit 1
fi

if [[ -z "${TMUX:-}" ]]; then
  echo "Not inside a tmux session. Run this from within tmux." >&2; exit 1
fi

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGE_ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
PACKAGE_VERSION="$(jq -r '.version // empty' "$PACKAGE_ROOT/plugin.json" 2>/dev/null || true)"
CONTROL_CLI=""

if [[ -n "${OMP_TEAM_CONTROL_CLI:-}" ]]; then
  if [[ "$OMP_TEAM_CONTROL_CLI" = /* && -x "$OMP_TEAM_CONTROL_CLI" ]]; then
    CONTROL_CLI="$OMP_TEAM_CONTROL_CLI"
  else
    echo "⚠️  OMP_TEAM_CONTROL_CLI must be an absolute executable path; visual monitoring is disabled" >&2
  fi
elif [[ -x "$PACKAGE_ROOT/dist/src/cli.js" ]]; then
  CONTROL_CLI="$PACKAGE_ROOT/dist/src/cli.js"
elif command -v omp &>/dev/null; then
  INSTALLED_VERSION="$(omp version --json 2>/dev/null | jq -r '.package // empty' 2>/dev/null || true)"
  if [[ -n "$PACKAGE_VERSION" && "$INSTALLED_VERSION" == "$PACKAGE_VERSION" ]]; then
    CONTROL_CLI="$(command -v omp)"
  else
    echo "⚠️  Installed omp version does not match this package; visual monitoring is disabled" >&2
  fi
else
  echo "⚠️  No matching omp control CLI found; visual monitoring is disabled" >&2
fi

# OMP_TEAM_WORKER tags worker sessions so the agentStop hook skips loop
# injection — otherwise a worker spawned inside a project with an active
# ralph/ultrawork/ultraqa loop gets hijacked by "[RALPH ITERATION N]" prompts.
if command -v omp &>/dev/null; then
  AGENT_CMD="OMP_TEAM_WORKER=1 omp --madmax"
elif command -v copilot &>/dev/null; then
  # --yolo = all permissions (tools+paths+urls) so worker panes never block on a
  # trust/permission dialog. Matches the bypass `omp --madmax` grants.
  AGENT_CMD="OMP_TEAM_WORKER=1 copilot --yolo"
else
  echo "Neither omp nor copilot CLI found" >&2; exit 1
fi

if ! jq -e '
  type == "array" and
  length > 0 and
  all(.[];
    (.id | type == "string") and
    (.id | test("^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")) and
    (.name | type == "string") and
    (.prompt | type == "string")
  ) and
  (([.[].id] | length) == ([.[].id] | unique | length))
' "$LANES_FILE" >/dev/null; then
  echo "Invalid lanes file: lane ids must be unique path-safe names and name/prompt must be strings" >&2
  exit 1
fi
LANE_COUNT=$(jq length "$LANES_FILE")

CWD=$(pwd)
# Each worker writes its final result here so the lead can collect deterministically
# (`omp team collect --dir`), rather than scraping live panes.
DELIVERY_DIR="/tmp/team-$SESSION"
if [[ -e "$DELIVERY_DIR" || -L "$DELIVERY_DIR" ]]; then
  echo "Delivery directory already exists; choose a fresh session name: $DELIVERY_DIR" >&2
  exit 1
fi
if ! (umask 077 && mkdir "$DELIVERY_DIR"); then
  echo "Unable to create a private delivery directory: $DELIVERY_DIR" >&2
  exit 1
fi
POLL="${TEAM_POLL_INTERVAL:-2}"
MAX_READY="${TEAM_MAX_READY_WAIT:-60}"
MAX_DONE="${TEAM_MAX_COMPLETION_WAIT:-300}"
if command -v uuidgen &>/dev/null; then
  LAUNCH_ID="$(uuidgen)"
else
  LAUNCH_ID="$(node -e 'process.stdout.write(require("node:crypto").randomUUID())')"
fi

# ── helpers ──────────────────────────────────────────────────────────

# Capture visible pane content (last N lines)
pane_text() { tmux capture-pane -t "$1" -p -S "-${2:-20}" 2>/dev/null || true; }

# Wait until the agent CLI is fully ready ('/ commands' status bar visible).
# Auto-accepts the folder-trust dialog if it appears.
wait_for_ready() {
  local pane="$1" elapsed=0 accepted=0
  while (( elapsed < MAX_READY )); do
    local txt
    txt=$(pane_text "$pane" 25)

    # Ready: the '/ commands' status bar means the CLI input prompt is active
    if echo "$txt" | grep -q '/ commands'; then
      return 0
    fi

    # Auto-accept folder trust dialog. Use the `Enter` key NAME, not C-m:
    # Copilot CLI >=1.0.61 ignores a literal carriage return (C-m) for TUI
    # selection/submit, so C-m left the trust dialog open and the agent hung.
    if (( accepted == 0 )) && echo "$txt" | grep -q 'Do you trust'; then
      tmux send-keys -t "$pane" Enter
      accepted=1
      echo "    ↳ Auto-accepted folder trust for $pane"
    fi

    sleep "$POLL"
    elapsed=$((elapsed + POLL))
  done
  return 1
}

# ── step 1: create panes ─────────────────────────────────────────────

echo "🚀 Splitting current window into $LANE_COUNT panes ($SESSION)"
echo ""

PANE_IDS=()
for i in $(seq 0 $((LANE_COUNT - 1))); do
  LANE_NAME=$(jq -r ".[$i].name" "$LANES_FILE")
  LANE_ID=$(jq -r ".[$i].id" "$LANES_FILE")

  if (( i == 0 )); then
    PANE_ID=$(tmux split-window -h -c "$CWD" -P -F '#{pane_id}')
  elif (( i % 2 == 1 )); then
    PANE_ID=$(tmux split-window -v -t "${PANE_IDS[$((i-1))]}" -c "$CWD" -P -F '#{pane_id}')
  else
    PANE_ID=$(tmux split-window -v -t "${PANE_IDS[$((i-2))]}" -c "$CWD" -P -F '#{pane_id}')
  fi
  PANE_IDS+=("$PANE_ID")

  tmux set-option -p -t "$PANE_ID" @omp_launch_uuid "$LAUNCH_ID"
  tmux set-option -p -t "$PANE_ID" @omp_lane_id "$LANE_ID"
  tmux select-pane -t "$PANE_ID" -T "$LANE_ID: $LANE_NAME"
  tmux send-keys -t "$PANE_ID" "$AGENT_CMD" C-m

  echo "  ✅ Pane $PANE_ID → $LANE_NAME"
done

tmux select-layout tiled

# ── step 2: wait for readiness ───────────────────────────────────────

echo ""
echo "⏳ Waiting for agents to initialise (up to ${MAX_READY}s)..."

for i in $(seq 0 $((LANE_COUNT - 1))); do
  PANE_ID="${PANE_IDS[$i]}"
  LANE_NAME=$(jq -r ".[$i].name" "$LANES_FILE")
  if wait_for_ready "$PANE_ID"; then
    echo "  ✅ $PANE_ID ($LANE_NAME) ready"
  else
    echo "  ⚠️  $PANE_ID ($LANE_NAME) not ready after ${MAX_READY}s — sending anyway"
  fi
done

# ── step 3: send prompts (literal text + Enter separately) ───────────

echo ""
echo "📨 Sending prompts..."
for i in $(seq 0 $((LANE_COUNT - 1))); do
  LANE_PROMPT=$(jq -r ".[$i].prompt" "$LANES_FILE")
  LANE_NAME=$(jq -r ".[$i].name" "$LANES_FILE")
  LANE_ID=$(jq -r ".[$i].id" "$LANES_FILE")
  PANE_ID="${PANE_IDS[$i]}"

  # Append a deterministic delivery instruction: the worker writes its final
  # result to a file so the lead's `omp team collect` knows it's done (vs
  # guessing from the pane). Kept on one line so send-keys submits cleanly.
  LANE_PROMPT="$LANE_PROMPT  IMPORTANT: when fully finished, write your complete final result to the file $DELIVERY_DIR/$LANE_ID.result.md (e.g. with a heredoc), then stop."

  # -l = literal (no key interpretation), then submit. Use the `Enter` key NAME,
  # not C-m: Copilot CLI >=1.0.61 ignores a literal carriage return, so C-m left
  # the prompt sitting unsent in the input buffer and the agent never started.
  tmux send-keys -t "$PANE_ID" -l "$LANE_PROMPT"
  sleep 0.3
  tmux send-keys -t "$PANE_ID" Enter

  echo "  📨 Sent to $PANE_ID ($LANE_NAME)"
done

tmux select-pane -t '{left}'

# Write the manifest before registration so the control CLI can validate the
# exact launch generation and pane map before the monitor discovers it.
MANIFEST="[]"
for i in $(seq 0 $((LANE_COUNT - 1))); do
  MANIFEST=$(echo "$MANIFEST" | jq \
    --arg id "$(jq -r ".[$i].id" "$LANES_FILE")" \
    --arg name "$(jq -r ".[$i].name" "$LANES_FILE")" \
    --arg pane "${PANE_IDS[$i]}" \
    '. + [{id:$id,name:$name,paneId:$pane}]')
done
echo "$MANIFEST" > "$DELIVERY_DIR/manifest.json"

if [[ -n "$CONTROL_CLI" ]]; then
  TMUX_IDENTITY=$(tmux display-message -p -t "${PANE_IDS[0]}" \
    -F '#{socket_path}|#{pid}|#{start_time}|#{session_id}|#{session_created}|#{window_id}')
  IFS='|' read -r SOCKET_PATH SERVER_PID SERVER_START_TIME SESSION_ID SESSION_CREATED WINDOW_ID _ <<< "$TMUX_IDENTITY"

  if ! "$CONTROL_CLI" team register-visual \
    --root "$CWD" \
    --name "$SESSION" \
    --launch-id "$LAUNCH_ID" \
    --dir "$DELIVERY_DIR" \
    --manifest "$DELIVERY_DIR/manifest.json" \
    --socket "$SOCKET_PATH" \
    --server-pid "$SERVER_PID" \
    --server-start-time "$SERVER_START_TIME" \
    --session-id "$SESSION_ID" \
    --session-created "$SESSION_CREATED" \
    --window-id "$WINDOW_ID" \
    --json >/dev/null; then
    echo "⚠️  Visual team registration failed; agents remain available in tmux" >&2
  fi
fi

# Prompts are sent — in --no-monitor mode return now so the caller (a Copilot
# lead) doesn't block on the long monitor loop and doesn't get killed mid-run
# by its shell-tool cleanup. The agents keep working in the panes for the user
# to watch; this is the default for the in-session visual flow.
if [[ -n "$NO_MONITOR" ]]; then
  echo ""
  echo "✅ $LANE_COUNT agents launched and prompted ($SESSION)."
  echo "📋 Lane → pane:"
  for i in $(seq 0 $((LANE_COUNT - 1))); do
    echo "   $(jq -r ".[$i].name" "$LANES_FILE") → ${PANE_IDS[$i]}"
  done
  echo ""
  echo "➡️  Collect — poll this until allDone, then read each lane's result and synthesize:"
  if [[ -n "$CONTROL_CLI" ]]; then
    printf '   %q team collect --dir %q --json\n' "$CONTROL_CLI" "$DELIVERY_DIR"
  else
    echo "   omp team collect --dir $DELIVERY_DIR --json"
  fi
  exit 0
fi

# ── step 4: monitor completion ───────────────────────────────────────

echo ""
echo "⏳ Monitoring agents for completion (up to ${MAX_DONE}s)..."

# Brief pause so agents start processing before we poll
sleep 5

# State per lane: 0=waiting-for-busy, 1=busy, 2=done
LANE_STATE=()
for i in $(seq 0 $((LANE_COUNT - 1))); do LANE_STATE[$i]=0; done

COMPLETED=0
ELAPSED=0
while (( COMPLETED < LANE_COUNT && ELAPSED < MAX_DONE )); do
  sleep "$POLL"
  ELAPSED=$((ELAPSED + POLL))

  for i in $(seq 0 $((LANE_COUNT - 1))); do
    [[ "${LANE_STATE[$i]}" == "2" ]] && continue

    PANE_ID="${PANE_IDS[$i]}"
    LANE_NAME=$(jq -r ".[$i].name" "$LANES_FILE")

    # Pane died?
    if ! tmux list-panes -a -F '#{pane_id}' 2>/dev/null | grep -q "^${PANE_ID}$"; then
      echo "  ❌ $PANE_ID ($LANE_NAME) — pane died"
      LANE_STATE[$i]=2; COMPLETED=$((COMPLETED + 1)); continue
    fi

    local_capture=$(pane_text "$PANE_ID" 15)

    # State 0→1: agent started working (response marker ● appears)
    if [[ "${LANE_STATE[$i]}" == "0" ]]; then
      if echo "$local_capture" | grep -q '●'; then
        LANE_STATE[$i]=1
      fi
      continue
    fi

    # State 1→2: agent finished (back to idle — '/ commands' in last 5 lines)
    if echo "$local_capture" | tail -5 | grep -q '/ commands'; then
      echo "  ✅ $PANE_ID ($LANE_NAME) — agent finished"
      LANE_STATE[$i]=2; COMPLETED=$((COMPLETED + 1))
    fi
  done
done

echo ""
if (( COMPLETED == LANE_COUNT )); then
  echo "🎉 All $LANE_COUNT agents completed!"
else
  echo "⏰ Timeout — $((LANE_COUNT - COMPLETED)) agent(s) still running"
fi

# ── summary ──────────────────────────────────────────────────────────

echo ""
echo "═══ Results Summary ═══"
for i in $(seq 0 $((LANE_COUNT - 1))); do
  PANE_ID="${PANE_IDS[$i]}"
  LANE_NAME=$(jq -r ".[$i].name" "$LANES_FILE")
  LANE_ID=$(jq -r ".[$i].id" "$LANES_FILE")
  echo ""
  echo "── $LANE_ID: $LANE_NAME ($PANE_ID) ──"
  if tmux list-panes -a -F '#{pane_id}' 2>/dev/null | grep -q "^${PANE_ID}$"; then
    pane_text "$PANE_ID" 40 | grep -E '●|✅|❌|⚠|error|Error|FAIL|PASS|done|Done' | tail -10 || echo "  (no notable output captured)"
  else
    echo "  (pane no longer exists)"
  fi
done

echo ""
echo "Pane IDs: ${PANE_IDS[*]}"
echo "Navigate: Ctrl-b + arrow keys"
echo "💡 Agents are interactive — send follow-up prompts to any pane"
