#!/usr/bin/env bash
#
# plugin-refresh.sh  -  bring the stack plugins to the latest published version.
#
# Two steps, because they are two different things: `claude plugin marketplace
# update` refreshes the catalog, and each installed plugin then needs its own
# `claude plugin update` in the scope it was installed in. A project or local
# install is updated from inside its own project, because that is how the CLI
# tells two projects' installs apart. The catalog refresh alone leaves every
# installed plugin where it was.
#
# Usage: plugin-refresh.sh <owner> [--add-only]
#   <owner>      GitHub owner of the multi-agent-plugins repository
#   --add-only   make sure the marketplace is configured, update nothing
#
# The CLI's own error output is passed through, never discarded.
# Exit codes: 0 = done (or no claude CLI on this machine), 1 = a step failed

set -uo pipefail

OWNER="${1:-}"
MODE="${2:-}"
MP="multi-agent-plugins"
CLAUDE="${CLAUDE_BIN:-claude}"

if [ -z "$OWNER" ]; then
  echo "usage: plugin-refresh.sh <owner> [--add-only]" >&2
  exit 1
fi

if ! command -v "$CLAUDE" >/dev/null 2>&1; then
  echo "  -> claude CLI not found; stack plugins not refreshed"
  exit 0
fi

FAILED=0

if ! "$CLAUDE" plugin marketplace list 2>/dev/null | grep -q "$MP"; then
  if "$CLAUDE" plugin marketplace add "$OWNER/$MP"; then
    echo "  -> marketplace $MP added"
  else
    echo "  -> could not add marketplace $OWNER/$MP" >&2
    exit 1
  fi
fi

[ "$MODE" = "--add-only" ] && exit 0

if "$CLAUDE" plugin marketplace update "$MP"; then
  echo "  -> marketplace $MP refreshed"
else
  echo "  -> marketplace $MP refresh failed" >&2
  FAILED=1
fi

INSTALLED=$("$CLAUDE" plugin list --json 2>/dev/null | node -e '
let s = "";
process.stdin.on("data", (d) => (s += d)).on("end", () => {
  let rows = [];
  try { rows = JSON.parse(s); } catch { process.exit(0); }
  const seen = new Set();
  for (const r of Array.isArray(rows) ? rows : []) {
    if (typeof r.id !== "string" || !r.id.endsWith("@" + process.argv[1])) continue;
    const scope = r.scope || "user";
    const dir = scope === "project" || scope === "local" ? r.projectPath || "" : "";
    if ((scope === "project" || scope === "local") && !dir) continue;
    const key = [r.id, scope, dir].join("\t");
    if (seen.has(key)) continue;
    seen.add(key);
    console.log(key);
  }
});' "$MP")

while IFS=$'\t' read -r ID SCOPE DIR; do
  [ -n "$ID" ] || continue
  WHERE="$SCOPE${DIR:+ $DIR}"
  if [ -n "$DIR" ] && [ ! -d "$DIR" ]; then
    echo "  -> $ID ($WHERE) skipped, project directory is gone"
    continue
  fi
  if (cd "${DIR:-$PWD}" && "$CLAUDE" plugin update "$ID" --scope "$SCOPE"); then
    echo "  -> $ID ($WHERE) updated"
  else
    echo "  -> $ID ($WHERE) update failed" >&2
    FAILED=1
  fi
done <<EOF
$INSTALLED
EOF

[ "$FAILED" -eq 0 ] || exit 1
exit 0
