#!/usr/bin/env bash
# Wrapper: resolves the sharedserver binary, fetching it if necessary.
#   1. $SHAREDSERVER_BIN
#   2. PATH (skipping ourselves to avoid recursion)
#   3. ~/.cargo/bin, ~/.local/bin, /opt/homebrew/bin, /usr/local/bin
#   4. download a pinned release via the cargo-dist installer  <-- the tail
#
# (4) is what lets a bare plugin install work with no Rust toolchain.
#
# Behaviourally identical to the OpenCode resolver (plugins/opencode/src/index.ts) —
# same ladder, floor, warnings and fallback — so both clients answer "which
# sharedserver am I on, and why" the same way. Change them together.

set -eu

# --- Version floor ----------------------------------------------------------------
# The floor IS the pin: what we would install is exactly what counts as new enough, so
# it is one number read from the manifest, self-maintaining via lockstep releases. Two
# constants could disagree, accepting a version older than the one we would fetch.
# The test is >=, so a newer local install is never undone; a bump does cost a user one
# patch behind a single download.
#
# HARDCODED_FLOOR is the backstop for an unreadable manifest: 0.5.0 added the PID-reuse
# guard, without which a recycled client PID can hold a server open indefinitely.
HARDCODED_FLOOR="0.5.0"

# --- Per-repo policy -------------------------------------------------------------
# This file is vendored BYTE-IDENTICAL into the consuming plugins (mcp-companion,
# cribsheet, svg-mcp) by their scripts/sync-vendored.sh, so the drift check is a plain
# diff. Everything that differs between them lives in the optional conf beside it:
#
#   SS_LABEL          prefix for user-facing messages     (default: sharedserver)
#   SS_MIN_VERSION    floor; empty => this plugin's own version (lockstep)
#   SS_INSTALLER_URL  installer to fetch; empty => pin to this plugin's version
#
# Empty defaults give sharedserver's own behaviour: floor IS the pin, both read from
# the manifest. Consumers set all three, because they use sharedserver rather than
# shipping it — "new enough" is the right test, and a pinned version in three
# unrelated repos would be a number to hand-bump forever.
_conf="$(dirname "$0")/sharedserver.conf"
# shellcheck source=/dev/null
[ -f "$_conf" ] && . "$_conf"
: "${SS_LABEL:=sharedserver}"
: "${SS_MIN_VERSION:=}"
: "${SS_INSTALLER_URL:=}"

version_ge() { # version_ge A B -> success when dotted-numeric prefix of A >= B
  local a b i x y
  local IFS=.
  read -r -a a <<<"${1%%[!0-9.]*}"
  read -r -a b <<<"${2%%[!0-9.]*}"
  for i in 0 1 2; do
    x="${a[i]:-0}"; y="${b[i]:-0}"
    ((10#${x:-0} > 10#${y:-0})) && return 0
    ((10#${x:-0} < 10#${y:-0})) && return 1
  done
  return 0
}

_version_of() { # dotted version of a sharedserver command, or empty
  "$1" --version 2>/dev/null | awk '{print $2}'
}

# Version to fetch. Pinned to THIS PLUGIN's version so the pair moves in lockstep
# (scripts/bump-version.sh writes both) — derived from the manifest, never
# duplicated as a constant here.
_plugin_version() {
  local pj="${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}/.claude-plugin/plugin.json"
  [ -f "$pj" ] || return 1
  if command -v jq >/dev/null 2>&1; then
    jq -r '.version // empty' <"$pj"
  else
    sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$pj" | head -1
  fi
}

# The one number: what we would install, and therefore what we require. A consumer
# overrides it via SS_MIN_VERSION, since its own version has nothing to do with
# sharedserver's.
_ver="$(_plugin_version || true)"
MIN_SHAREDSERVER_VERSION="${SS_MIN_VERSION:-${_ver:-$HARDCODED_FLOOR}}"

_probe() { # echo the first sharedserver found (ANY version), or nothing
  if [ -n "${SHAREDSERVER_BIN:-}" ] && [ -x "$SHAREDSERVER_BIN" ]; then
    printf '%s' "$SHAREDSERVER_BIN"; return 0
  fi
  local real
  if real="$(command -v sharedserver 2>/dev/null)" && [ -x "$real" ] && [ "$real" != "$0" ]; then
    printf '%s' "$real"; return 0
  fi
  local candidate
  for candidate in \
    "$HOME/.cargo/bin/sharedserver" \
    "$HOME/.local/bin/sharedserver" \
    "/opt/homebrew/bin/sharedserver" \
    "/usr/local/bin/sharedserver"; do
    if [ -x "$candidate" ]; then printf '%s' "$candidate"; return 0; fi
  done
  return 1
}

# An explicit SHAREDSERVER_BIN is never second-guessed: the user named a specific
# binary, so silently downloading a different one would be the wrong answer to that.
# Warn if it is old, then honour it anyway.
if [ -n "${SHAREDSERVER_BIN:-}" ] && [ -x "$SHAREDSERVER_BIN" ]; then
  _v="$(_version_of "$SHAREDSERVER_BIN")"
  if [ -n "$_v" ] && ! version_ge "$_v" "$MIN_SHAREDSERVER_VERSION"; then
    echo "${SS_LABEL}: SHAREDSERVER_BIN points at version $_v; this plugin ships against ${MIN_SHAREDSERVER_VERSION}." >&2
    echo "  Using it anyway because you set it explicitly. Upgrade with: cargo install sharedserver" >&2
  fi
  exec "$SHAREDSERVER_BIN" "$@"
fi

# $_ver was resolved at the top — it is both the floor and the pin.
_base="https://github.com/georgeharker/sharedserver/releases/download"
if [ -n "$SS_INSTALLER_URL" ]; then
  _url="$SS_INSTALLER_URL"
  _what="the latest release"
elif [ -n "$_ver" ]; then
  _url="$_base/v${_ver}/sharedserver-installer.sh"
  _what="v${_ver}"
else
  _url="https://github.com/georgeharker/sharedserver/releases/latest/download/sharedserver-installer.sh"
  _what="the latest release"
fi

_stale=""
if _found="$(_probe)"; then
  _v="$(_version_of "$_found")"
  if [ -n "$_v" ] && version_ge "$_v" "$MIN_SHAREDSERVER_VERSION"; then
    exec "$_found" "$@"
  fi
  # Too old (or unreadable — pre-0.5 releases still answered --version, so empty
  # means something unexpected, and we treat that as suspect too). Fall through to
  # fetch a known-good release, but REMEMBER it: if the download fails we would
  # rather run the old binary than nothing.
  _stale="$_found"
  echo "${SS_LABEL}: found ${_found} at version ${_v:-unknown}; this plugin ships against ${MIN_SHAREDSERVER_VERSION}." >&2
  echo "  Fetching ${_what} instead." >&2
  echo "  To keep your own build instead, set SHAREDSERVER_BIN=${_found}" >&2
fi

# --- Fetch a pinned release --------------------------------------------------------
#
# Locked because this runs from SessionStart and people open several sessions at once;
# the installer is not safe to run concurrently against one target path. `mkdir` is
# atomic everywhere and needs no helper; the PID inside is for diagnosis, not liveness.
# The loser waits and re-probes rather than installing too.
_lockdir="${TMPDIR:-/tmp}/.sharedserver-install.lock"
_have_lock=0
_cleanup() { [ "$_have_lock" = 1 ] && rm -rf "$_lockdir" 2>/dev/null || true; }
trap _cleanup EXIT INT TERM

# Always exec through this once the lock may be held: `exec` replaces the process, so
# the EXIT trap never runs and a bare exec leaks the lock — after which every later run
# burns its full 20s wait on phantom contention.
_exec() {
  _cleanup
  exec "$@"
}

_fallback_or_die() { # use the stale binary if we have one, else fail
  if [ -n "$_stale" ]; then
    echo "  Continuing with the existing ${_stale} despite its version." >&2
    _exec "$_stale" "$@"
  fi
  _cleanup
  exit 127
}

if mkdir "$_lockdir" 2>/dev/null; then
  _have_lock=1
  printf '%s' "$$" >"$_lockdir/pid" 2>/dev/null || true
else
  # Someone else is installing. Wait, then re-probe — bounded, because a
  # SessionStart hook that blocks forever is worse than one that degrades.
  _waited=0
  while [ -d "$_lockdir" ] && [ "$_waited" -lt 20 ]; do
    sleep 1
    _waited=$((_waited + 1))
  done
  if _found="$(_probe)"; then
    _v="$(_version_of "$_found")"
    if [ -n "$_v" ] && version_ge "$_v" "$MIN_SHAREDSERVER_VERSION"; then
      _exec "$_found" "$@"
    fi
  fi
  if ! mkdir "$_lockdir" 2>/dev/null; then
    echo "${SS_LABEL}: another process is installing sharedserver and did not finish." >&2
    echo "  If this persists, remove the stale lock: rm -rf $_lockdir" >&2
    _fallback_or_die "$@"
  fi
  _have_lock=1
fi

# Re-probe under the lock: the winner may have finished between our failed mkdir
# and acquiring it. Without this the loser reinstalls what it just waited for.
if _found="$(_probe)"; then
  _v="$(_version_of "$_found")"
  if [ -n "$_v" ] && version_ge "$_v" "$MIN_SHAREDSERVER_VERSION"; then
    _exec "$_found" "$@"
  fi
fi

if ! command -v curl >/dev/null 2>&1; then
  echo "${SS_LABEL}: not found, and curl is unavailable to fetch it." >&2
  echo "  Install it with: cargo install sharedserver" >&2
  _fallback_or_die "$@"
fi

# Announce, once. This only ever prints when we are ABOUT to install — i.e. exactly
# on the first run that finds nothing usable — so it needs no marker file to stay
# one-time. It is informational, not a prompt: the install proceeds either way.
if [ -z "$_stale" ]; then
  echo "${SS_LABEL}: no usable sharedserver found; fetching ${_what} (one time)." >&2
  echo "  This needs no Rust toolchain. To use your own build instead, set SHAREDSERVER_BIN." >&2
fi

# Download to a file, then run it — NOT `curl … | sh`, whose exit status is sh's, so a
# 404 reads as success (curl fails, emits nothing, sh exits 0 on empty input). Staging
# also lets a truncated download fail the size check instead of half-executing.
# --proto '=https' --tlsv1.2 match cargo-dist's own install line.
_script="$_lockdir/installer.sh"
if ! curl --proto '=https' --tlsv1.2 -LsSf "$_url" -o "$_script" 2>/dev/null; then
  echo "${SS_LABEL}: could not download the installer from $_url" >&2
  echo "  (a release for v${_ver:-?} may not exist yet, or the network is unavailable)" >&2
  _fallback_or_die "$@"
fi
if [ ! -s "$_script" ]; then
  echo "${SS_LABEL}: the downloaded installer was empty (from $_url)." >&2
  _fallback_or_die "$@"
fi

# cargo-dist embeds the expected sha256 but looks up only `sha256sum` and SKIPS
# verification when it is missing — i.e. always, on macOS, which ships `shasum -a 256`.
# Give it a sha256sum (identical output) rather than execute an unverified binary.
if ! command -v sha256sum >/dev/null 2>&1; then
  if command -v shasum >/dev/null 2>&1; then
    printf '#!/bin/sh\nexec shasum -a 256 "$@"\n' >"$_lockdir/sha256sum"
    chmod +x "$_lockdir/sha256sum"
    PATH="$_lockdir:$PATH"
    export PATH
  else
    echo "${SS_LABEL}: refusing to install — neither sha256sum nor shasum is available," >&2
    echo "  so the download could not be checksum-verified." >&2
    _fallback_or_die "$@"
  fi
fi

if ! sh "$_script" >&2; then
  echo "${SS_LABEL}: the installer ran but failed (from $_url)." >&2
  _fallback_or_die "$@"
fi

# The installer lands in ~/.cargo/bin or ~/.local/bin, both already in the probe
# list — so re-probing is how we find what it just wrote, rather than assuming a path.
if _found="$(_probe)"; then
  _exec "$_found" "$@"
fi

echo "${SS_LABEL}: install reported success but no binary was found afterwards." >&2
echo "  Looked in: \$SHAREDSERVER_BIN, PATH, ~/.cargo/bin, ~/.local/bin," >&2
echo "             /opt/homebrew/bin, /usr/local/bin" >&2
_fallback_or_die "$@"
