#!/usr/bin/env bash
# SessionStart hook — ensure Python interpreter + deps available for ASU Canvas Builder.
# True plug-and-play: if system Python missing or <3.9, installs uv (Astral) then
# a managed standalone Python (3.12) and deps into a plugin-local venv.
# Idempotent: tracks requirements.txt hash in marker file, skips if unchanged.

set -u

PLUGIN_ROOT="${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}}}"
REQ="${PLUGIN_ROOT}/scripts/requirements.txt"
MARKER="${PLUGIN_ROOT}/.deps-installed"
VENV="${PLUGIN_ROOT}/.venv"
BIN_DIR="${PLUGIN_ROOT}/bin"
PYBIN_FILE="${PLUGIN_ROOT}/.python-bin"

[ -f "$REQ" ] || exit 0

log()  { echo "[asu-canvas-builder] $*" >&2; }
warn() { echo "[asu-canvas-builder] $*" >&2; }

# --- hash requirements for idempotency ---
if command -v shasum >/dev/null 2>&1; then
  HASH=$(shasum -a 256 "$REQ" | awk '{print $1}')
elif command -v sha256sum >/dev/null 2>&1; then
  HASH=$(sha256sum "$REQ" | awk '{print $1}')
else
  HASH=$(wc -c <"$REQ")
fi

# Fast path: marker matches AND wrapper exists
if [ -f "$MARKER" ] && [ "$(cat "$MARKER" 2>/dev/null)" = "$HASH" ] && [ -x "${BIN_DIR}/python3" ]; then
  exit 0
fi

mkdir -p "$BIN_DIR"

# --- detect system Python >= 3.9 ---
SYSTEM_PY=""
check_py() {
  local cmd="$1"
  command -v "$cmd" >/dev/null 2>&1 || return 1
  "$cmd" -c 'import sys; sys.exit(0 if sys.version_info >= (3,9) else 1)' >/dev/null 2>&1 || return 1
  echo "$cmd"
}
SYSTEM_PY=$(check_py python3 || check_py python || true)

USE_MANAGED=0
if [ -z "$SYSTEM_PY" ]; then
  USE_MANAGED=1
fi

# --- managed Python via uv (fallback path) ---
if [ "$USE_MANAGED" = "1" ]; then
  log "System Python 3.9+ not found. Installing managed Python via uv (Astral)..."

  UV_BIN=""
  if command -v uv >/dev/null 2>&1; then
    UV_BIN=$(command -v uv)
  elif [ -x "$HOME/.local/bin/uv" ]; then
    UV_BIN="$HOME/.local/bin/uv"
  else
    log "Installing uv..."
    # S5: Pin to a specific uv release installer (immutable URL) and verify SHA-256 before
    # executing.  Never pipe an unpinned URL directly to sh.
    #
    # To refresh on a uv bump:
    #   1. Run: gh api repos/astral-sh/uv/releases/latest --jq .tag_name
    #   2. Download: curl -LsSf "https://github.com/astral-sh/uv/releases/download/<TAG>/uv-installer.sh" -o /tmp/uv-inst.sh
    #   3. Hash:    shasum -a 256 /tmp/uv-inst.sh | awk '{print $1}'
    #   4. Update UV_VERSION and UV_SHA256 below.
    UV_VERSION="0.11.21"
    UV_INSTALLER_URL="https://github.com/astral-sh/uv/releases/download/${UV_VERSION}/uv-installer.sh"
    UV_SHA256="053045e1e69ec77358fd44f2ef2cacb768a22d50f433e213624f0157ffbbc883"

    _uv_tmp=$(mktemp /tmp/asucb-uv-installer-XXXXXX.sh)
    # Download pinned installer; log to the standard log file.
    if ! curl -LsSf "$UV_INSTALLER_URL" -o "$_uv_tmp" >/tmp/asucb-uv-install.log 2>&1; then
      warn "uv installer download failed. Details: /tmp/asucb-uv-install.log"
      warn "Manual fix: install Python 3.9+ from https://www.python.org/downloads/ then reload."
      rm -f "$_uv_tmp"
      exit 0
    fi

    # Verify SHA-256 before executing (prefer shasum on macOS, fall back to sha256sum on Linux).
    _uv_actual=""
    if command -v shasum >/dev/null 2>&1; then
      _uv_actual=$(shasum -a 256 "$_uv_tmp" | awk '{print $1}')
    elif command -v sha256sum >/dev/null 2>&1; then
      _uv_actual=$(sha256sum "$_uv_tmp" | awk '{print $1}')
    fi

    if [ "$_uv_actual" != "$UV_SHA256" ]; then
      warn "uv installer SHA-256 mismatch — aborting to prevent tampered-installer execution."
      warn "  expected: $UV_SHA256"
      warn "  got:      $_uv_actual"
      warn "Manual fix: install Python 3.9+ from https://www.python.org/downloads/ then reload."
      rm -f "$_uv_tmp"
      exit 0
    fi

    if ! sh "$_uv_tmp" >>/tmp/asucb-uv-install.log 2>&1; then
      rm -f "$_uv_tmp"
      warn "uv install failed. Details: /tmp/asucb-uv-install.log"
      warn "Manual fix: install Python 3.9+ from https://www.python.org/downloads/ then reload."
      exit 0
    fi
    rm -f "$_uv_tmp"
    if [ -x "$HOME/.local/bin/uv" ]; then
      UV_BIN="$HOME/.local/bin/uv"
    elif command -v uv >/dev/null 2>&1; then
      UV_BIN=$(command -v uv)
    else
      warn "uv installed but not found on PATH. Expected at ~/.local/bin/uv."
      exit 0
    fi
  fi

  log "Provisioning Python 3.12 via uv..."
  if ! "$UV_BIN" python install 3.12 >/tmp/asucb-uv-py.log 2>&1; then
    warn "uv python install failed. Details: /tmp/asucb-uv-py.log"
    exit 0
  fi
  # Resolve the installed interpreter path
  MANAGED_PY=$("$UV_BIN" python find 3.12 2>/dev/null || true)
  if [ -z "$MANAGED_PY" ] || [ ! -x "$MANAGED_PY" ]; then
    warn "Could not locate uv-managed Python 3.12."
    exit 0
  fi
  SYSTEM_PY="$MANAGED_PY"
fi

# --- create/refresh venv using selected Python ---
NEED_VENV=0
if [ ! -x "${VENV}/bin/python3" ]; then
  NEED_VENV=1
fi

if [ "$NEED_VENV" = "1" ]; then
  log "Creating plugin virtualenv at ${VENV}..."
  if ! "$SYSTEM_PY" -m venv "$VENV" >/tmp/asucb-venv.log 2>&1; then
    # venv module may be missing on some system pythons; try ensurepip
    if ! "$SYSTEM_PY" -m venv --without-pip "$VENV" >>/tmp/asucb-venv.log 2>&1; then
      warn "venv creation failed. Details: /tmp/asucb-venv.log"
      warn "Falling back to --user pip install with system Python."
      # Fallback to prior flow: --user install
      if ! "$SYSTEM_PY" -m pip install --user --quiet --disable-pip-version-check -r "$REQ" 2>/tmp/asucb-pip.log; then
        "$SYSTEM_PY" -m pip install --user --break-system-packages --quiet --disable-pip-version-check -r "$REQ" 2>>/tmp/asucb-pip.log || {
          warn "pip install failed. Details: /tmp/asucb-pip.log"
          exit 0
        }
      fi
      echo "$HASH" >"$MARKER"
      exit 0
    fi
    # Bootstrap pip in venv
    "${VENV}/bin/python3" -m ensurepip --upgrade >>/tmp/asucb-venv.log 2>&1 || true
  fi
fi

# --- install deps into venv ---
log "Installing Python dependencies..."
if ! "${VENV}/bin/python3" -m pip install --quiet --disable-pip-version-check --upgrade pip >/tmp/asucb-pip.log 2>&1; then
  : # non-fatal
fi
if ! "${VENV}/bin/python3" -m pip install --quiet --disable-pip-version-check -r "$REQ" 2>>/tmp/asucb-pip.log; then
  warn "pip install failed. Details: /tmp/asucb-pip.log"
  exit 0
fi

# --- write wrapper + marker ---
echo "${VENV}/bin/python3" >"$PYBIN_FILE"

cat >"${BIN_DIR}/python3" <<'WRAP'
#!/usr/bin/env bash
# Plugin-provided Python wrapper. Resolves to the managed venv when present.
HERE="$(cd "$(dirname "$0")" && pwd)"
PLUGIN_ROOT="$(cd "${HERE}/.." && pwd)"
if [ -f "${PLUGIN_ROOT}/.python-bin" ]; then
  PYBIN="$(cat "${PLUGIN_ROOT}/.python-bin")"
  if [ -x "$PYBIN" ]; then
    exec "$PYBIN" "$@"
  fi
fi
exec python3 "$@"
WRAP
chmod +x "${BIN_DIR}/python3"
ln -sf python3 "${BIN_DIR}/python" 2>/dev/null || true

echo "$HASH" >"$MARKER"
log "Dependencies ready. Plugin Python: ${VENV}/bin/python3"
exit 0
