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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MAIN_BRANCH="${SWARMFORGE_SCRIPTS_BRANCH:-main}"
ROLES_BRANCH="${SWARMFORGE_ROLES_BRANCH:-$MAIN_BRANCH}"
_REPO_BASE="${SWARMFORGE_REPO_URL:-https://github.com/gabadi/swarm-forge}"
ARCHIVE_URL="${SWARMFORGE_SCRIPTS_URL:-${_REPO_BASE}/archive/refs/heads/${MAIN_BRANCH}.tar.gz}"
ROLES_ARCHIVE_URL="${SWARMFORGE_ROLES_URL:-${_REPO_BASE}/archive/refs/heads/${ROLES_BRANCH}.tar.gz}"
TMP_DIR=""
ROLES_TMP_DIR=""
MATTPOCOCK_TMP_DIR=""

cleanup() {
  [[ -n "$TMP_DIR" ]] && rm -rf "$TMP_DIR"
  [[ -n "$ROLES_TMP_DIR" ]] && rm -rf "$ROLES_TMP_DIR"
  [[ -n "$MATTPOCOCK_TMP_DIR" ]] && rm -rf "$MATTPOCOCK_TMP_DIR"
}
trap cleanup EXIT

install_mattpocock_skills() {
  local pins_file="$SCRIPT_DIR/swarmforge/scripts/install-pins.conf"
  [[ ! -f "$pins_file" ]] && return 0
  local sha="" include=""
  while IFS='=' read -r _k _v; do
    [[ "$_k" =~ ^# ]] && continue
    _k="${_k// /}"; _v="${_v// /}"
    [[ "$_k" == "MATTPOCOCK_SKILLS_SHA" ]] && sha="$_v"
    [[ "$_k" == "MATTPOCOCK_SKILLS_INCLUDE" ]] && include="$_v"
  done < "$pins_file"
  [[ -z "$sha" ]] && return 0
  local sentinel="$SCRIPT_DIR/.swarmforge/mattpocock-skills-installed"
  if [[ -f "$sentinel" ]] && [[ "$(cat "$sentinel")" == "$sha" ]]; then
    echo "  mattpocock skills already at ${sha:0:8}, skipping"
    return 0
  fi
  echo "  Installing mattpocock skills (${sha:0:8})..."
  MATTPOCOCK_TMP_DIR="$(mktemp -d)"
  if ! curl -fsSL "https://github.com/mattpocock/skills/archive/${sha}.tar.gz" | tar -xz --strip-components=1 -C "$MATTPOCOCK_TMP_DIR"; then
    echo "  ⚠ mattpocock skills unavailable (network error) — skipping"
    return 0
  fi
  local skills_base="$MATTPOCOCK_TMP_DIR/skills"
  [[ ! -d "$skills_base" ]] && return 0
  IFS=',' read -ra _inc_arr <<< "$include"
  local dsts=("$SCRIPT_DIR/.claude/skills")
  for _wt in "$SCRIPT_DIR/.worktrees"/*/; do
    [[ -d "$_wt/.claude/skills" ]] && dsts+=("$_wt/.claude/skills")
  done
  # Search all subdirs (engineering, productivity, etc.) for included skills
  while IFS= read -r -d '' _skill_dir; do
    local _name; _name="$(basename "$_skill_dir")"
    local _ok=false
    if [[ -z "$include" ]]; then
      _ok=true
    else
      for _i in "${_inc_arr[@]}"; do
        _i="${_i// /}"
        [[ "$_name" == "$_i" ]] && _ok=true && break
      done
    fi
    [[ "$_ok" != "true" ]] && continue
    rm -rf "$SCRIPT_DIR/swarmforge/skills/$_name"
    cp -R "$_skill_dir" "$SCRIPT_DIR/swarmforge/skills/$_name"
    for _dst in "${dsts[@]}"; do
      mkdir -p "$_dst"
      rm -rf "$_dst/$_name"
      cp -R "$_skill_dir" "$_dst/$_name"
    done
    echo "  ✓ $_name"
  done < <(find "$skills_base" -mindepth 2 -maxdepth 2 -type d -print0)
  mkdir -p "$SCRIPT_DIR/.swarmforge"
  echo "$sha" > "$sentinel"
  rm -rf "$MATTPOCOCK_TMP_DIR"; MATTPOCOCK_TMP_DIR=""
}

if [[ "${1:-}" == "stop" ]]; then
  STATE_DIR="$SCRIPT_DIR/.swarmforge"
  CLEANUP_SCRIPT="$SCRIPT_DIR/swarmforge/scripts/swarm-cleanup.sh"
  if [[ ! -f "$STATE_DIR/tmux-socket" ]]; then
    echo "No running swarm found (.swarmforge/tmux-socket missing)." >&2
    exit 1
  fi
  if [[ ! -f "$CLEANUP_SCRIPT" ]]; then
    echo "swarm-cleanup.sh not found — run ./swarm once to bootstrap scripts." >&2
    exit 1
  fi
  _tmux_socket="$(< "$STATE_DIR/tmux-socket")"
  _sessions=()
  if [[ -f "$STATE_DIR/sessions.tsv" ]]; then
    while IFS=$'\t' read -r _ _ _session _; do
      [[ -n "${_session:-}" ]] && _sessions+=("$_session")
    done < "$STATE_DIR/sessions.tsv"
  fi
  SWARMFORGE_TERMINAL_BACKEND="${SWARMFORGE_TERMINAL_BACKEND:-${SWARMFORGE_TERMINAL:-ghostty}}" \
    "$CLEANUP_SCRIPT" \
    "$_tmux_socket" \
    "$STATE_DIR/window-ids" \
    "${_sessions[@]+"${_sessions[@]}"}"
  echo "SwarmForge stopped."
  exit 0
fi

if [[ "${1:-}" == "upgrade" ]]; then
  echo "Upgrading swarmforge scripts from $MAIN_BRANCH, roles from $ROLES_BRANCH..."

  # Re-fetch scripts (force by removing existing)
  rm -rf "$SCRIPT_DIR/swarmforge/scripts"
  TMP_DIR="$(mktemp -d)"
  curl -L "$ARCHIVE_URL" | tar -xz --strip-components=1 -C "$TMP_DIR"
  cp -R "$TMP_DIR/swarmforge/scripts" "$SCRIPT_DIR/swarmforge/scripts"

  # Overwrite shared articles from the downloaded archive
  if [[ -d "$TMP_DIR/swarmforge/constitution/articles" ]]; then
    mkdir -p "$SCRIPT_DIR/swarmforge/scripts/shared-articles"
    cp -R "$TMP_DIR/swarmforge/constitution/articles/." "$SCRIPT_DIR/swarmforge/scripts/shared-articles/"
    mkdir -p "$SCRIPT_DIR/swarmforge/constitution/articles"
    for _article in "$SCRIPT_DIR/swarmforge/scripts/shared-articles"/*.prompt; do
      cp "$_article" "$SCRIPT_DIR/swarmforge/constitution/articles/$(basename "$_article")"
    done
  fi

  # Update roles — use a separate archive if ROLES_BRANCH differs from MAIN_BRANCH
  if [[ "$ROLES_BRANCH" == "$MAIN_BRANCH" ]]; then
    _roles_src="$TMP_DIR"
  else
    ROLES_TMP_DIR="$(mktemp -d)"
    curl -L "$ROLES_ARCHIVE_URL" | tar -xz --strip-components=1 -C "$ROLES_TMP_DIR"
    _roles_src="$ROLES_TMP_DIR"
  fi
  if [[ -d "$_roles_src/swarmforge/roles" ]]; then
    cp -R "$_roles_src/swarmforge/roles/." "$SCRIPT_DIR/swarmforge/roles/"
  fi

  # Update skills
  if [[ -d "$_roles_src/swarmforge/skills" ]]; then
    rm -rf "$SCRIPT_DIR/swarmforge/skills"
    cp -R "$_roles_src/swarmforge/skills" "$SCRIPT_DIR/swarmforge/skills"
  fi

  # Install pinned external skills (mattpocock et al.) and refresh all worktrees
  install_mattpocock_skills

  echo "SwarmForge upgraded."
  exit 0
fi

if [[ ! -d "$SCRIPT_DIR/swarmforge/scripts" || ! -d "$SCRIPT_DIR/swarmforge/scripts/shared-articles" || ! -d "$SCRIPT_DIR/swarmforge/skills" ]]; then
  TMP_DIR="$(mktemp -d)"
  mkdir -p "$SCRIPT_DIR/swarmforge"
  curl -L "$ARCHIVE_URL" | tar -xz --strip-components=1 -C "$TMP_DIR"
  if [[ ! -d "$SCRIPT_DIR/swarmforge/scripts" ]]; then
    cp -R "$TMP_DIR/swarmforge/scripts" "$SCRIPT_DIR/swarmforge/scripts"
  fi
  if [[ -d "$TMP_DIR/swarmforge/constitution/articles" ]]; then
    mkdir -p "$SCRIPT_DIR/swarmforge/scripts/shared-articles"
    cp -R "$TMP_DIR/swarmforge/constitution/articles/." "$SCRIPT_DIR/swarmforge/scripts/shared-articles/"
  fi
  if [[ ! -d "$SCRIPT_DIR/swarmforge/skills" && -d "$TMP_DIR/swarmforge/skills" ]]; then
    cp -R "$TMP_DIR/swarmforge/skills" "$SCRIPT_DIR/swarmforge/skills"
  fi
fi

# Copy shared articles into constitution/articles/ if not already present.
# Runs unconditionally — projects installed from a pre-packaged branch already
# ship scripts/shared-articles/ so the download block above is skipped, but the
# articles still need to land in constitution/articles/ for agent bundles to include them.
if [[ -d "$SCRIPT_DIR/swarmforge/scripts/shared-articles" ]]; then
  mkdir -p "$SCRIPT_DIR/swarmforge/constitution/articles"
  for _article in "$SCRIPT_DIR/swarmforge/scripts/shared-articles"/*.prompt; do
    _dest="$SCRIPT_DIR/swarmforge/constitution/articles/$(basename "$_article")"
    [[ ! -f "$_dest" ]] && cp "$_article" "$_dest"
  done
fi

# Install local skills immediately so /setup-swarm is available in Claude Code
# before swarmforge.sh runs and before setup-complete exists.
if [[ -d "$SCRIPT_DIR/swarmforge/skills" ]]; then
  mkdir -p "$SCRIPT_DIR/.claude/skills"
  for _skill_dir in "$SCRIPT_DIR/swarmforge/skills"/*/; do
    _skill_name="$(basename "$_skill_dir")"
    cp -R "$_skill_dir" "$SCRIPT_DIR/.claude/skills/$_skill_name"
  done
fi

exec "$SCRIPT_DIR/swarmforge/scripts/swarmforge.sh" "$@"
